@kenkaiiii/ggcoder 5.26.1 → 5.26.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/app-sidecar.js +123 -53
  2. package/dist/app-sidecar.js.map +1 -1
  3. package/dist/core/agent-session-marker-anchors.test.js +181 -2
  4. package/dist/core/agent-session-marker-anchors.test.js.map +1 -1
  5. package/dist/core/agent-session-queue.test.js +65 -0
  6. package/dist/core/agent-session-queue.test.js.map +1 -1
  7. package/dist/core/agent-session-slash-restore.test.d.ts +2 -0
  8. package/dist/core/agent-session-slash-restore.test.d.ts.map +1 -0
  9. package/dist/core/agent-session-slash-restore.test.js +121 -0
  10. package/dist/core/agent-session-slash-restore.test.js.map +1 -0
  11. package/dist/core/agent-session.d.ts +37 -0
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +126 -31
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/compaction/compactor.d.ts +21 -0
  16. package/dist/core/compaction/compactor.d.ts.map +1 -1
  17. package/dist/core/compaction/compactor.js +16 -0
  18. package/dist/core/compaction/compactor.js.map +1 -1
  19. package/dist/core/compaction/compactor.test.js +91 -0
  20. package/dist/core/compaction/compactor.test.js.map +1 -1
  21. package/dist/core/event-bus.d.ts +7 -0
  22. package/dist/core/event-bus.d.ts.map +1 -1
  23. package/dist/core/event-bus.js.map +1 -1
  24. package/dist/core/run-claim.d.ts +37 -0
  25. package/dist/core/run-claim.d.ts.map +1 -0
  26. package/dist/core/run-claim.js +46 -0
  27. package/dist/core/run-claim.js.map +1 -0
  28. package/dist/core/run-claim.test.d.ts +2 -0
  29. package/dist/core/run-claim.test.d.ts.map +1 -0
  30. package/dist/core/run-claim.test.js +107 -0
  31. package/dist/core/run-claim.test.js.map +1 -0
  32. package/dist/core/session-history.d.ts +61 -4
  33. package/dist/core/session-history.d.ts.map +1 -1
  34. package/dist/core/session-history.js +144 -15
  35. package/dist/core/session-history.js.map +1 -1
  36. package/dist/core/session-history.test.js +50 -1
  37. package/dist/core/session-history.test.js.map +1 -1
  38. package/dist/core/session-manager.d.ts +30 -5
  39. package/dist/core/session-manager.d.ts.map +1 -1
  40. package/dist/core/session-manager.js +37 -9
  41. package/dist/core/session-manager.js.map +1 -1
  42. package/dist/core/session-manager.test.js +14 -2
  43. package/dist/core/session-manager.test.js.map +1 -1
  44. package/package.json +4 -4
@@ -0,0 +1,107 @@
1
+ /**
2
+ * The concurrency property the sidecar's `/prompt` handler depends on: two
3
+ * prompts arriving back-to-back must produce ONE run plus one queued message,
4
+ * never two concurrent runs against the same session.
5
+ */
6
+ import { describe, expect, it } from "vitest";
7
+ import { RunClaim } from "./run-claim.js";
8
+ describe("RunClaim", () => {
9
+ it("grants the first claim", () => {
10
+ const claim = new RunClaim();
11
+ expect(claim.claim()).toBe(true);
12
+ expect(claim.active).toBe(true);
13
+ });
14
+ it("refuses a second claim while one is held", () => {
15
+ const claim = new RunClaim();
16
+ claim.claim();
17
+ expect(claim.claim()).toBe(false);
18
+ });
19
+ it("grants again after release", () => {
20
+ const claim = new RunClaim();
21
+ claim.claim();
22
+ claim.release();
23
+ expect(claim.active).toBe(false);
24
+ expect(claim.claim()).toBe(true);
25
+ });
26
+ it("tolerates release without a claim, so it can sit in a finally", () => {
27
+ const claim = new RunClaim();
28
+ expect(() => claim.release()).not.toThrow();
29
+ expect(claim.active).toBe(false);
30
+ });
31
+ });
32
+ /**
33
+ * Reproduces the `/prompt` handler's control flow: check the guard, then await
34
+ * before the run actually starts and flips `running`. The awaits stand in for
35
+ * attachment preparation and `loadWorkflowCommandSpecs()`.
36
+ */
37
+ describe("concurrent POST /prompt", () => {
38
+ function makeHarness(useClaim) {
39
+ let running = false;
40
+ let concurrent = 0;
41
+ const claim = new RunClaim();
42
+ const h = { started: [], queued: [], maxConcurrent: 0, post: async () => { } };
43
+ // Mirrors runAgent: `running` only becomes true once the run begins.
44
+ const runAgent = async (text) => {
45
+ running = true;
46
+ concurrent += 1;
47
+ h.maxConcurrent = Math.max(h.maxConcurrent, concurrent);
48
+ h.started.push(text);
49
+ await new Promise((resolve) => setTimeout(resolve, 5));
50
+ concurrent -= 1;
51
+ running = false;
52
+ };
53
+ h.post = async (text) => {
54
+ let claimed = false;
55
+ try {
56
+ if (running || (useClaim && claim.active)) {
57
+ h.queued.push(text);
58
+ return;
59
+ }
60
+ if (useClaim)
61
+ claimed = claim.claim();
62
+ // The yield that opens the race: `running` is still false here.
63
+ await Promise.resolve();
64
+ await new Promise((resolve) => setTimeout(resolve, 0));
65
+ await runAgent(text);
66
+ }
67
+ finally {
68
+ if (claimed)
69
+ claim.release();
70
+ }
71
+ };
72
+ return h;
73
+ }
74
+ it("queues the second prompt instead of running it concurrently", async () => {
75
+ const h = makeHarness(true);
76
+ await Promise.all([h.post("first"), h.post("second")]);
77
+ expect(h.started).toEqual(["first"]);
78
+ expect(h.queued).toEqual(["second"]);
79
+ expect(h.maxConcurrent).toBe(1);
80
+ });
81
+ it("holds across several simultaneous prompts", async () => {
82
+ const h = makeHarness(true);
83
+ await Promise.all([h.post("a"), h.post("b"), h.post("c"), h.post("d")]);
84
+ expect(h.started).toEqual(["a"]);
85
+ expect(h.queued).toEqual(["b", "c", "d"]);
86
+ expect(h.maxConcurrent).toBe(1);
87
+ });
88
+ it("frees the claim so a later prompt still starts its own run", async () => {
89
+ const h = makeHarness(true);
90
+ await Promise.all([h.post("first"), h.post("second")]);
91
+ await h.post("third");
92
+ expect(h.started).toEqual(["first", "third"]);
93
+ expect(h.maxConcurrent).toBe(1);
94
+ });
95
+ it("demonstrates the bug without the claim", async () => {
96
+ // Guarding on `running` alone lets both prompts through, because neither
97
+ // has reached runAgent when the other checks. This is the regression the
98
+ // claim prevents; if this ever stops failing, the harness has drifted from
99
+ // the handler it models.
100
+ const h = makeHarness(false);
101
+ await Promise.all([h.post("first"), h.post("second")]);
102
+ expect(h.started).toEqual(["first", "second"]);
103
+ expect(h.queued).toEqual([]);
104
+ expect(h.maxConcurrent).toBe(2);
105
+ });
106
+ });
107
+ //# sourceMappingURL=run-claim.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-claim.test.js","sourceRoot":"","sources":["../../src/core/run-claim.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,28 @@
1
1
  import type { Message } from "@kenkaiiii/gg-ai";
2
+ import type { CompactionAnchorRemap } from "./compaction/compactor.js";
2
3
  import type { AutopilotMarkerPayload, AppMarkerPayload, KenTurnPayload } from "./session-manager.js";
4
+ /**
5
+ * Move a transcript anchor (`afterMessageCount`) from the pre-compaction
6
+ * message list onto the compacted one.
7
+ *
8
+ * Compaction folds the leading `summarizedCount` non-system messages into a
9
+ * `prefixCount`-message summary block and keeps the rest verbatim. Anchors
10
+ * inside the collapsed region land right after the summary (their surrounding
11
+ * conversation no longer exists); anchors in the retained tail shift by the
12
+ * difference. Without this, re-persisted markers keep indices from a much
13
+ * longer transcript — they then replay far too late, or past the end, which is
14
+ * what bunches old Ken bubbles and error rows at the bottom on resume.
15
+ */
16
+ export declare function remapAnchorForCompaction(anchor: number, remap: CompactionAnchorRemap): number;
17
+ /**
18
+ * Drop the read-only file-order position before writing a marker back to disk.
19
+ * It describes where a marker sat in the file it was READ from, so persisting
20
+ * it into a rewritten file would bake in a position that no longer applies —
21
+ * the next load recomputes it anyway.
22
+ */
23
+ export declare function stripRecordedPosition<T extends {
24
+ recordedAfterMessageCount?: number;
25
+ }>(payload: T): Omit<T, "recordedAfterMessageCount">;
3
26
  export interface HistoryAutopilotMarker extends AutopilotMarkerPayload {
4
27
  /** Stable seed derived from persisted marker data for deterministic UI copy. */
5
28
  copySeed: string;
@@ -8,10 +31,11 @@ export declare function autopilotMarkerCopySeed(marker: AutopilotMarkerPayload):
8
31
  /**
9
32
  * Normalize persisted autopilot markers for transcript replay.
10
33
  *
11
- * Older compacted/continued sessions may carry markers whose original
12
- * `afterMessageCount` points beyond the restored message list. Replaying those
13
- * at EOF bunches old Ken all-clear bubbles at the bottom, so drop them. Also
14
- * dedupe exact marker payloads produced by old rewrite/re-persist paths.
34
+ * Stale anchors are pulled back to where the marker was actually written (see
35
+ * {@link resolveAnchor}); anything still outside the restored transcript is
36
+ * dropped rather than replayed at EOF, which is what bunched old Ken all-clear
37
+ * bubbles at the bottom. Exact duplicate payloads from old rewrite/re-persist
38
+ * paths are deduped.
15
39
  */
16
40
  export declare function normalizeAutopilotMarkersForHistory(markers: readonly AutopilotMarkerPayload[], maxAfterMessageCount: number): HistoryAutopilotMarker[];
17
41
  /**
@@ -37,9 +61,42 @@ export interface RestoredUserRow {
37
61
  /** True when the message carried a video the model could NOT watch natively
38
62
  * (live showed an info row after the bubble). */
39
63
  videoWarning: boolean;
64
+ /** True when autopilot injected this turn (the message carried the
65
+ * situational-awareness preamble). No human typed it, and the live
66
+ * transcript showed NO user bubble for it — only the Ken-tinted autopilot
67
+ * marker. Resume must skip the row, or the injected body renders twice:
68
+ * once styled as Ken's marker, once raw as a user message. */
69
+ autopilotInjected: boolean;
40
70
  }
41
71
  /** Rebuild the live user bubble from a persisted user message's content. */
42
72
  export declare function restoreUserRow(content: Message["content"]): RestoredUserRow;
73
+ /**
74
+ * Reverse a prompt-template command's expansion by matching the restored body
75
+ * against the known templates.
76
+ *
77
+ * Best-effort only: it works while a template is byte-identical to the one that
78
+ * produced the message, and templates drift (edited `.gg/commands/*.md`,
79
+ * reworded built-ins, app-vs-CLI phrasing). Prefer the invocation recorded at
80
+ * send time — see {@link resolveRestoredCommand}. Returns null when the text
81
+ * isn't a known command body (an ordinary user message).
82
+ */
83
+ export declare function detectPromptCommand(text: string, candidates: ReadonlyArray<{
84
+ name: string;
85
+ prompt: string;
86
+ }>): string | null;
87
+ /**
88
+ * The `/name [args]` chip a restored user row should show, or null for an
89
+ * ordinary message.
90
+ *
91
+ * The invocation persisted with the prompt wins: it's exactly what the user
92
+ * typed and survives any later template edit. Sessions recorded before that was
93
+ * persisted fall back to matching the expanded body, which is why an edited
94
+ * command used to resume as its raw multi-KB template.
95
+ */
96
+ export declare function resolveRestoredCommand(persistedCommand: string | null | undefined, text: string, candidates: ReadonlyArray<{
97
+ name: string;
98
+ prompt: string;
99
+ }>): string | null;
43
100
  /**
44
101
  * Split a persisted assistant message into per-bubble texts. Live streaming
45
102
  * ends the assistant bubble at every server_tool_call (see useAgentEvents'
@@ -1 +1 @@
1
- {"version":3,"file":"session-history.d.ts","sourceRoot":"","sources":["../../src/core/session-history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAI9B,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAWD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAE9E;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,oBAAoB,EAAE,MAAM,GAC3B,sBAAsB,EAAE,CAa1B;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,oBAAoB,EAAE,MAAM,GAC3B,gBAAgB,EAAE,CAepB;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,oBAAoB,EAAE,MAAM,GAC3B,cAAc,EAAE,CAclB;AAmBD,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;sDACkD;IAClD,YAAY,EAAE,OAAO,CAAC;CACvB;AAuBD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,eAAe,CAwB3E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,CAK3E"}
1
+ {"version":3,"file":"session-history.d.ts","sourceRoot":"","sources":["../../src/core/session-history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACf,MAAM,sBAAsB,CAAC;AAI9B;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAQ7F;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,yBAAyB,CAAC,EAAE,MAAM,CAAA;CAAE,EACpF,OAAO,EAAE,CAAC,GACT,IAAI,CAAC,CAAC,EAAE,2BAA2B,CAAC,CAGtC;AAED,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;CAClB;AAWD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAE9E;AAuCD;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,SAAS,sBAAsB,EAAE,EAC1C,oBAAoB,EAAE,MAAM,GAC3B,sBAAsB,EAAE,CAoB1B;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,oBAAoB,EAAE,MAAM,GAC3B,gBAAgB,EAAE,CAoBpB;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,oBAAoB,EAAE,MAAM,GAC3B,cAAc,EAAE,CAelB;AAmBD,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;sDACkD;IAClD,YAAY,EAAE,OAAO,CAAC;IACtB;;;;mEAI+D;IAC/D,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AA8BD,4EAA4E;AAC5E,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,eAAe,CA6B3E;AAUD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1D,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GAC1D,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,CAK3E"}
@@ -1,5 +1,35 @@
1
1
  import { STEERING_PREFIX } from "./steering.js";
2
2
  import { AUTOPILOT_INJECTION_PREAMBLE } from "./autopilot-cycle.js";
3
+ /**
4
+ * Move a transcript anchor (`afterMessageCount`) from the pre-compaction
5
+ * message list onto the compacted one.
6
+ *
7
+ * Compaction folds the leading `summarizedCount` non-system messages into a
8
+ * `prefixCount`-message summary block and keeps the rest verbatim. Anchors
9
+ * inside the collapsed region land right after the summary (their surrounding
10
+ * conversation no longer exists); anchors in the retained tail shift by the
11
+ * difference. Without this, re-persisted markers keep indices from a much
12
+ * longer transcript — they then replay far too late, or past the end, which is
13
+ * what bunches old Ken bubbles and error rows at the bottom on resume.
14
+ */
15
+ export function remapAnchorForCompaction(anchor, remap) {
16
+ const moved = anchor <= remap.summarizedCount
17
+ ? Math.min(anchor, remap.prefixCount)
18
+ : anchor - remap.summarizedCount + remap.prefixCount;
19
+ // The retained tail can be shorter than the collapse implies (tool-pairing
20
+ // repair, trailing-assistant pop), so clamp to the real end of the new list.
21
+ return Math.min(moved, remap.newNonSystemCount);
22
+ }
23
+ /**
24
+ * Drop the read-only file-order position before writing a marker back to disk.
25
+ * It describes where a marker sat in the file it was READ from, so persisting
26
+ * it into a rewritten file would bake in a position that no longer applies —
27
+ * the next load recomputes it anyway.
28
+ */
29
+ export function stripRecordedPosition(payload) {
30
+ const { recordedAfterMessageCount: _ignored, ...rest } = payload;
31
+ return rest;
32
+ }
3
33
  function markerKey(marker) {
4
34
  return JSON.stringify({
5
35
  phase: marker.phase,
@@ -11,25 +41,64 @@ function markerKey(marker) {
11
41
  export function autopilotMarkerCopySeed(marker) {
12
42
  return `${marker.phase}\0${marker.afterMessageCount}\0${marker.reason ?? ""}\0${marker.body ?? ""}`;
13
43
  }
44
+ /**
45
+ * Resolve the replay position for one persisted marker.
46
+ *
47
+ * A marker's anchor counts messages that were ALREADY on disk when it was
48
+ * recorded, and markers are appended after those messages — so a correctly
49
+ * written marker can never sit at a file position lower than its own anchor.
50
+ * File order is therefore a hard ceiling, and an anchor above it is provably
51
+ * stale. Two historical paths produced exactly that:
52
+ *
53
+ * - compaction re-persisted markers into the continuation file while they
54
+ * still carried indices from the much longer pre-compaction transcript;
55
+ * - older sessions anchored against the in-memory message list, which runs
56
+ * ahead of the file whenever a run fails before its messages are flushed.
57
+ *
58
+ * Both make markers replay far too late — bunched at the bottom of a reopened
59
+ * session, or dropped entirely when the anchor overshoots the end. Clamping to
60
+ * the file position fixes both. The clamp only ever moves an anchor DOWN;
61
+ * markers written before their messages landed (fire-and-forget persistence)
62
+ * legitimately sit below their file position and are left alone.
63
+ *
64
+ * `ceilingOffset` covers markers deliberately anchored ahead of the file — the
65
+ * user_hint that attaches to the user message a prompt is about to push.
66
+ * Returns null when even the clamped anchor falls outside the transcript.
67
+ */
68
+ function resolveAnchor(marker, maxAfterMessageCount, ceilingOffset = 0) {
69
+ const ceiling = marker.recordedAfterMessageCount === undefined
70
+ ? Number.POSITIVE_INFINITY
71
+ : marker.recordedAfterMessageCount + ceilingOffset;
72
+ const anchor = Math.min(marker.afterMessageCount, ceiling);
73
+ return anchor <= maxAfterMessageCount ? anchor : null;
74
+ }
14
75
  /**
15
76
  * Normalize persisted autopilot markers for transcript replay.
16
77
  *
17
- * Older compacted/continued sessions may carry markers whose original
18
- * `afterMessageCount` points beyond the restored message list. Replaying those
19
- * at EOF bunches old Ken all-clear bubbles at the bottom, so drop them. Also
20
- * dedupe exact marker payloads produced by old rewrite/re-persist paths.
78
+ * Stale anchors are pulled back to where the marker was actually written (see
79
+ * {@link resolveAnchor}); anything still outside the restored transcript is
80
+ * dropped rather than replayed at EOF, which is what bunched old Ken all-clear
81
+ * bubbles at the bottom. Exact duplicate payloads from old rewrite/re-persist
82
+ * paths are deduped.
21
83
  */
22
84
  export function normalizeAutopilotMarkersForHistory(markers, maxAfterMessageCount) {
23
85
  const seen = new Set();
24
86
  const normalized = [];
25
87
  for (const marker of markers) {
26
- if (marker.afterMessageCount > maxAfterMessageCount)
88
+ const anchor = resolveAnchor(marker, maxAfterMessageCount);
89
+ if (anchor === null)
27
90
  continue;
28
91
  const key = markerKey(marker);
29
92
  if (seen.has(key))
30
93
  continue;
31
94
  seen.add(key);
32
- normalized.push({ ...marker, copySeed: autopilotMarkerCopySeed(marker) });
95
+ // The copy seed stays tied to the PERSISTED anchor so the all-clear wording
96
+ // a resumed session shows matches the one the live run broadcast.
97
+ normalized.push({
98
+ ...marker,
99
+ afterMessageCount: anchor,
100
+ copySeed: autopilotMarkerCopySeed(marker),
101
+ });
33
102
  }
34
103
  return normalized;
35
104
  }
@@ -43,7 +112,10 @@ export function normalizeAppMarkersForHistory(markers, maxAfterMessageCount) {
43
112
  const seen = new Set();
44
113
  const normalized = [];
45
114
  for (const marker of markers) {
46
- if (marker.afterMessageCount > maxAfterMessageCount)
115
+ // user_hint is anchored +1 on purpose so it decorates the user row a prompt
116
+ // is about to add; everything else must not exceed its file position.
117
+ const anchor = resolveAnchor(marker, maxAfterMessageCount, marker.kind === "user_hint" ? 1 : 0);
118
+ if (anchor === null)
47
119
  continue;
48
120
  const key = JSON.stringify({
49
121
  kind: marker.kind,
@@ -53,7 +125,7 @@ export function normalizeAppMarkersForHistory(markers, maxAfterMessageCount) {
53
125
  if (seen.has(key))
54
126
  continue;
55
127
  seen.add(key);
56
- normalized.push(marker);
128
+ normalized.push(anchor === marker.afterMessageCount ? marker : { ...marker, afterMessageCount: anchor });
57
129
  }
58
130
  return normalized;
59
131
  }
@@ -72,9 +144,10 @@ export function normalizeKenTurnsForHistory(turns, maxAfterMessageCount) {
72
144
  if (seen.has(key))
73
145
  continue;
74
146
  seen.add(key);
75
- normalized.push(turn.afterMessageCount > maxAfterMessageCount
76
- ? { ...turn, afterMessageCount: maxAfterMessageCount }
77
- : turn);
147
+ // File order first, EOF clamp only as a last resort — clamping is exactly
148
+ // what stacked resumed Ken exchanges at the bottom of the transcript.
149
+ const anchor = resolveAnchor(turn, maxAfterMessageCount) ?? maxAfterMessageCount;
150
+ normalized.push(anchor === turn.afterMessageCount ? turn : { ...turn, afterMessageCount: anchor });
78
151
  }
79
152
  return normalized;
80
153
  }
@@ -101,10 +174,16 @@ function stripSteering(text) {
101
174
  * on resume the raw session message must render the same clean instruction, not
102
175
  * the machine-facing preamble. */
103
176
  function stripAutopilotPreamble(text) {
104
- return text.startsWith(AUTOPILOT_INJECTION_PREAMBLE)
177
+ return hasAutopilotPreamble(text)
105
178
  ? text.slice(AUTOPILOT_INJECTION_PREAMBLE.length).trimStart()
106
179
  : text;
107
180
  }
181
+ /** Whether a persisted user message was injected by autopilot rather than typed
182
+ * by a human. frameAutopilotInjection adds this preamble to every injected
183
+ * build run, and nothing else produces it. */
184
+ function hasAutopilotPreamble(text) {
185
+ return text.startsWith(AUTOPILOT_INJECTION_PREAMBLE);
186
+ }
108
187
  function stripAttachedFilesBlock(text) {
109
188
  if (text.startsWith(ATTACHED_FILES_HEADER))
110
189
  return "";
@@ -114,15 +193,18 @@ function stripAttachedFilesBlock(text) {
114
193
  /** Rebuild the live user bubble from a persisted user message's content. */
115
194
  export function restoreUserRow(content) {
116
195
  if (typeof content === "string") {
196
+ const unsteered = stripSteering(content);
117
197
  return {
118
- text: stripAttachedFilesBlock(stripAutopilotPreamble(stripSteering(content))).trim(),
198
+ text: stripAttachedFilesBlock(stripAutopilotPreamble(unsteered)).trim(),
119
199
  images: [],
120
200
  videoWarning: false,
201
+ autopilotInjected: hasAutopilotPreamble(unsteered),
121
202
  };
122
203
  }
123
204
  const images = [];
124
205
  const textParts = [];
125
206
  let videoWarning = false;
207
+ let autopilotInjected = false;
126
208
  for (const c of content) {
127
209
  if (c.type === "image") {
128
210
  images.push(`data:${c.mediaType};base64,${c.data}`);
@@ -130,7 +212,10 @@ export function restoreUserRow(content) {
130
212
  }
131
213
  if (c.type !== "text" || typeof c.text !== "string")
132
214
  continue;
133
- const stripped = stripAutopilotPreamble(stripSteering(c.text));
215
+ const unsteered = stripSteering(c.text);
216
+ if (hasAutopilotPreamble(unsteered))
217
+ autopilotInjected = true;
218
+ const stripped = stripAutopilotPreamble(unsteered);
134
219
  if (stripped.startsWith("[User attached a video file"))
135
220
  videoWarning = true;
136
221
  if (ATTACHMENT_NOTE_PATTERNS.some((re) => re.test(stripped)))
@@ -139,7 +224,51 @@ export function restoreUserRow(content) {
139
224
  if (cleaned.trim())
140
225
  textParts.push(cleaned);
141
226
  }
142
- return { text: textParts.join("\n\n").trim(), images, videoWarning };
227
+ return { text: textParts.join("\n\n").trim(), images, videoWarning, autopilotInjected };
228
+ }
229
+ // ── Slash-command reconstruction ──────────────────────────────
230
+ // A `/name` command is expanded before it reaches the model, so the persisted
231
+ // user message is the FULL template body — not the short chip the user saw.
232
+ /** Separator AgentSession.prompt() inserts between a command's prompt body and
233
+ * the user's trailing args. Must stay in sync with the expansion there. */
234
+ const COMMAND_ARGS_SEP = "\n\n## User Instructions\n\n";
235
+ /**
236
+ * Reverse a prompt-template command's expansion by matching the restored body
237
+ * against the known templates.
238
+ *
239
+ * Best-effort only: it works while a template is byte-identical to the one that
240
+ * produced the message, and templates drift (edited `.gg/commands/*.md`,
241
+ * reworded built-ins, app-vs-CLI phrasing). Prefer the invocation recorded at
242
+ * send time — see {@link resolveRestoredCommand}. Returns null when the text
243
+ * isn't a known command body (an ordinary user message).
244
+ */
245
+ export function detectPromptCommand(text, candidates) {
246
+ for (const c of candidates) {
247
+ if (!c.prompt)
248
+ continue;
249
+ if (text === c.prompt)
250
+ return `/${c.name}`;
251
+ if (text.startsWith(c.prompt + COMMAND_ARGS_SEP)) {
252
+ const args = text.slice(c.prompt.length + COMMAND_ARGS_SEP.length).trim();
253
+ return args ? `/${c.name} ${args}` : `/${c.name}`;
254
+ }
255
+ }
256
+ return null;
257
+ }
258
+ /**
259
+ * The `/name [args]` chip a restored user row should show, or null for an
260
+ * ordinary message.
261
+ *
262
+ * The invocation persisted with the prompt wins: it's exactly what the user
263
+ * typed and survives any later template edit. Sessions recorded before that was
264
+ * persisted fall back to matching the expanded body, which is why an edited
265
+ * command used to resume as its raw multi-KB template.
266
+ */
267
+ export function resolveRestoredCommand(persistedCommand, text, candidates) {
268
+ if (typeof persistedCommand === "string" && persistedCommand.trim()) {
269
+ return persistedCommand.trim();
270
+ }
271
+ return detectPromptCommand(text, candidates);
143
272
  }
144
273
  /**
145
274
  * Split a persisted assistant message into per-bubble texts. Live streaming
@@ -1 +1 @@
1
- {"version":3,"file":"session-history.js","sourceRoot":"","sources":["../../src/core/session-history.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-history.js","sourceRoot":"","sources":["../../src/core/session-history.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAc,EAAE,KAA4B;IACnF,MAAM,KAAK,GACT,MAAM,IAAI,KAAK,CAAC,eAAe;QAC7B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC;QACrC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC;IACzD,2EAA2E;IAC3E,6EAA6E;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAU;IAEV,MAAM,EAAE,yBAAyB,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAOD,SAAS,SAAS,CAAC,MAA8B;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,IAAI;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAA8B;IACpE,OAAO,GAAG,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,iBAAiB,KAAK,MAAM,CAAC,MAAM,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;AACtG,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,SAAS,aAAa,CACpB,MAAyE,EACzE,oBAA4B,EAC5B,aAAa,GAAG,CAAC;IAEjB,MAAM,OAAO,GACX,MAAM,CAAC,yBAAyB,KAAK,SAAS;QAC5C,CAAC,CAAC,MAAM,CAAC,iBAAiB;QAC1B,CAAC,CAAC,MAAM,CAAC,yBAAyB,GAAG,aAAa,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;IAC3D,OAAO,MAAM,IAAI,oBAAoB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mCAAmC,CACjD,OAA0C,EAC1C,oBAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAA6B,EAAE,CAAC;IAEhD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;QAC3D,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,4EAA4E;QAC5E,kEAAkE;QAClE,UAAU,CAAC,IAAI,CAAC;YACd,GAAG,MAAM;YACT,iBAAiB,EAAE,MAAM;YACzB,QAAQ,EAAE,uBAAuB,CAAC,MAAM,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,6BAA6B,CAC3C,OAAoC,EACpC,oBAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAuB,EAAE,CAAC;IAC1C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,4EAA4E;QAC5E,sEAAsE;QACtE,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,oBAAoB,EAAE,MAAM,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAChG,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;YACzB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;YAC3C,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAC,CAAC;QACH,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,UAAU,CAAC,IAAI,CACb,MAAM,KAAK,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,CACxF,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAAgC,EAChC,oBAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAqB,EAAE,CAAC;IACxC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC3F,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,0EAA0E;QAC1E,sEAAsE;QACtE,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,oBAAoB,CAAC,IAAI,oBAAoB,CAAC;QACjF,UAAU,CAAC,IAAI,CACb,MAAM,KAAK,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAClF,CAAC;IACJ,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,sEAAsE;AACtE,8EAA8E;AAC9E,0EAA0E;AAC1E,2DAA2D;AAE3D;4DAC4D;AAC5D,MAAM,qBAAqB,GAAG,2CAA2C,CAAC;AAE1E;wCACwC;AACxC,MAAM,wBAAwB,GAAG;IAC/B,0BAA0B;IAC1B,mCAAmC;IACnC,sCAAsC;CACvC,CAAC;AAkBF,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtF,CAAC;AAED;;;;mCAImC;AACnC,SAAS,sBAAsB,CAAC,IAAY;IAC1C,OAAO,oBAAoB,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,4BAA4B,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE;QAC7D,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED;;+CAE+C;AAC/C,SAAS,oBAAoB,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC;QAAE,OAAO,EAAE,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,qBAAqB,EAAE,CAAC,CAAC;IACzD,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,OAA2B;IACxD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO;YACL,IAAI,EAAE,uBAAuB,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE;YACvE,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,KAAK;YACnB,iBAAiB,EAAE,oBAAoB,CAAC,SAAS,CAAC;SACnD,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QAC9D,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,oBAAoB,CAAC,SAAS,CAAC;YAAE,iBAAiB,GAAG,IAAI,CAAC;QAC9D,MAAM,QAAQ,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;QACnD,IAAI,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAAE,YAAY,GAAG,IAAI,CAAC;QAC5E,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAAE,SAAS;QACvE,MAAM,OAAO,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,OAAO,CAAC,IAAI,EAAE;YAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAC1F,CAAC;AAED,iEAAiE;AACjE,8EAA8E;AAC9E,4EAA4E;AAE5E;4EAC4E;AAC5E,MAAM,gBAAgB,GAAG,8BAA8B,CAAC;AAExD;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,UAA2D;IAE3D,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,CAAC,CAAC,MAAM;YAAE,SAAS;QACxB,IAAI,IAAI,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,GAAG,gBAAgB,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,gBAA2C,EAC3C,IAAY,EACZ,UAA2D;IAE3D,IAAI,OAAO,gBAAgB,KAAK,QAAQ,IAAI,gBAAgB,CAAC,IAAI,EAAE,EAAE,CAAC;QACpE,OAAO,gBAAgB,CAAC,IAAI,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA2B;IAC/D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxE,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3B,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CACjF,CAAC;AACJ,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { STEERING_PREFIX } from "./steering.js";
3
3
  import { frameAutopilotInjection } from "./autopilot-cycle.js";
4
- import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeKenTurnsForHistory, restoreUserRow, restoreAssistantTexts, } from "./session-history.js";
4
+ import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeKenTurnsForHistory, restoreUserRow, restoreAssistantTexts, detectPromptCommand, resolveRestoredCommand, } from "./session-history.js";
5
5
  describe("normalizeAutopilotMarkersForHistory", () => {
6
6
  it("drops out-of-range compacted-session markers and dedupes exact all-clear rows", () => {
7
7
  const markers = [
@@ -60,6 +60,22 @@ describe("restoreUserRow", () => {
60
60
  expect(row.text).toBe("Add a test for the login flow.");
61
61
  expect(row.text).not.toContain("[Autopilot]");
62
62
  });
63
+ it("flags autopilot-injected turns so resume can skip the bubble live never showed", () => {
64
+ const injected = restoreUserRow(frameAutopilotInjection("Fix the failing test."));
65
+ expect(injected.autopilotInjected).toBe(true);
66
+ // The same body typed by a human keeps its user bubble.
67
+ expect(restoreUserRow("Fix the failing test.").autopilotInjected).toBe(false);
68
+ });
69
+ it("detects the autopilot preamble under a steering wrapper and in block content", () => {
70
+ const steered = restoreUserRow(`${STEERING_PREFIX}${frameAutopilotInjection("Retry the deploy.")}`);
71
+ expect(steered.autopilotInjected).toBe(true);
72
+ expect(steered.text).toBe("Retry the deploy.");
73
+ const blocks = restoreUserRow([
74
+ { type: "text", text: frameAutopilotInjection("Retry the deploy.") },
75
+ ]);
76
+ expect(blocks.autopilotInjected).toBe(true);
77
+ expect(blocks.text).toBe("Retry the deploy.");
78
+ });
63
79
  it("drops attachment notes and the attached-files block, keeps typed text + images", () => {
64
80
  const row = restoreUserRow([
65
81
  {
@@ -85,6 +101,39 @@ describe("restoreUserRow", () => {
85
101
  expect(row.videoWarning).toBe(true);
86
102
  });
87
103
  });
104
+ describe("resolveRestoredCommand", () => {
105
+ const candidates = [
106
+ { name: "release", prompt: "# Release\n\nShip the thing." },
107
+ { name: "commit", prompt: "# Commit\n\nWrite a commit." },
108
+ ];
109
+ it("reverses an expanded template body back to its /name chip", () => {
110
+ expect(detectPromptCommand("# Release\n\nShip the thing.", candidates)).toBe("/release");
111
+ expect(resolveRestoredCommand(null, "# Release\n\nShip the thing.", candidates)).toBe("/release");
112
+ });
113
+ it("keeps the user's trailing args", () => {
114
+ const body = "# Release\n\nShip the thing.\n\n## User Instructions\n\npatch only";
115
+ expect(resolveRestoredCommand(null, body, candidates)).toBe("/release patch only");
116
+ });
117
+ it("leaves an ordinary message alone", () => {
118
+ expect(resolveRestoredCommand(null, "just a normal question", candidates)).toBeNull();
119
+ });
120
+ // The reported bug: editing a command template (or the app-vs-CLI wording of a
121
+ // built-in) made the body match fail, so reopening the session rendered the
122
+ // whole raw template instead of the `/name` chip.
123
+ it("uses the persisted invocation when the template has drifted since", () => {
124
+ const bodyFromOldTemplate = "# Release\n\nShip the thing the OLD way.";
125
+ // Body matching alone can no longer recognise it.
126
+ expect(detectPromptCommand(bodyFromOldTemplate, candidates)).toBeNull();
127
+ // The invocation recorded at send time still restores the chip.
128
+ expect(resolveRestoredCommand("/release", bodyFromOldTemplate, candidates)).toBe("/release");
129
+ });
130
+ it("prefers the persisted invocation over a body match, args included", () => {
131
+ expect(resolveRestoredCommand("/release patch only", "# Release\n\nShip the thing.", candidates)).toBe("/release patch only");
132
+ });
133
+ it("ignores a blank persisted invocation and falls back to the body", () => {
134
+ expect(resolveRestoredCommand(" ", "# Commit\n\nWrite a commit.", candidates)).toBe("/commit");
135
+ });
136
+ });
88
137
  describe("restoreAssistantTexts", () => {
89
138
  it("keeps server-tool text splits as separate bubbles", () => {
90
139
  expect(restoreAssistantTexts([
@@ -1 +1 @@
1
- {"version":3,"file":"session-history.test.js","sourceRoot":"","sources":["../../src/core/session-history.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-history.test.js","sourceRoot":"","sources":["../../src/core/session-history.test.ts"],"names":[],"mappings":"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"}