Skip to content

Commit 1fd84c1

Browse files
committed
fix(server): keep sessions idle until submit
1 parent 51a2993 commit 1fd84c1

3 files changed

Lines changed: 16 additions & 22 deletions

File tree

packages/server/src/__tests__/session-integration.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ describe("Session Integration", () => {
883883
expect(sessionMgr.get(sessionId)?.state).toBe("running");
884884
});
885885

886-
it("ignores typing echo but restores running when real PTY output follows", async () => {
886+
it("ignores typing echo and keeps the session idle when PTY output follows without a submit", async () => {
887887
vi.advanceTimersByTime(3050);
888888
expect(sessionMgr.get(sessionId)?.state).toBe("idle");
889889

@@ -907,10 +907,10 @@ describe("Session Integration", () => {
907907
expect(sessionMgr.get(sessionId)?.state).toBe("idle");
908908

909909
triggerDataForProcessIndex(0, "assistant working\n");
910-
expect(sessionMgr.get(sessionId)?.state).toBe("running");
910+
expect(sessionMgr.get(sessionId)?.state).toBe("idle");
911911
});
912912

913-
it("restores running when a recovered PTY stream mixes typing echo with real output", async () => {
913+
it("keeps the session idle when a recovered PTY stream mixes typing echo with output", async () => {
914914
vi.advanceTimersByTime(3050);
915915
expect(sessionMgr.get(sessionId)?.state).toBe("idle");
916916

@@ -931,7 +931,7 @@ describe("Session Integration", () => {
931931
expect(typingResult.ok).toBe(true);
932932

933933
triggerDataForProcessIndex(0, "gassistant working\n");
934-
expect(sessionMgr.get(sessionId)?.state).toBe("running");
934+
expect(sessionMgr.get(sessionId)?.state).toBe("idle");
935935
});
936936
});
937937

packages/server/src/__tests__/session-manager-api.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ describe("SessionManager session-level API", () => {
250250
expect(lifecycleEvents).toEqual([]);
251251
});
252252

253-
it("promotes an idle session back to running when PTY emits real output", async () => {
253+
it("keeps an idle session idle when PTY emits output without a submit", async () => {
254254
vi.useFakeTimers();
255255
provider = {
256256
...provider,
@@ -283,13 +283,13 @@ describe("SessionManager session-level API", () => {
283283
expect(sessionMgr.get(session.id)?.state).toBe("idle");
284284

285285
onData?.("assistant working\n");
286-
expect(sessionMgr.get(session.id)?.state).toBe("running");
286+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
287287

288288
vi.advanceTimersByTime(3000);
289289
expect(sessionMgr.get(session.id)?.state).toBe("idle");
290290
});
291291

292-
it("ignores recent input echo while promoting real PTY output back to running", async () => {
292+
it("keeps an idle session idle even when recent typing echo is followed by PTY output", async () => {
293293
vi.useFakeTimers();
294294
provider = {
295295
...provider,
@@ -328,13 +328,13 @@ describe("SessionManager session-level API", () => {
328328
expect(sessionMgr.get(session.id)?.state).toBe("idle");
329329

330330
onData?.("assistant working\n");
331-
expect(sessionMgr.get(session.id)?.state).toBe("running");
331+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
332332

333333
vi.advanceTimersByTime(3000);
334334
expect(sessionMgr.get(session.id)?.state).toBe("idle");
335335
});
336336

337-
it("restores running when PTY output contains remaining text beyond a recent typing echo", async () => {
337+
it("keeps an idle session idle when PTY output extends beyond a recent typing echo", async () => {
338338
vi.useFakeTimers();
339339
provider = {
340340
...provider,
@@ -373,10 +373,10 @@ describe("SessionManager session-level API", () => {
373373
expect(sessionMgr.get(session.id)?.state).toBe("idle");
374374

375375
onData?.("enerating...\n");
376-
expect(sessionMgr.get(session.id)?.state).toBe("running");
376+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
377377
});
378378

379-
it("restores running when a single PTY chunk mixes typing echo with real output", async () => {
379+
it("keeps an idle session idle when a PTY chunk mixes typing echo with output", async () => {
380380
vi.useFakeTimers();
381381
provider = {
382382
...provider,
@@ -412,7 +412,7 @@ describe("SessionManager session-level API", () => {
412412
expect(sessionMgr.get(session.id)?.state).toBe("idle");
413413

414414
onData?.("gassistant working\n");
415-
expect(sessionMgr.get(session.id)?.state).toBe("running");
415+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
416416

417417
vi.advanceTimersByTime(3000);
418418
expect(sessionMgr.get(session.id)?.state).toBe("idle");
@@ -463,7 +463,7 @@ describe("SessionManager session-level API", () => {
463463
expect(sessionMgr.get(session.id)?.state).toBe("idle");
464464
});
465465

466-
it("restores running when real output follows a typing repaint sequence within the aggregation window", async () => {
466+
it("keeps an idle session idle when PTY output follows a typing repaint sequence", async () => {
467467
vi.useFakeTimers();
468468
provider = {
469469
...provider,
@@ -505,7 +505,7 @@ describe("SessionManager session-level API", () => {
505505
expect(sessionMgr.get(session.id)?.state).toBe("idle");
506506

507507
onData?.("\nassistant working\n");
508-
expect(sessionMgr.get(session.id)?.state).toBe("running");
508+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
509509
});
510510

511511
it("does not restore running for a pure control-triggered line repaint", async () => {
@@ -547,7 +547,7 @@ describe("SessionManager session-level API", () => {
547547
expect(sessionMgr.get(session.id)?.state).toBe("idle");
548548
});
549549

550-
it("restores running when real output arrives after recent control input has aged out", async () => {
550+
it("keeps an idle session idle when PTY output arrives after recent control input has aged out", async () => {
551551
vi.useFakeTimers();
552552
provider = {
553553
...provider,
@@ -584,7 +584,7 @@ describe("SessionManager session-level API", () => {
584584

585585
vi.advanceTimersByTime(250);
586586
onData?.("assistant working\n");
587-
expect(sessionMgr.get(session.id)?.state).toBe("running");
587+
expect(sessionMgr.get(session.id)?.state).toBe("idle");
588588
});
589589

590590
it("emits turn_completed only after an armed submit returns to idle", async () => {

packages/server/src/session/manager.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -938,9 +938,6 @@ export class SessionManager {
938938
if (outputAssessment.countsAsTurnOutput) {
939939
session.sawOutputSinceTurnStart = true;
940940
}
941-
if (outputAssessment.shouldResumeRunning && session.state === "idle") {
942-
this.transitionSessionToRunning(session);
943-
}
944941
}
945942

946943
private schedulePendingResumeAggregation(session: ActiveSession, chunk: Buffer): void {
@@ -1084,9 +1081,6 @@ export class SessionManager {
10841081
if (outputAssessment.countsAsTurnOutput) {
10851082
activeSession.sawOutputSinceTurnStart = true;
10861083
}
1087-
if (outputAssessment.shouldResumeRunning && activeSession.state === "idle") {
1088-
this.transitionSessionToRunning(activeSession);
1089-
}
10901084

10911085
detector.feed(event.chunk);
10921086
});

0 commit comments

Comments
 (0)