Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions windows/src/core/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export interface AgentTask {
state: BotStateName;
stepIndex: number;
steps: string[];
/**
* Position of the newest step in the whole session. `steps` is capped, so
* `stepIndex` stops moving once it is full; this keeps counting.
*/
stepSeq?: number;
source: AgentSource;
isIntegration: boolean;
emote?: BotEmoteName | null;
Expand Down Expand Up @@ -186,9 +191,11 @@ class AppState {
appendStep(id: string, step: string) {
const t = this.tasks.find((x) => x.id === id);
if (!t) return;
const newest = t.stepSeq ?? t.steps.length - 1;
t.steps.push(step);
if (t.steps.length > 20) t.steps.shift();
t.stepIndex = t.steps.length - 1;
t.stepSeq = newest + 1;
this.notify();
}

Expand Down
1 change: 1 addition & 0 deletions windows/src/island/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function clearSession() {
if (!t) return;
t.steps = [];
t.stepIndex = 0;
delete t.stepSeq;
t.name = "VS Code";
t.pillBadge = null;
}
Expand Down
34 changes: 15 additions & 19 deletions windows/src/views/ticker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,27 @@ export class Ticker {
}

sync(task: AgentTask | null) {
const steps = task && task.steps.length > 0 ? task.steps : ["…"];
const idx = task ? Math.min(task.stepIndex, steps.length - 1) : -1;

// First render: drop straight into place, no animation.
if (this.displayIndex < 0) {
this.displayIndex = idx;
setText(this.a, idx > 0 ? steps[idx - 1] : "…");
setText(this.b, steps[Math.max(idx, 0)]);
this.rest();
return;
}

// The session restarted (steps were cleared): re-seed rather than scroll.
if (idx < this.displayIndex) {
const steps = task?.steps ?? [];
// Where the newest step sits in the whole session, not in `steps`: that
// list is capped at 20, and counting inside it made the ticker stop for
// good at the twentieth step of a session.
const newest = steps.length === 0 ? -1 : (task?.stepSeq ?? steps.length - 1);

// First render, or the session restarted (steps were cleared): drop
// straight into place rather than scroll.
if (this.displayIndex < 0 || newest < this.displayIndex) {
this.queue = [];
this.startMs = null;
this.displayIndex = idx;
setText(this.a, idx > 0 ? steps[idx - 1] : "…");
setText(this.b, steps[Math.max(idx, 0)]);
this.displayIndex = newest;
setText(this.a, steps.at(-2) ?? "…");
setText(this.b, steps.at(-1) ?? "…");
this.rest();
return;
}

for (let i = this.displayIndex + 1; i <= idx; i++) this.queue.push(steps[i]);
this.displayIndex = idx;
const fresh = Math.min(newest - this.displayIndex, steps.length);
if (fresh > 0) this.queue.push(...steps.slice(-fresh));
this.displayIndex = newest;
if (this.queue.length > MAX_QUEUE) {
this.queue = this.queue.slice(-MAX_QUEUE);
}
Expand Down