@prestyj/cli 5.2.0 → 5.3.1
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.
- package/dist/app-sidecar.js +856 -91
- package/dist/app-sidecar.js.map +1 -1
- package/dist/core/agent-session-compaction.test.js +89 -0
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session-queue.test.d.ts +2 -0
- package/dist/core/agent-session-queue.test.d.ts.map +1 -0
- package/dist/core/agent-session-queue.test.js +122 -0
- package/dist/core/agent-session-queue.test.js.map +1 -0
- package/dist/core/agent-session.d.ts +79 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +268 -47
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autopilot-cycle.d.ts +119 -0
- package/dist/core/autopilot-cycle.d.ts.map +1 -0
- package/dist/core/autopilot-cycle.js +119 -0
- package/dist/core/autopilot-cycle.js.map +1 -0
- package/dist/core/autopilot-cycle.test.d.ts +2 -0
- package/dist/core/autopilot-cycle.test.d.ts.map +1 -0
- package/dist/core/autopilot-cycle.test.js +375 -0
- package/dist/core/autopilot-cycle.test.js.map +1 -0
- package/dist/core/autopilot-gate.d.ts +109 -0
- package/dist/core/autopilot-gate.d.ts.map +1 -0
- package/dist/core/autopilot-gate.js +205 -0
- package/dist/core/autopilot-gate.js.map +1 -0
- package/dist/core/autopilot-gate.test.d.ts +2 -0
- package/dist/core/autopilot-gate.test.d.ts.map +1 -0
- package/dist/core/autopilot-gate.test.js +295 -0
- package/dist/core/autopilot-gate.test.js.map +1 -0
- package/dist/core/autopilot-verdict.d.ts +20 -2
- package/dist/core/autopilot-verdict.d.ts.map +1 -1
- package/dist/core/autopilot-verdict.js +94 -3
- package/dist/core/autopilot-verdict.js.map +1 -1
- package/dist/core/autopilot-verdict.test.js +73 -0
- package/dist/core/autopilot-verdict.test.js.map +1 -1
- package/dist/core/bash-spawn-benchmark.d.ts +2 -0
- package/dist/core/bash-spawn-benchmark.d.ts.map +1 -0
- package/dist/core/bash-spawn-benchmark.js +139 -0
- package/dist/core/bash-spawn-benchmark.js.map +1 -0
- package/dist/core/hashline-edit-benchmark.d.ts +33 -1
- package/dist/core/hashline-edit-benchmark.d.ts.map +1 -1
- package/dist/core/hashline-edit-benchmark.js +193 -21
- package/dist/core/hashline-edit-benchmark.js.map +1 -1
- package/dist/core/hashline-edit-benchmark.test.js +51 -2
- package/dist/core/hashline-edit-benchmark.test.js.map +1 -1
- package/dist/core/json-mode-flag-parity.test.d.ts +2 -0
- package/dist/core/json-mode-flag-parity.test.d.ts.map +1 -0
- package/dist/core/json-mode-flag-parity.test.js +66 -0
- package/dist/core/json-mode-flag-parity.test.js.map +1 -0
- package/dist/core/mcp/deferred-catalog.d.ts +28 -0
- package/dist/core/mcp/deferred-catalog.d.ts.map +1 -0
- package/dist/core/mcp/deferred-catalog.js +72 -0
- package/dist/core/mcp/deferred-catalog.js.map +1 -0
- package/dist/core/mcp/resolve-stdio.d.ts +19 -3
- package/dist/core/mcp/resolve-stdio.d.ts.map +1 -1
- package/dist/core/mcp/resolve-stdio.js +136 -5
- package/dist/core/mcp/resolve-stdio.js.map +1 -1
- package/dist/core/mcp/resolve-stdio.test.js +82 -1
- package/dist/core/mcp/resolve-stdio.test.js.map +1 -1
- package/dist/core/nolan-context.d.ts +43 -2
- package/dist/core/nolan-context.d.ts.map +1 -1
- package/dist/core/nolan-context.js +91 -8
- package/dist/core/nolan-context.js.map +1 -1
- package/dist/core/nolan-context.test.js +167 -5
- package/dist/core/nolan-context.test.js.map +1 -1
- package/dist/core/nolan-model.d.ts +46 -0
- package/dist/core/nolan-model.d.ts.map +1 -0
- package/dist/core/nolan-model.js +30 -0
- package/dist/core/nolan-model.js.map +1 -0
- package/dist/core/nolan-model.test.d.ts +2 -0
- package/dist/core/nolan-model.test.d.ts.map +1 -0
- package/dist/core/nolan-model.test.js +51 -0
- package/dist/core/nolan-model.test.js.map +1 -0
- package/dist/core/nolan-prompt.d.ts +5 -18
- package/dist/core/nolan-prompt.d.ts.map +1 -1
- package/dist/core/nolan-prompt.js +112 -19
- package/dist/core/nolan-prompt.js.map +1 -1
- package/dist/core/nolan-prompt.test.d.ts +2 -0
- package/dist/core/nolan-prompt.test.d.ts.map +1 -0
- package/dist/core/nolan-prompt.test.js +138 -0
- package/dist/core/nolan-prompt.test.js.map +1 -0
- package/dist/core/persistent-shell.d.ts +27 -0
- package/dist/core/persistent-shell.d.ts.map +1 -0
- package/dist/core/persistent-shell.js +150 -0
- package/dist/core/persistent-shell.js.map +1 -0
- package/dist/core/persistent-shell.test.d.ts +2 -0
- package/dist/core/persistent-shell.test.d.ts.map +1 -0
- package/dist/core/persistent-shell.test.js +84 -0
- package/dist/core/persistent-shell.test.js.map +1 -0
- package/dist/core/process-manager-dev-server-repro.test.js +34 -6
- package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
- package/dist/core/progress/engine.d.ts +23 -0
- package/dist/core/progress/engine.d.ts.map +1 -0
- package/dist/core/progress/engine.js +131 -0
- package/dist/core/progress/engine.js.map +1 -0
- package/dist/core/progress/engine.test.d.ts +2 -0
- package/dist/core/progress/engine.test.d.ts.map +1 -0
- package/dist/core/progress/engine.test.js +136 -0
- package/dist/core/progress/engine.test.js.map +1 -0
- package/dist/core/progress/git-xp.d.ts +16 -0
- package/dist/core/progress/git-xp.d.ts.map +1 -0
- package/dist/core/progress/git-xp.js +106 -0
- package/dist/core/progress/git-xp.js.map +1 -0
- package/dist/core/progress/git-xp.test.d.ts +2 -0
- package/dist/core/progress/git-xp.test.d.ts.map +1 -0
- package/dist/core/progress/git-xp.test.js +88 -0
- package/dist/core/progress/git-xp.test.js.map +1 -0
- package/dist/core/progress/ranks.d.ts +21 -0
- package/dist/core/progress/ranks.d.ts.map +1 -0
- package/dist/core/progress/ranks.js +141 -0
- package/dist/core/progress/ranks.js.map +1 -0
- package/dist/core/progress/ranks.test.d.ts +2 -0
- package/dist/core/progress/ranks.test.d.ts.map +1 -0
- package/dist/core/progress/ranks.test.js +59 -0
- package/dist/core/progress/ranks.test.js.map +1 -0
- package/dist/core/progress/rebuild.d.ts +7 -0
- package/dist/core/progress/rebuild.d.ts.map +1 -0
- package/dist/core/progress/rebuild.js +106 -0
- package/dist/core/progress/rebuild.js.map +1 -0
- package/dist/core/progress/rebuild.test.d.ts +2 -0
- package/dist/core/progress/rebuild.test.d.ts.map +1 -0
- package/dist/core/progress/rebuild.test.js +72 -0
- package/dist/core/progress/rebuild.test.js.map +1 -0
- package/dist/core/progress/store.d.ts +35 -0
- package/dist/core/progress/store.d.ts.map +1 -0
- package/dist/core/progress/store.js +200 -0
- package/dist/core/progress/store.js.map +1 -0
- package/dist/core/progress/store.test.d.ts +2 -0
- package/dist/core/progress/store.test.d.ts.map +1 -0
- package/dist/core/progress/store.test.js +108 -0
- package/dist/core/progress/store.test.js.map +1 -0
- package/dist/core/progress/types.d.ts +108 -0
- package/dist/core/progress/types.d.ts.map +1 -0
- package/dist/core/progress/types.js +3 -0
- package/dist/core/progress/types.js.map +1 -0
- package/dist/core/project-discovery.d.ts.map +1 -1
- package/dist/core/project-discovery.js +40 -9
- package/dist/core/project-discovery.js.map +1 -1
- package/dist/core/project-discovery.test.d.ts +2 -0
- package/dist/core/project-discovery.test.d.ts.map +1 -0
- package/dist/core/project-discovery.test.js +104 -0
- package/dist/core/project-discovery.test.js.map +1 -0
- package/dist/core/session-history.d.ts +51 -0
- package/dist/core/session-history.d.ts.map +1 -0
- package/dist/core/session-history.js +156 -0
- package/dist/core/session-history.js.map +1 -0
- package/dist/core/session-history.test.d.ts +2 -0
- package/dist/core/session-history.test.d.ts.map +1 -0
- package/dist/core/session-history.test.js +101 -0
- package/dist/core/session-history.test.js.map +1 -0
- package/dist/core/session-manager.d.ts +34 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +67 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-manager.test.js +140 -1
- package/dist/core/session-manager.test.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +4 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/speed-benchmark.test.js +2 -3
- package/dist/core/speed-benchmark.test.js.map +1 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +12 -8
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +15 -20
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/bash.d.ts +1 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +27 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +9 -2
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +91 -10
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +97 -0
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/plan-mode.test.js +25 -0
- package/dist/tools/plan-mode.test.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +3 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +24 -1
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/tool-search.d.ts +15 -0
- package/dist/tools/tool-search.d.ts.map +1 -0
- package/dist/tools/tool-search.js +35 -0
- package/dist/tools/tool-search.js.map +1 -0
- package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
- package/dist/ui/hooks/useAgentLoop.js +22 -9
- package/dist/ui/hooks/useAgentLoop.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { encodeCwd } from "./encode-cwd.js";
|
|
6
|
+
import { discoverProjects } from "./project-discovery.js";
|
|
7
|
+
// Holder the hoisted mock reads at call time (vi.mock is hoisted above imports,
|
|
8
|
+
// so it can't close over a value assigned later without this indirection).
|
|
9
|
+
const state = { sessionsDir: "" };
|
|
10
|
+
vi.mock("../config.js", async (orig) => {
|
|
11
|
+
const actual = await orig();
|
|
12
|
+
return {
|
|
13
|
+
...actual,
|
|
14
|
+
getAppPaths: () => ({ ...actual.getAppPaths(), sessionsDir: state.sessionsDir }),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
/** Write a minimal ezcoder session file (header + one message) into `dir`. */
|
|
18
|
+
async function writeSession(dir, cwd) {
|
|
19
|
+
await fs.mkdir(dir, { recursive: true });
|
|
20
|
+
const header = JSON.stringify({
|
|
21
|
+
type: "session",
|
|
22
|
+
version: 2,
|
|
23
|
+
id: "11111111-1111-1111-1111-111111111111",
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
cwd,
|
|
26
|
+
provider: "anthropic",
|
|
27
|
+
model: "claude-sonnet-5",
|
|
28
|
+
});
|
|
29
|
+
const message = JSON.stringify({
|
|
30
|
+
type: "message",
|
|
31
|
+
id: "22222222-2222-2222-2222-222222222222",
|
|
32
|
+
timestamp: new Date().toISOString(),
|
|
33
|
+
message: { role: "user", content: "hi" },
|
|
34
|
+
});
|
|
35
|
+
await fs.writeFile(path.join(dir, "session.jsonl"), `${header}\n${message}\n`, "utf-8");
|
|
36
|
+
}
|
|
37
|
+
describe("discoverProjects (ezcoder store)", () => {
|
|
38
|
+
let tmp;
|
|
39
|
+
beforeEach(async () => {
|
|
40
|
+
tmp = await fs.mkdtemp(path.join(os.tmpdir(), "gg-discovery-"));
|
|
41
|
+
state.sessionsDir = path.join(tmp, ".ezcoder", "sessions");
|
|
42
|
+
await fs.mkdir(state.sessionsDir, { recursive: true });
|
|
43
|
+
// Point Claude/Codex discovery at an empty home so they contribute nothing.
|
|
44
|
+
vi.spyOn(os, "homedir").mockReturnValue(path.join(tmp, "home"));
|
|
45
|
+
});
|
|
46
|
+
afterEach(async () => {
|
|
47
|
+
vi.restoreAllMocks();
|
|
48
|
+
await fs.rm(tmp, { recursive: true, force: true });
|
|
49
|
+
});
|
|
50
|
+
it("lists a project whose folder name contains an underscore (regression)", async () => {
|
|
51
|
+
// Real project path with a literal underscore — the lossy slash→underscore
|
|
52
|
+
// decode would resolve this to `.../projects/my/app`, which doesn't exist,
|
|
53
|
+
// so the project used to silently vanish from the picker.
|
|
54
|
+
const projectPath = path.join(tmp, "projects", "my_app");
|
|
55
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
56
|
+
await writeSession(path.join(state.sessionsDir, encodeCwd(projectPath)), projectPath);
|
|
57
|
+
const projects = await discoverProjects();
|
|
58
|
+
const found = projects.find((p) => p.path === projectPath);
|
|
59
|
+
expect(found).toBeDefined();
|
|
60
|
+
expect(found?.name).toBe("my_app");
|
|
61
|
+
expect(found?.sources).toContain("ezcoder");
|
|
62
|
+
// The lossy decode must NOT surface as a phantom project.
|
|
63
|
+
expect(projects.some((p) => p.path === path.join(tmp, "projects", "my", "app"))).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
it("keys the project off the header cwd, not the directory name", async () => {
|
|
66
|
+
// The real cwd lives in the session header; the directory name is only a
|
|
67
|
+
// lossy hint. Prove the header wins by giving the dir an arbitrary name
|
|
68
|
+
// (as happens for a copied/renamed session store) whose underscore-decode
|
|
69
|
+
// would resolve somewhere else entirely — the project must still resolve to
|
|
70
|
+
// the header's true underscore path.
|
|
71
|
+
const projectPath = path.join(tmp, "projects", "my_app");
|
|
72
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
73
|
+
await writeSession(path.join(state.sessionsDir, "arbitrary-store-name"), projectPath);
|
|
74
|
+
const projects = await discoverProjects();
|
|
75
|
+
const found = projects.find((p) => p.path === projectPath);
|
|
76
|
+
expect(found).toBeDefined();
|
|
77
|
+
expect(found?.name).toBe("my_app");
|
|
78
|
+
// The decode of "arbitrary-store-name" (an existing-looking rel path) must
|
|
79
|
+
// not surface as its own phantom project.
|
|
80
|
+
expect(projects.some((p) => p.path.endsWith("arbitrary-store-name"))).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
// The best-effort decode only round-trips for underscore-free absolute paths
|
|
83
|
+
// (that's the whole point of the header fix). macOS's own os.tmpdir() contains
|
|
84
|
+
// a literal underscore, so this test roots its project under posix /tmp to get
|
|
85
|
+
// an underscore-free path; skip on Windows where that root doesn't exist.
|
|
86
|
+
it.skipIf(process.platform === "win32")("falls back to underscore decode when a session file carries no cwd header", async () => {
|
|
87
|
+
const root = await fs.mkdtemp("/tmp/ggfallback-");
|
|
88
|
+
try {
|
|
89
|
+
// Legacy/headerless session dir: no `type:"session"` line. The decode
|
|
90
|
+
// still lists it as long as the decoded path exists on disk.
|
|
91
|
+
const projectPath = path.join(root, "legacy");
|
|
92
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
93
|
+
const dir = path.join(state.sessionsDir, encodeCwd(projectPath));
|
|
94
|
+
await fs.mkdir(dir, { recursive: true });
|
|
95
|
+
await fs.writeFile(path.join(dir, "session.jsonl"), `${JSON.stringify({ type: "message", message: { role: "user", content: "hi" } })}\n`, "utf-8");
|
|
96
|
+
const projects = await discoverProjects();
|
|
97
|
+
expect(projects.find((p) => p.path === projectPath)).toBeDefined();
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=project-discovery.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-discovery.test.js","sourceRoot":"","sources":["../../src/core/project-discovery.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Message } from "@prestyj/ai";
|
|
2
|
+
import type { AutopilotMarkerPayload, AppMarkerPayload, NolanTurnPayload } from "./session-manager.js";
|
|
3
|
+
export interface HistoryAutopilotMarker extends AutopilotMarkerPayload {
|
|
4
|
+
/** Stable seed derived from persisted marker data for deterministic UI copy. */
|
|
5
|
+
copySeed: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function autopilotMarkerCopySeed(marker: AutopilotMarkerPayload): string;
|
|
8
|
+
/**
|
|
9
|
+
* Normalize persisted autopilot markers for transcript replay.
|
|
10
|
+
*
|
|
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 Nolan all-clear bubbles at the bottom, so drop them. Also
|
|
14
|
+
* dedupe exact marker payloads produced by old rewrite/re-persist paths.
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeAutopilotMarkersForHistory(markers: readonly AutopilotMarkerPayload[], maxAfterMessageCount: number): HistoryAutopilotMarker[];
|
|
17
|
+
/**
|
|
18
|
+
* Normalize persisted app transcript markers for replay: drop markers whose
|
|
19
|
+
* anchor points beyond the restored message list (stale after compaction) and
|
|
20
|
+
* dedupe exact payloads (old rewrite paths could re-append). Mirrors
|
|
21
|
+
* {@link normalizeAutopilotMarkersForHistory}.
|
|
22
|
+
*/
|
|
23
|
+
export declare function normalizeAppMarkersForHistory(markers: readonly AppMarkerPayload[], maxAfterMessageCount: number): AppMarkerPayload[];
|
|
24
|
+
/**
|
|
25
|
+
* Normalize persisted Nolan turns for replay. Unlike autopilot/app markers, Nolan
|
|
26
|
+
* turns carry real conversation — an out-of-range anchor (stale after
|
|
27
|
+
* compaction) is CLAMPED to the last message instead of dropped, so the
|
|
28
|
+
* exchange still renders (at the end, in order) rather than vanishing. Exact
|
|
29
|
+
* duplicate payloads (old rewrite/re-persist paths) are deduped.
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeNolanTurnsForHistory(turns: readonly NolanTurnPayload[], maxAfterMessageCount: number): NolanTurnPayload[];
|
|
32
|
+
export interface RestoredUserRow {
|
|
33
|
+
/** The typed text as the live bubble showed it. */
|
|
34
|
+
text: string;
|
|
35
|
+
/** Attached image data URLs. */
|
|
36
|
+
images: string[];
|
|
37
|
+
/** True when the message carried a video the model could NOT watch natively
|
|
38
|
+
* (live showed an info row after the bubble). */
|
|
39
|
+
videoWarning: boolean;
|
|
40
|
+
}
|
|
41
|
+
/** Rebuild the live user bubble from a persisted user message's content. */
|
|
42
|
+
export declare function restoreUserRow(content: Message["content"]): RestoredUserRow;
|
|
43
|
+
/**
|
|
44
|
+
* Split a persisted assistant message into per-bubble texts. Live streaming
|
|
45
|
+
* ends the assistant bubble at every server_tool_call (see useAgentEvents'
|
|
46
|
+
* server_tool_call case), so pre- and post-tool text render as separate rows.
|
|
47
|
+
* Persisted content keeps that structure as separate text blocks — emit one
|
|
48
|
+
* text per block instead of gluing them into a single row on resume.
|
|
49
|
+
*/
|
|
50
|
+
export declare function restoreAssistantTexts(content: Message["content"]): string[];
|
|
51
|
+
//# sourceMappingURL=session-history.d.ts.map
|
|
@@ -0,0 +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,aAAa,CAAC;AAC3C,OAAO,KAAK,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EACjB,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,6BAA6B,CAC3C,KAAK,EAAE,SAAS,gBAAgB,EAAE,EAClC,oBAAoB,EAAE,MAAM,GAC3B,gBAAgB,EAAE,CAcpB;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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { STEERING_PREFIX } from "./steering.js";
|
|
2
|
+
import { AUTOPILOT_INJECTION_PREAMBLE } from "./autopilot-cycle.js";
|
|
3
|
+
function markerKey(marker) {
|
|
4
|
+
return JSON.stringify({
|
|
5
|
+
phase: marker.phase,
|
|
6
|
+
afterMessageCount: marker.afterMessageCount,
|
|
7
|
+
reason: marker.reason ?? null,
|
|
8
|
+
body: marker.body ?? null,
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export function autopilotMarkerCopySeed(marker) {
|
|
12
|
+
return `${marker.phase}\0${marker.afterMessageCount}\0${marker.reason ?? ""}\0${marker.body ?? ""}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Normalize persisted autopilot markers for transcript replay.
|
|
16
|
+
*
|
|
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 Nolan all-clear bubbles at the bottom, so drop them. Also
|
|
20
|
+
* dedupe exact marker payloads produced by old rewrite/re-persist paths.
|
|
21
|
+
*/
|
|
22
|
+
export function normalizeAutopilotMarkersForHistory(markers, maxAfterMessageCount) {
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
const normalized = [];
|
|
25
|
+
for (const marker of markers) {
|
|
26
|
+
if (marker.afterMessageCount > maxAfterMessageCount)
|
|
27
|
+
continue;
|
|
28
|
+
const key = markerKey(marker);
|
|
29
|
+
if (seen.has(key))
|
|
30
|
+
continue;
|
|
31
|
+
seen.add(key);
|
|
32
|
+
normalized.push({ ...marker, copySeed: autopilotMarkerCopySeed(marker) });
|
|
33
|
+
}
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Normalize persisted app transcript markers for replay: drop markers whose
|
|
38
|
+
* anchor points beyond the restored message list (stale after compaction) and
|
|
39
|
+
* dedupe exact payloads (old rewrite paths could re-append). Mirrors
|
|
40
|
+
* {@link normalizeAutopilotMarkersForHistory}.
|
|
41
|
+
*/
|
|
42
|
+
export function normalizeAppMarkersForHistory(markers, maxAfterMessageCount) {
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
const normalized = [];
|
|
45
|
+
for (const marker of markers) {
|
|
46
|
+
if (marker.afterMessageCount > maxAfterMessageCount)
|
|
47
|
+
continue;
|
|
48
|
+
const key = JSON.stringify({
|
|
49
|
+
kind: marker.kind,
|
|
50
|
+
afterMessageCount: marker.afterMessageCount,
|
|
51
|
+
data: marker.data,
|
|
52
|
+
});
|
|
53
|
+
if (seen.has(key))
|
|
54
|
+
continue;
|
|
55
|
+
seen.add(key);
|
|
56
|
+
normalized.push(marker);
|
|
57
|
+
}
|
|
58
|
+
return normalized;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Normalize persisted Nolan turns for replay. Unlike autopilot/app markers, Nolan
|
|
62
|
+
* turns carry real conversation — an out-of-range anchor (stale after
|
|
63
|
+
* compaction) is CLAMPED to the last message instead of dropped, so the
|
|
64
|
+
* exchange still renders (at the end, in order) rather than vanishing. Exact
|
|
65
|
+
* duplicate payloads (old rewrite/re-persist paths) are deduped.
|
|
66
|
+
*/
|
|
67
|
+
export function normalizeNolanTurnsForHistory(turns, maxAfterMessageCount) {
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
const normalized = [];
|
|
70
|
+
for (const turn of turns) {
|
|
71
|
+
const key = JSON.stringify({ q: turn.question, r: turn.reply, a: turn.afterMessageCount });
|
|
72
|
+
if (seen.has(key))
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(key);
|
|
75
|
+
normalized.push(turn.afterMessageCount > maxAfterMessageCount
|
|
76
|
+
? { ...turn, afterMessageCount: maxAfterMessageCount }
|
|
77
|
+
: turn);
|
|
78
|
+
}
|
|
79
|
+
return normalized;
|
|
80
|
+
}
|
|
81
|
+
// ── User-row reconstruction ────────────────────────────────────────
|
|
82
|
+
// The persisted user message is what the MODEL saw — steering wrapper, saved-
|
|
83
|
+
// path notes, attached-files block. The live bubble showed only the typed
|
|
84
|
+
// text, so resume must strip the machine framing back out.
|
|
85
|
+
/** Separator AgentSession.buildAttachmentParts uses before the file-notes
|
|
86
|
+
* block appended to a user message's leading text part. */
|
|
87
|
+
const ATTACHED_FILES_HEADER = "Attached files (inspect with your tools):";
|
|
88
|
+
/** Attachment-note text parts injected alongside the typed text. These never
|
|
89
|
+
* appeared in the live user bubble. */
|
|
90
|
+
const ATTACHMENT_NOTE_PATTERNS = [
|
|
91
|
+
/^\[Image saved at .+\]$/s,
|
|
92
|
+
/^The user attached a video at .+/s,
|
|
93
|
+
/^\[User attached a video file .+\]$/s,
|
|
94
|
+
];
|
|
95
|
+
function stripSteering(text) {
|
|
96
|
+
return text.startsWith(STEERING_PREFIX) ? text.slice(STEERING_PREFIX.length) : text;
|
|
97
|
+
}
|
|
98
|
+
/** Strip the autopilot situational-awareness preamble that the sidecar prepends
|
|
99
|
+
* to every autopilot-injected build-session run (see frameAutopilotInjection).
|
|
100
|
+
* The live transcript shows the clean body via the autopilot "prompted" marker;
|
|
101
|
+
* on resume the raw session message must render the same clean instruction, not
|
|
102
|
+
* the machine-facing preamble. */
|
|
103
|
+
function stripAutopilotPreamble(text) {
|
|
104
|
+
return text.startsWith(AUTOPILOT_INJECTION_PREAMBLE)
|
|
105
|
+
? text.slice(AUTOPILOT_INJECTION_PREAMBLE.length).trimStart()
|
|
106
|
+
: text;
|
|
107
|
+
}
|
|
108
|
+
function stripAttachedFilesBlock(text) {
|
|
109
|
+
if (text.startsWith(ATTACHED_FILES_HEADER))
|
|
110
|
+
return "";
|
|
111
|
+
const idx = text.indexOf(`\n\n${ATTACHED_FILES_HEADER}`);
|
|
112
|
+
return idx === -1 ? text : text.slice(0, idx);
|
|
113
|
+
}
|
|
114
|
+
/** Rebuild the live user bubble from a persisted user message's content. */
|
|
115
|
+
export function restoreUserRow(content) {
|
|
116
|
+
if (typeof content === "string") {
|
|
117
|
+
return {
|
|
118
|
+
text: stripAttachedFilesBlock(stripAutopilotPreamble(stripSteering(content))).trim(),
|
|
119
|
+
images: [],
|
|
120
|
+
videoWarning: false,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const images = [];
|
|
124
|
+
const textParts = [];
|
|
125
|
+
let videoWarning = false;
|
|
126
|
+
for (const c of content) {
|
|
127
|
+
if (c.type === "image") {
|
|
128
|
+
images.push(`data:${c.mediaType};base64,${c.data}`);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (c.type !== "text" || typeof c.text !== "string")
|
|
132
|
+
continue;
|
|
133
|
+
const stripped = stripAutopilotPreamble(stripSteering(c.text));
|
|
134
|
+
if (stripped.startsWith("[User attached a video file"))
|
|
135
|
+
videoWarning = true;
|
|
136
|
+
if (ATTACHMENT_NOTE_PATTERNS.some((re) => re.test(stripped)))
|
|
137
|
+
continue;
|
|
138
|
+
const cleaned = stripAttachedFilesBlock(stripped);
|
|
139
|
+
if (cleaned.trim())
|
|
140
|
+
textParts.push(cleaned);
|
|
141
|
+
}
|
|
142
|
+
return { text: textParts.join("\n\n").trim(), images, videoWarning };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Split a persisted assistant message into per-bubble texts. Live streaming
|
|
146
|
+
* ends the assistant bubble at every server_tool_call (see useAgentEvents'
|
|
147
|
+
* server_tool_call case), so pre- and post-tool text render as separate rows.
|
|
148
|
+
* Persisted content keeps that structure as separate text blocks — emit one
|
|
149
|
+
* text per block instead of gluing them into a single row on resume.
|
|
150
|
+
*/
|
|
151
|
+
export function restoreAssistantTexts(content) {
|
|
152
|
+
if (typeof content === "string")
|
|
153
|
+
return content.trim() ? [content] : [];
|
|
154
|
+
return content.flatMap((c) => c.type === "text" && typeof c.text === "string" && c.text.trim() ? [c.text] : []);
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=session-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-history.js","sourceRoot":"","sources":["../../src/core/session-history.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-history.test.d.ts","sourceRoot":"","sources":["../../src/core/session-history.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { STEERING_PREFIX } from "./steering.js";
|
|
3
|
+
import { frameAutopilotInjection } from "./autopilot-cycle.js";
|
|
4
|
+
import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeNolanTurnsForHistory, restoreUserRow, restoreAssistantTexts, } from "./session-history.js";
|
|
5
|
+
describe("normalizeAutopilotMarkersForHistory", () => {
|
|
6
|
+
it("drops out-of-range compacted-session markers and dedupes exact all-clear rows", () => {
|
|
7
|
+
const markers = [
|
|
8
|
+
{ version: 1, phase: "done", afterMessageCount: 2 },
|
|
9
|
+
{ version: 1, phase: "done", afterMessageCount: 2 },
|
|
10
|
+
{ version: 1, phase: "done", afterMessageCount: 9 },
|
|
11
|
+
{ version: 1, phase: "human", afterMessageCount: 3, reason: "Needs user approval." },
|
|
12
|
+
{ version: 1, phase: "done", afterMessageCount: 12 },
|
|
13
|
+
];
|
|
14
|
+
const restored = normalizeAutopilotMarkersForHistory(markers, 4);
|
|
15
|
+
expect(restored).toEqual([
|
|
16
|
+
{ version: 1, phase: "done", afterMessageCount: 2, copySeed: "done\u00002\u0000\u0000" },
|
|
17
|
+
{
|
|
18
|
+
version: 1,
|
|
19
|
+
phase: "human",
|
|
20
|
+
afterMessageCount: 3,
|
|
21
|
+
reason: "Needs user approval.",
|
|
22
|
+
copySeed: "human\u00003\u0000Needs user approval.\u0000",
|
|
23
|
+
},
|
|
24
|
+
]);
|
|
25
|
+
expect(restored.filter((m) => m.phase === "done")).toHaveLength(1);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe("normalizeAppMarkersForHistory", () => {
|
|
29
|
+
it("drops out-of-range markers and dedupes exact payloads", () => {
|
|
30
|
+
const markers = [
|
|
31
|
+
{ version: 1, kind: "plan", afterMessageCount: 1, data: { reason: "complex change" } },
|
|
32
|
+
{ version: 1, kind: "plan", afterMessageCount: 1, data: { reason: "complex change" } },
|
|
33
|
+
{ version: 1, kind: "task", afterMessageCount: 9, data: { title: "stale task" } },
|
|
34
|
+
];
|
|
35
|
+
expect(normalizeAppMarkersForHistory(markers, 4)).toEqual([
|
|
36
|
+
{ version: 1, kind: "plan", afterMessageCount: 1, data: { reason: "complex change" } },
|
|
37
|
+
]);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe("normalizeNolanTurnsForHistory", () => {
|
|
41
|
+
it("clamps stale anchors to the last message instead of dropping, and dedupes", () => {
|
|
42
|
+
const turns = [
|
|
43
|
+
{ version: 1, question: "why?", reply: "because", afterMessageCount: 2 },
|
|
44
|
+
{ version: 1, question: "why?", reply: "because", afterMessageCount: 2 },
|
|
45
|
+
{ version: 1, question: "later q", reply: "later a", afterMessageCount: 50 },
|
|
46
|
+
];
|
|
47
|
+
expect(normalizeNolanTurnsForHistory(turns, 4)).toEqual([
|
|
48
|
+
{ version: 1, question: "why?", reply: "because", afterMessageCount: 2 },
|
|
49
|
+
{ version: 1, question: "later q", reply: "later a", afterMessageCount: 4 },
|
|
50
|
+
]);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe("restoreUserRow", () => {
|
|
54
|
+
it("strips the mid-run steering wrapper so queued prompts resume clean", () => {
|
|
55
|
+
const row = restoreUserRow(`${STEERING_PREFIX}also add dark mode`);
|
|
56
|
+
expect(row.text).toBe("also add dark mode");
|
|
57
|
+
});
|
|
58
|
+
it("strips the autopilot preamble so injected prompts resume as the clean body", () => {
|
|
59
|
+
const row = restoreUserRow(frameAutopilotInjection("Add a test for the login flow."));
|
|
60
|
+
expect(row.text).toBe("Add a test for the login flow.");
|
|
61
|
+
expect(row.text).not.toContain("[Autopilot]");
|
|
62
|
+
});
|
|
63
|
+
it("drops attachment notes and the attached-files block, keeps typed text + images", () => {
|
|
64
|
+
const row = restoreUserRow([
|
|
65
|
+
{
|
|
66
|
+
type: "text",
|
|
67
|
+
text: "what's in this screenshot?\n\nAttached files (inspect with your tools):\n- notes.txt (saved at /p/notes.txt)",
|
|
68
|
+
},
|
|
69
|
+
{ type: "image", mediaType: "image/png", data: "aGk=" },
|
|
70
|
+
{ type: "text", text: "[Image saved at /p/.gg/uploads/x.png]" },
|
|
71
|
+
]);
|
|
72
|
+
expect(row.text).toBe("what's in this screenshot?");
|
|
73
|
+
expect(row.images).toEqual(["data:image/png;base64,aGk="]);
|
|
74
|
+
expect(row.videoWarning).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it("flags the non-native-video note so resume re-shows the live info row", () => {
|
|
77
|
+
const row = restoreUserRow([
|
|
78
|
+
{ type: "text", text: "summarize this clip" },
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: "[User attached a video file at /p/clip.mp4. You cannot watch video directly; if needed, use ffmpeg to extract frames or audio.]",
|
|
82
|
+
},
|
|
83
|
+
]);
|
|
84
|
+
expect(row.text).toBe("summarize this clip");
|
|
85
|
+
expect(row.videoWarning).toBe(true);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("restoreAssistantTexts", () => {
|
|
89
|
+
it("keeps server-tool text splits as separate bubbles", () => {
|
|
90
|
+
expect(restoreAssistantTexts([
|
|
91
|
+
{ type: "text", text: "Let me search for that." },
|
|
92
|
+
{ type: "server_tool_call", id: "st1", name: "web_search", args: {} },
|
|
93
|
+
{ type: "text", text: "Found it — here's the answer." },
|
|
94
|
+
])).toEqual(["Let me search for that.", "Found it — here's the answer."]);
|
|
95
|
+
});
|
|
96
|
+
it("passes plain string content through as one bubble", () => {
|
|
97
|
+
expect(restoreAssistantTexts("hello")).toEqual(["hello"]);
|
|
98
|
+
expect(restoreAssistantTexts(" ")).toEqual([]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=session-history.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-history.test.js","sourceRoot":"","sources":["../../src/core/session-history.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -49,6 +49,34 @@ export interface NolanTurnPayload {
|
|
|
49
49
|
reply: string;
|
|
50
50
|
afterMessageCount: number;
|
|
51
51
|
}
|
|
52
|
+
/** Custom-entry kind for an autopilot verdict marker. Mirrors `nolan_turn`:
|
|
53
|
+
* persisted as a `custom` entry with `parentId: null` so it's never on the
|
|
54
|
+
* message DAG (EZ Coder never sees it) but survives resume/compaction and
|
|
55
|
+
* interleaves back into the transcript via `afterMessageCount`. Covers all
|
|
56
|
+
* four terminal/near-terminal autopilot markers so a resumed session renders
|
|
57
|
+
* the exact same Nolan bubble the live run showed — never the raw verdict
|
|
58
|
+
* keyword (e.g. `ALL_CLEAR`) the model actually replied with. */
|
|
59
|
+
export declare const AUTOPILOT_MARKER_CUSTOM_KIND = "autopilot_marker";
|
|
60
|
+
export interface AutopilotMarkerPayload {
|
|
61
|
+
version: 1;
|
|
62
|
+
phase: "prompted" | "done" | "human" | "capped" | "plan_approved";
|
|
63
|
+
reason?: string;
|
|
64
|
+
body?: string;
|
|
65
|
+
afterMessageCount: number;
|
|
66
|
+
}
|
|
67
|
+
/** Custom-entry kind for a generic app transcript marker (plan-mode banner,
|
|
68
|
+
* task header, error row, user-bubble display hint). Same not-on-the-DAG
|
|
69
|
+
* treatment as Nolan turns / autopilot markers: persisted with `parentId: null`
|
|
70
|
+
* so the LLM never sees it, anchored by `afterMessageCount` so the host can
|
|
71
|
+
* interleave it back into the transcript on resume. */
|
|
72
|
+
export declare const APP_MARKER_CUSTOM_KIND = "app_transcript_marker";
|
|
73
|
+
export interface AppMarkerPayload {
|
|
74
|
+
version: 1;
|
|
75
|
+
kind: "plan" | "task" | "error" | "user_hint" | "compaction";
|
|
76
|
+
afterMessageCount: number;
|
|
77
|
+
/** Kind-specific display fields (reason/title/headline/nolanSent/counts/…). */
|
|
78
|
+
data: Record<string, unknown>;
|
|
79
|
+
}
|
|
52
80
|
export type SessionEntry = MessageEntry | ModelChangeEntry | ThinkingLevelChangeEntry | CompactionEntry | LabelEntry | CustomEntry;
|
|
53
81
|
export interface SessionHeader {
|
|
54
82
|
type: "session";
|
|
@@ -130,6 +158,12 @@ export declare class SessionManager {
|
|
|
130
158
|
/** Read all persisted Nolan turns in file order. Returns them regardless of
|
|
131
159
|
* branch (Nolan turns are not chained into the DAG), validated + normalized. */
|
|
132
160
|
getNolanTurns(entries: SessionEntry[]): NolanTurnPayload[];
|
|
161
|
+
/** Read all persisted app transcript markers in file order, validated +
|
|
162
|
+
* normalized (same not-on-the-DAG treatment as Nolan turns). */
|
|
163
|
+
getAppMarkers(entries: SessionEntry[]): AppMarkerPayload[];
|
|
164
|
+
/** Read all persisted autopilot markers in file order, validated + normalized
|
|
165
|
+
* (same not-on-the-DAG treatment as Nolan turns). */
|
|
166
|
+
getAutopilotMarkers(entries: SessionEntry[]): AutopilotMarkerPayload[];
|
|
133
167
|
/**
|
|
134
168
|
* Ensure every assistant message with tool_use blocks is followed by a tool
|
|
135
169
|
* message containing matching tool_result entries. Inserts synthetic
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/core/session-manager.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../src/core/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,20 @@ export const DISPLAY_ITEM_CUSTOM_KIND = "display_item";
|
|
|
15
15
|
* number of non-system messages that existed when the turn was recorded, used
|
|
16
16
|
* to interleave Nolan turns back into the transcript chronologically. */
|
|
17
17
|
export const NOLAN_TURN_CUSTOM_KIND = "nolan_turn";
|
|
18
|
+
/** Custom-entry kind for an autopilot verdict marker. Mirrors `nolan_turn`:
|
|
19
|
+
* persisted as a `custom` entry with `parentId: null` so it's never on the
|
|
20
|
+
* message DAG (EZ Coder never sees it) but survives resume/compaction and
|
|
21
|
+
* interleaves back into the transcript via `afterMessageCount`. Covers all
|
|
22
|
+
* four terminal/near-terminal autopilot markers so a resumed session renders
|
|
23
|
+
* the exact same Nolan bubble the live run showed — never the raw verdict
|
|
24
|
+
* keyword (e.g. `ALL_CLEAR`) the model actually replied with. */
|
|
25
|
+
export const AUTOPILOT_MARKER_CUSTOM_KIND = "autopilot_marker";
|
|
26
|
+
/** Custom-entry kind for a generic app transcript marker (plan-mode banner,
|
|
27
|
+
* task header, error row, user-bubble display hint). Same not-on-the-DAG
|
|
28
|
+
* treatment as Nolan turns / autopilot markers: persisted with `parentId: null`
|
|
29
|
+
* so the LLM never sees it, anchored by `afterMessageCount` so the host can
|
|
30
|
+
* interleave it back into the transcript on resume. */
|
|
31
|
+
export const APP_MARKER_CUSTOM_KIND = "app_transcript_marker";
|
|
18
32
|
function isCompletedItemLike(value) {
|
|
19
33
|
return (typeof value === "object" &&
|
|
20
34
|
value !== null &&
|
|
@@ -351,6 +365,59 @@ export class SessionManager {
|
|
|
351
365
|
return [];
|
|
352
366
|
});
|
|
353
367
|
}
|
|
368
|
+
/** Read all persisted app transcript markers in file order, validated +
|
|
369
|
+
* normalized (same not-on-the-DAG treatment as Nolan turns). */
|
|
370
|
+
getAppMarkers(entries) {
|
|
371
|
+
return entries.flatMap((entry) => {
|
|
372
|
+
if (entry.type !== "custom" || entry.kind !== APP_MARKER_CUSTOM_KIND)
|
|
373
|
+
return [];
|
|
374
|
+
const p = entry.data;
|
|
375
|
+
const kind = p?.kind;
|
|
376
|
+
if (p?.version === 1 &&
|
|
377
|
+
(kind === "plan" ||
|
|
378
|
+
kind === "task" ||
|
|
379
|
+
kind === "error" ||
|
|
380
|
+
kind === "user_hint" ||
|
|
381
|
+
kind === "compaction")) {
|
|
382
|
+
return [
|
|
383
|
+
{
|
|
384
|
+
version: 1,
|
|
385
|
+
kind,
|
|
386
|
+
afterMessageCount: typeof p.afterMessageCount === "number" ? p.afterMessageCount : 0,
|
|
387
|
+
data: typeof p.data === "object" && p.data !== null ? p.data : {},
|
|
388
|
+
},
|
|
389
|
+
];
|
|
390
|
+
}
|
|
391
|
+
return [];
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
/** Read all persisted autopilot markers in file order, validated + normalized
|
|
395
|
+
* (same not-on-the-DAG treatment as Nolan turns). */
|
|
396
|
+
getAutopilotMarkers(entries) {
|
|
397
|
+
return entries.flatMap((entry) => {
|
|
398
|
+
if (entry.type !== "custom" || entry.kind !== AUTOPILOT_MARKER_CUSTOM_KIND)
|
|
399
|
+
return [];
|
|
400
|
+
const p = entry.data;
|
|
401
|
+
const phase = p?.phase;
|
|
402
|
+
if (p?.version === 1 &&
|
|
403
|
+
(phase === "prompted" ||
|
|
404
|
+
phase === "done" ||
|
|
405
|
+
phase === "human" ||
|
|
406
|
+
phase === "capped" ||
|
|
407
|
+
phase === "plan_approved")) {
|
|
408
|
+
return [
|
|
409
|
+
{
|
|
410
|
+
version: 1,
|
|
411
|
+
phase,
|
|
412
|
+
...(typeof p.reason === "string" ? { reason: p.reason } : {}),
|
|
413
|
+
...(typeof p.body === "string" ? { body: p.body } : {}),
|
|
414
|
+
afterMessageCount: typeof p.afterMessageCount === "number" ? p.afterMessageCount : 0,
|
|
415
|
+
},
|
|
416
|
+
];
|
|
417
|
+
}
|
|
418
|
+
return [];
|
|
419
|
+
});
|
|
420
|
+
}
|
|
354
421
|
/**
|
|
355
422
|
* Ensure every assistant message with tool_use blocks is followed by a tool
|
|
356
423
|
* message containing matching tool_result entries. Inserts synthetic
|