@kenkaiiii/ggcoder 5.74.3 → 5.75.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.
Files changed (215) hide show
  1. package/README.md +1 -1
  2. package/assets/skills/bulletproof/SKILL.md +1 -1
  3. package/assets/skills/clarify/SKILL.md +1 -1
  4. package/assets/skills/code-review/SKILL.md +1 -1
  5. package/assets/skills/compliance-guard/SKILL.md +1 -1
  6. package/assets/skills/durable/SKILL.md +1 -1
  7. package/assets/skills/evidence-led-ui/SKILL.md +1 -1
  8. package/assets/skills/lean/SKILL.md +1 -1
  9. package/assets/skills/refactoring/SKILL.md +1 -1
  10. package/assets/skills/root-cause/SKILL.md +1 -1
  11. package/assets/skills/shared-language/SKILL.md +1 -1
  12. package/assets/skills/tdd/SKILL.md +1 -1
  13. package/dist/app-sidecar/app-settings.d.ts +65 -0
  14. package/dist/app-sidecar/app-settings.js +147 -0
  15. package/dist/app-sidecar/app-settings.js.map +1 -0
  16. package/dist/app-sidecar/attachments.d.ts +11 -0
  17. package/dist/app-sidecar/attachments.js +47 -0
  18. package/dist/app-sidecar/attachments.js.map +1 -0
  19. package/dist/app-sidecar/auth-routes.d.ts +3 -0
  20. package/dist/app-sidecar/auth-routes.js +290 -0
  21. package/dist/app-sidecar/auth-routes.js.map +1 -0
  22. package/dist/app-sidecar/autopilot-runner.d.ts +61 -0
  23. package/dist/app-sidecar/autopilot-runner.js +367 -0
  24. package/dist/app-sidecar/autopilot-runner.js.map +1 -0
  25. package/dist/app-sidecar/file-search.d.ts +15 -0
  26. package/dist/app-sidecar/file-search.js +103 -0
  27. package/dist/app-sidecar/file-search.js.map +1 -0
  28. package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
  29. package/dist/app-sidecar/hf-pull-manager.js +224 -0
  30. package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
  31. package/dist/app-sidecar/history-routes.d.ts +3 -0
  32. package/dist/app-sidecar/history-routes.js +375 -0
  33. package/dist/app-sidecar/history-routes.js.map +1 -0
  34. package/dist/app-sidecar/history.d.ts +67 -0
  35. package/dist/app-sidecar/history.js +23 -0
  36. package/dist/app-sidecar/history.js.map +1 -0
  37. package/dist/app-sidecar/http.d.ts +5 -0
  38. package/dist/app-sidecar/http.js +27 -0
  39. package/dist/app-sidecar/http.js.map +1 -0
  40. package/dist/app-sidecar/integration-routes.d.ts +3 -0
  41. package/dist/app-sidecar/integration-routes.js +286 -0
  42. package/dist/app-sidecar/integration-routes.js.map +1 -0
  43. package/dist/app-sidecar/json-mode.d.ts +10 -0
  44. package/dist/app-sidecar/json-mode.js +73 -0
  45. package/dist/app-sidecar/json-mode.js.map +1 -0
  46. package/dist/app-sidecar/keep-awake.d.ts +4 -0
  47. package/dist/app-sidecar/keep-awake.js +5 -0
  48. package/dist/app-sidecar/keep-awake.js.map +1 -0
  49. package/dist/app-sidecar/ken-context.d.ts +20 -0
  50. package/dist/app-sidecar/ken-context.js +55 -0
  51. package/dist/app-sidecar/ken-context.js.map +1 -0
  52. package/dist/app-sidecar/mcp-routes.d.ts +3 -0
  53. package/dist/app-sidecar/mcp-routes.js +185 -0
  54. package/dist/app-sidecar/mcp-routes.js.map +1 -0
  55. package/dist/app-sidecar/mcp-rows.d.ts +31 -0
  56. package/dist/app-sidecar/mcp-rows.js +77 -0
  57. package/dist/app-sidecar/mcp-rows.js.map +1 -0
  58. package/dist/app-sidecar/progress-manager.d.ts +10 -0
  59. package/dist/app-sidecar/progress-manager.js +116 -0
  60. package/dist/app-sidecar/progress-manager.js.map +1 -0
  61. package/dist/app-sidecar/prompt-routes.d.ts +3 -0
  62. package/dist/app-sidecar/prompt-routes.js +354 -0
  63. package/dist/app-sidecar/prompt-routes.js.map +1 -0
  64. package/dist/app-sidecar/repo-polls.d.ts +15 -0
  65. package/dist/app-sidecar/repo-polls.js +25 -0
  66. package/dist/app-sidecar/repo-polls.js.map +1 -0
  67. package/dist/app-sidecar/route-context.d.ts +145 -0
  68. package/dist/app-sidecar/route-context.js +2 -0
  69. package/dist/app-sidecar/route-context.js.map +1 -0
  70. package/dist/app-sidecar/run-control-routes.d.ts +3 -0
  71. package/dist/app-sidecar/run-control-routes.js +430 -0
  72. package/dist/app-sidecar/run-control-routes.js.map +1 -0
  73. package/dist/app-sidecar/session-routes.d.ts +3 -0
  74. package/dist/app-sidecar/session-routes.js +115 -0
  75. package/dist/app-sidecar/session-routes.js.map +1 -0
  76. package/dist/app-sidecar/session-types.d.ts +39 -0
  77. package/dist/app-sidecar/session-types.js +5 -0
  78. package/dist/app-sidecar/session-types.js.map +1 -0
  79. package/dist/app-sidecar/task-routes.d.ts +3 -0
  80. package/dist/app-sidecar/task-routes.js +149 -0
  81. package/dist/app-sidecar/task-routes.js.map +1 -0
  82. package/dist/app-sidecar/usage.d.ts +19 -0
  83. package/dist/app-sidecar/usage.js +153 -0
  84. package/dist/app-sidecar/usage.js.map +1 -0
  85. package/dist/app-sidecar/workspace-routes.d.ts +3 -0
  86. package/dist/app-sidecar/workspace-routes.js +244 -0
  87. package/dist/app-sidecar/workspace-routes.js.map +1 -0
  88. package/dist/app-sidecar.js +467 -3775
  89. package/dist/app-sidecar.js.map +1 -1
  90. package/dist/cli.js +2 -2
  91. package/dist/cli.js.map +1 -1
  92. package/dist/config.js +1 -1
  93. package/dist/core/acceptance-checks.js +3 -9
  94. package/dist/core/acceptance-checks.js.map +1 -1
  95. package/dist/core/agent-session/helpers.d.ts +26 -0
  96. package/dist/core/agent-session/helpers.js +47 -0
  97. package/dist/core/agent-session/helpers.js.map +1 -0
  98. package/dist/core/agent-session/mcp-tools.d.ts +68 -0
  99. package/dist/core/agent-session/mcp-tools.js +195 -0
  100. package/dist/core/agent-session/mcp-tools.js.map +1 -0
  101. package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
  102. package/dist/core/agent-session/run-loop-monitor.js +164 -0
  103. package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
  104. package/dist/core/agent-session/transcript-markers.d.ts +57 -0
  105. package/dist/core/agent-session/transcript-markers.js +166 -0
  106. package/dist/core/agent-session/transcript-markers.js.map +1 -0
  107. package/dist/core/agent-session/verification-tracker.d.ts +46 -0
  108. package/dist/core/agent-session/verification-tracker.js +246 -0
  109. package/dist/core/agent-session/verification-tracker.js.map +1 -0
  110. package/dist/core/agent-session.d.ts +21 -87
  111. package/dist/core/agent-session.js +141 -712
  112. package/dist/core/agent-session.js.map +1 -1
  113. package/dist/core/auth-providers.js +3 -3
  114. package/dist/core/auth-providers.js.map +1 -1
  115. package/dist/core/bundled-agents.js +6 -6
  116. package/dist/core/bundled-agents.js.map +1 -1
  117. package/dist/core/checklist-git.d.ts +19 -0
  118. package/dist/core/checklist-git.js +54 -0
  119. package/dist/core/checklist-git.js.map +1 -0
  120. package/dist/core/checklist-items.d.ts +10 -1
  121. package/dist/core/checklist-items.js +22 -0
  122. package/dist/core/checklist-items.js.map +1 -1
  123. package/dist/core/checklist-prompt.d.ts +5 -1
  124. package/dist/core/checklist-prompt.js +16 -5
  125. package/dist/core/checklist-prompt.js.map +1 -1
  126. package/dist/core/checklist-snapshot.d.ts +5 -1
  127. package/dist/core/checklist-snapshot.js +19 -2
  128. package/dist/core/checklist-snapshot.js.map +1 -1
  129. package/dist/core/context-limits.js +1 -1
  130. package/dist/core/context-limits.js.map +1 -1
  131. package/dist/core/skills.js +6 -9
  132. package/dist/core/skills.js.map +1 -1
  133. package/dist/core/style-packs/index.js +2 -11
  134. package/dist/core/style-packs/index.js.map +1 -1
  135. package/dist/core/style-packs/packs.d.ts +3 -12
  136. package/dist/core/style-packs/packs.js +132 -173
  137. package/dist/core/style-packs/packs.js.map +1 -1
  138. package/dist/system-prompt.js +55 -78
  139. package/dist/system-prompt.js.map +1 -1
  140. package/dist/tools/ask-user.js +13 -74
  141. package/dist/tools/ask-user.js.map +1 -1
  142. package/dist/tools/bash.js +13 -78
  143. package/dist/tools/bash.js.map +1 -1
  144. package/dist/tools/checklist.d.ts +2 -10
  145. package/dist/tools/checklist.js +7 -39
  146. package/dist/tools/checklist.js.map +1 -1
  147. package/dist/tools/code-nav.js +7 -29
  148. package/dist/tools/code-nav.js.map +1 -1
  149. package/dist/tools/edit.d.ts +3 -9
  150. package/dist/tools/edit.js +92 -65
  151. package/dist/tools/edit.js.map +1 -1
  152. package/dist/tools/enter-plan.js +2 -7
  153. package/dist/tools/enter-plan.js.map +1 -1
  154. package/dist/tools/exit-plan.js +2 -3
  155. package/dist/tools/exit-plan.js.map +1 -1
  156. package/dist/tools/find.js +3 -4
  157. package/dist/tools/find.js.map +1 -1
  158. package/dist/tools/grep.js +6 -18
  159. package/dist/tools/grep.js.map +1 -1
  160. package/dist/tools/ls.js +3 -3
  161. package/dist/tools/ls.js.map +1 -1
  162. package/dist/tools/prompt-hints.js +34 -47
  163. package/dist/tools/prompt-hints.js.map +1 -1
  164. package/dist/tools/read.js +8 -20
  165. package/dist/tools/read.js.map +1 -1
  166. package/dist/tools/search-code.js +4 -12
  167. package/dist/tools/search-code.js.map +1 -1
  168. package/dist/tools/skill.js +13 -7
  169. package/dist/tools/skill.js.map +1 -1
  170. package/dist/tools/subagent-control.js +7 -22
  171. package/dist/tools/subagent-control.js.map +1 -1
  172. package/dist/tools/subagent.js +4 -7
  173. package/dist/tools/subagent.js.map +1 -1
  174. package/dist/tools/task-output.js +4 -15
  175. package/dist/tools/task-output.js.map +1 -1
  176. package/dist/tools/task-send.js +5 -17
  177. package/dist/tools/task-send.js.map +1 -1
  178. package/dist/tools/task-stop.js +2 -2
  179. package/dist/tools/task-stop.js.map +1 -1
  180. package/dist/tools/tool-search.js +2 -7
  181. package/dist/tools/tool-search.js.map +1 -1
  182. package/dist/tools/tool-tiers.d.ts +17 -4
  183. package/dist/tools/tool-tiers.js +38 -15
  184. package/dist/tools/tool-tiers.js.map +1 -1
  185. package/dist/tools/web-fetch.js +7 -33
  186. package/dist/tools/web-fetch.js.map +1 -1
  187. package/dist/tools/write.js +3 -4
  188. package/dist/tools/write.js.map +1 -1
  189. package/dist/ui/components/Footer.js +1 -2
  190. package/dist/ui/components/Footer.js.map +1 -1
  191. package/dist/utils/shared-poll.d.ts +37 -0
  192. package/dist/utils/shared-poll.js +104 -0
  193. package/dist/utils/shared-poll.js.map +1 -0
  194. package/package.json +7 -4
  195. package/dist/core/api-benchmark.d.ts +0 -63
  196. package/dist/core/api-benchmark.js +0 -381
  197. package/dist/core/api-benchmark.js.map +0 -1
  198. package/dist/core/bash-spawn-benchmark.d.ts +0 -1
  199. package/dist/core/bash-spawn-benchmark.js +0 -139
  200. package/dist/core/bash-spawn-benchmark.js.map +0 -1
  201. package/dist/core/cache-warm-benchmark.d.ts +0 -21
  202. package/dist/core/cache-warm-benchmark.js +0 -170
  203. package/dist/core/cache-warm-benchmark.js.map +0 -1
  204. package/dist/core/fast-apply-benchmark.d.ts +0 -25
  205. package/dist/core/fast-apply-benchmark.js +0 -284
  206. package/dist/core/fast-apply-benchmark.js.map +0 -1
  207. package/dist/core/hashline-edit-benchmark.d.ts +0 -88
  208. package/dist/core/hashline-edit-benchmark.js +0 -518
  209. package/dist/core/hashline-edit-benchmark.js.map +0 -1
  210. package/dist/core/semantic-search-benchmark.d.ts +0 -36
  211. package/dist/core/semantic-search-benchmark.js +0 -211
  212. package/dist/core/semantic-search-benchmark.js.map +0 -1
  213. package/dist/core/speed-benchmark.d.ts +0 -132
  214. package/dist/core/speed-benchmark.js +0 -410
  215. package/dist/core/speed-benchmark.js.map +0 -1
@@ -0,0 +1,224 @@
1
+ import { spawn } from "node:child_process";
2
+ import { AuthStorage } from "../core/auth-storage.js";
3
+ import { advancesPhase, explainPullFailure, isGgufShard, parseOllamaPullLine, pickGgufQuant, SHARDED_MESSAGE, toHfSearchRow, } from "../hf-pull.js";
4
+ /** Per-session Hugging Face → Ollama pull state + Hub search (moved verbatim
5
+ * out of `createSession`). */
6
+ export function createHfPullManager(deps) {
7
+ const { paths, broadcast, broadcastAll, scanLocalModels, localStatePayload } = deps;
8
+ // ── Hugging Face → Ollama pulls (the "Add from Hugging Face" modal) ──
9
+ // One pull at a time: multi-GB downloads, one progress surface. State lives
10
+ // here (not in the webview) so a closed modal or app restart mid-pull keeps
11
+ // streaming; the terminal state is kept until the next pull so reopening the
12
+ // modal shows how the last one ended.
13
+ let hfPull = null;
14
+ const hfPullPayload = (s) => ({
15
+ repo: s.repo,
16
+ model: s.model,
17
+ tag: s.tag,
18
+ file: s.file,
19
+ sizeBytes: s.sizeBytes,
20
+ phase: s.phase,
21
+ percent: s.percent,
22
+ ...(s.detail ? { detail: s.detail } : {}),
23
+ ...(s.error ? { error: s.error } : {}),
24
+ });
25
+ /** Stored HF token, if the user connected the huggingface provider. */
26
+ async function hfToken() {
27
+ try {
28
+ const auth = new AuthStorage(paths.authFile);
29
+ const creds = await auth.resolveCredentials("huggingface");
30
+ return creds.accessToken || undefined;
31
+ }
32
+ catch {
33
+ return undefined;
34
+ }
35
+ }
36
+ async function hfHubJson(pathname) {
37
+ const token = await hfToken();
38
+ const res = await fetch(`https://huggingface.co${pathname}`, {
39
+ headers: token ? { authorization: `Bearer ${token}` } : {},
40
+ signal: AbortSignal.timeout(10_000),
41
+ });
42
+ if (!res.ok)
43
+ throw new Error(`Hugging Face responded ${res.status}`);
44
+ return res.json();
45
+ }
46
+ /** Search the Hub for GGUF repos (what Ollama can pull). */
47
+ async function hfSearch(query) {
48
+ // `filter=gguf` (the tag the Hub applies to repos that actually contain
49
+ // GGUF files) — `library=gguf` also matches safetensors-only base repos,
50
+ // which then fail at pull time. `expand[]=gguf` confirms per row.
51
+ const params = new URLSearchParams({
52
+ search: query,
53
+ filter: "gguf",
54
+ sort: "downloads",
55
+ direction: "-1",
56
+ limit: "12",
57
+ });
58
+ for (const field of ["gguf", "downloads", "likes", "lastModified"]) {
59
+ params.append("expand[]", field);
60
+ }
61
+ const data = (await hfHubJson(`/api/models?${params.toString()}`));
62
+ return (Array.isArray(data) ? data : [])
63
+ .map(toHfSearchRow)
64
+ .filter((r) => r !== null);
65
+ }
66
+ /**
67
+ * Start `ollama pull hf.co/<repo>[:quant]`. Resolves once the child is
68
+ * spawned; progress streams as `hf_pull` events. The chosen quant comes from
69
+ * the repo's real file list — the client only ever sends a repo id, so there
70
+ * is no injection surface into argv.
71
+ */
72
+ async function startHfPull(repo) {
73
+ if (hfPull?.child) {
74
+ throw Object.assign(new Error("A download is already running."), { status: 409 });
75
+ }
76
+ // `recursive=true`: many repos (unsloth, mradermacher) keep quants in
77
+ // per-quant subfolders, and a flat listing reports them as GGUF-less.
78
+ const tree = (await hfHubJson(`/api/models/${repo}/tree/main?recursive=true`));
79
+ const files = (Array.isArray(tree) ? tree : []).flatMap((entry) => {
80
+ const e = entry;
81
+ // `type` guards a directory entry (size 0) from beating real files in the
82
+ // size fallback; the Hub marks folders as "directory".
83
+ if (e.type !== undefined && e.type !== "file")
84
+ return [];
85
+ if (typeof e.path !== "string" || !e.path.toLowerCase().endsWith(".gguf"))
86
+ return [];
87
+ const size = Number(e.lfs?.size ?? e.size ?? 0);
88
+ return [{ path: e.path, sizeBytes: Number.isFinite(size) ? size : 0 }];
89
+ });
90
+ const choice = pickGgufQuant(files);
91
+ if (!choice) {
92
+ const sharded = files.some((f) => isGgufShard(f.path));
93
+ throw Object.assign(new Error(sharded ? SHARDED_MESSAGE : "That repo has no GGUF file for Ollama to pull."), { status: 400 });
94
+ }
95
+ const model = `hf.co/${repo}${choice.tag ? `:${choice.tag}` : ""}`;
96
+ const token = await hfToken();
97
+ const state = {
98
+ repo,
99
+ model,
100
+ tag: choice.tag,
101
+ file: choice.file.path,
102
+ sizeBytes: choice.file.sizeBytes,
103
+ phase: "preparing",
104
+ percent: 0,
105
+ child: null,
106
+ };
107
+ hfPull = state;
108
+ broadcast("hf_pull", hfPullPayload(state));
109
+ // ollama prints progress to stderr (stdout on some builds); parse both.
110
+ let stderrTail = "";
111
+ let lastBroadcast = "";
112
+ const feed = (chunk) => {
113
+ // Once the pull is terminal (success, failure, or user cancel) stop
114
+ // parsing: a killed ollama dumps a burst of stderr that would otherwise
115
+ // spam the modal with garbage frames after the outcome is already shown.
116
+ if (state.phase === "success" || state.phase === "error")
117
+ return;
118
+ for (const line of chunk.split(/\r\n|\r|\n/)) {
119
+ const parsed = parseOllamaPullLine(line);
120
+ if (!parsed)
121
+ continue;
122
+ // A redrawn frame repeats `pulling manifest` next to live progress; it
123
+ // must not drag the modal back to "Contacting Ollama…".
124
+ if (!advancesPhase(state.phase, parsed.phase))
125
+ continue;
126
+ if (parsed.phase !== "error") {
127
+ state.phase = parsed.phase;
128
+ if (parsed.percent !== undefined)
129
+ state.percent = parsed.percent;
130
+ state.detail = parsed.detail;
131
+ }
132
+ // ollama redraws its TUI frame several times a second, mostly with
133
+ // identical numbers. Broadcasting each one re-rendered the modal for no
134
+ // visible change; only a frame that actually reads differently ships.
135
+ const next = JSON.stringify(hfPullPayload(state));
136
+ if (next === lastBroadcast)
137
+ continue;
138
+ lastBroadcast = next;
139
+ broadcast("hf_pull", hfPullPayload(state));
140
+ }
141
+ };
142
+ try {
143
+ const child = spawn("ollama", ["pull", model], {
144
+ env: { ...process.env, ...(token ? { HF_TOKEN: token } : {}) },
145
+ stdio: ["ignore", "pipe", "pipe"],
146
+ });
147
+ state.child = child;
148
+ child.stdout?.setEncoding("utf8");
149
+ child.stderr?.setEncoding("utf8");
150
+ child.stdout?.on("data", feed);
151
+ child.stderr?.on("data", (d) => {
152
+ stderrTail = (stderrTail + d).slice(-2000);
153
+ feed(d);
154
+ });
155
+ child.on("error", (err) => {
156
+ state.child = null;
157
+ state.phase = "error";
158
+ state.error =
159
+ err.code === "ENOENT"
160
+ ? "Ollama isn't installed (or isn't on PATH). Install it from ollama.com, then retry."
161
+ : `Could not start Ollama: ${err.message}`;
162
+ broadcast("hf_pull", hfPullPayload(state));
163
+ });
164
+ child.on("close", (code) => {
165
+ state.child = null;
166
+ if (state.phase === "success" || state.phase === "error")
167
+ return; // cancelled
168
+ if (code === 0) {
169
+ state.phase = "success";
170
+ state.percent = 100;
171
+ state.detail = undefined;
172
+ broadcast("hf_pull", hfPullPayload(state));
173
+ // The new model only exists to the app once Ollama lists it. Ollama's
174
+ // library is machine-wide, like the shared auth file, so every window
175
+ // gets the refresh — not just the one that ran the download.
176
+ void scanLocalModels(true)
177
+ .then(() => broadcastAll("models_change", { local: localStatePayload() }))
178
+ .catch(() => undefined);
179
+ }
180
+ else {
181
+ state.phase = "error";
182
+ state.error = state.error ?? explainPullFailure(stderrTail);
183
+ broadcast("hf_pull", hfPullPayload(state));
184
+ }
185
+ });
186
+ }
187
+ catch (err) {
188
+ state.child = null;
189
+ state.phase = "error";
190
+ state.error = `Could not start Ollama: ${err instanceof Error ? err.message : String(err)}`;
191
+ broadcast("hf_pull", hfPullPayload(state));
192
+ }
193
+ return hfPullPayload(state);
194
+ }
195
+ function cancelHfPull() {
196
+ const child = hfPull?.child;
197
+ if (!child)
198
+ return false;
199
+ // Terminal state FIRST, then the kill: the child's death rattle must not
200
+ // overwrite the clean "cancelled" outcome with raw stderr.
201
+ if (hfPull) {
202
+ hfPull.phase = "error";
203
+ hfPull.error = "Download cancelled.";
204
+ hfPull.detail = undefined;
205
+ hfPull.child = null;
206
+ broadcast("hf_pull", hfPullPayload(hfPull));
207
+ }
208
+ child.kill("SIGTERM");
209
+ return true;
210
+ }
211
+ return {
212
+ get hfPull() {
213
+ return hfPull;
214
+ },
215
+ set hfPull(v) {
216
+ hfPull = v;
217
+ },
218
+ hfPullPayload,
219
+ hfSearch,
220
+ startHfPull,
221
+ cancelHfPull,
222
+ };
223
+ }
224
+ //# sourceMappingURL=hf-pull-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hf-pull-manager.js","sourceRoot":"","sources":["../../src/app-sidecar/hf-pull-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type http from "node:http";
2
+ import type { SessionRouteContext } from "./route-context.js";
3
+ export declare function handleHistoryRoutes(ctx: SessionRouteContext, req: http.IncomingMessage, res: http.ServerResponse, url: string, method: string): boolean;
@@ -0,0 +1,375 @@
1
+ import path from "node:path";
2
+ import { restoreAppErrorPayload } from "../app-error.js";
3
+ import { normalizeAutopilotMarkersForHistory, normalizeAppMarkersForHistory, normalizeKenTurnsForHistory, getHistoryMessageVisibility, replayMessagesInOrder, restoreUserRow, restoreAssistantTexts, resolveRestoredCommand, extractToolImagePaths, } from "../core/session-history.js";
4
+ import { spawnedTasks } from "../tools/subagent-shared.js";
5
+ import { PROMPT_COMMANDS } from "../core/prompt-commands.js";
6
+ import { loadCustomCommands } from "../core/custom-commands.js";
7
+ import { downscaleForPreview, IMAGE_MEDIA_TYPES } from "../utils/image.js";
8
+ import { readFileBounded } from "../tools/operations.js";
9
+ import { json } from "./http.js";
10
+ import { detectHookKind } from "./history.js";
11
+ export function handleHistoryRoutes(ctx, req, res, url, method) {
12
+ if (method === "GET" && url === "/history") {
13
+ // Reconstruct the transcript from persisted messages so resume is 1:1 with
14
+ // the live SSE stream. Walks ALL message types (not just user/assistant):
15
+ // tool result messages carry ImageContent blocks (screenshots,
16
+ // generate_image) that must re-render inline, and assistant tool_call
17
+ // blocks carry sub-agent delegations that must re-appear as group items.
18
+ //
19
+ // The `details` object (imagePreviews with path + downscaled preview) is
20
+ // event-only and never persisted — we reconstruct from the raw
21
+ // ImageContent in the tool result, downsampling on the sidecar side and
22
+ // extracting the path from the text block ("Generated image → /path").
23
+ void (async () => {
24
+ const commandCandidates = [...PROMPT_COMMANDS, ...(await loadCustomCommands(ctx.cwd))];
25
+ const messages = ctx.session.getMessages();
26
+ // An Ideal hook is injected immediately after the assistant's candidate
27
+ // no-tool response. That response is review scratch, not a user-visible
28
+ // final answer. Live SSE drops it when the hook event arrives; mark the
29
+ // same assistant message here so resumed history stays identical.
30
+ const hiddenIdealDrafts = new Set();
31
+ for (let i = 0; i < messages.length - 1; i++) {
32
+ const draft = messages[i];
33
+ const hookPrompt = messages[i + 1];
34
+ if (draft?.role !== "assistant" || hookPrompt?.role !== "user")
35
+ continue;
36
+ const restored = restoreUserRow(hookPrompt.content);
37
+ if (detectHookKind(restored.text) === "ideal")
38
+ hiddenIdealDrafts.add(draft);
39
+ }
40
+ // Pre-index tool results by toolCallId so we can pair tool calls with
41
+ // their results (for sub-agent status + image extraction).
42
+ const toolResultMap = new Map();
43
+ // Tool name per call, so restore only trusts generate_image's own text
44
+ // when it reads extra images from disk (an MCP server could fake it).
45
+ const toolNameById = new Map();
46
+ for (const msg of messages) {
47
+ if (msg.role === "assistant" && typeof msg.content !== "string") {
48
+ for (const c of msg.content) {
49
+ if (c.type === "tool_call")
50
+ toolNameById.set(c.id, c.name);
51
+ }
52
+ }
53
+ if (msg.role !== "tool")
54
+ continue;
55
+ for (const tr of msg.content) {
56
+ toolResultMap.set(tr.toolCallId, {
57
+ content: tr.content,
58
+ isError: tr.isError ?? false,
59
+ });
60
+ }
61
+ }
62
+ const history = [];
63
+ // Ken (mentor) turns to interleave: group by the non-system message count
64
+ // they were recorded after, so each lands right after that message. A
65
+ // turn becomes two wire rows: the `@Ken` question (user) + Ken's reply
66
+ // (assistant), both flagged `ken` so the webview tints them.
67
+ // Deduped; stale anchors are clamped to the last message (Ken turns
68
+ // carry real conversation, so they render at the end instead of
69
+ // vanishing).
70
+ const kenByCount = new Map();
71
+ for (const turn of normalizeKenTurnsForHistory(ctx.session.getKenTurns(), messages.filter((m) => m.role !== "system").length)) {
72
+ const list = kenByCount.get(turn.afterMessageCount) ?? [];
73
+ list.push(turn);
74
+ kenByCount.set(turn.afterMessageCount, list);
75
+ }
76
+ const flushKen = (count) => {
77
+ const turns = kenByCount.get(count);
78
+ if (!turns)
79
+ return;
80
+ kenByCount.delete(count);
81
+ for (const turn of turns) {
82
+ history.push({ role: "user", text: `@Ken ${turn.question}`, ken: true });
83
+ history.push({ role: "assistant", text: turn.reply, ken: true });
84
+ }
85
+ };
86
+ // Autopilot verdict markers to interleave, same anchor scheme as Ken
87
+ // turns — each becomes a single assistant row the webview renders
88
+ // exactly like the live `autopilot` item (never a raw verdict string).
89
+ // Normalization pulls anchors left over from an unrebased compaction
90
+ // back to where the marker was actually written, so stale all-clear
91
+ // bubbles no longer bunch at the bottom of a reopened session.
92
+ const restoredMessageCount = messages.filter((m) => m.role !== "system").length;
93
+ const autopilotByCount = new Map();
94
+ for (const marker of normalizeAutopilotMarkersForHistory(ctx.session.getAutopilotMarkers(), restoredMessageCount)) {
95
+ const list = autopilotByCount.get(marker.afterMessageCount) ?? [];
96
+ list.push(marker);
97
+ autopilotByCount.set(marker.afterMessageCount, list);
98
+ }
99
+ const flushAutopilot = (count) => {
100
+ const markers = autopilotByCount.get(count);
101
+ if (!markers)
102
+ return;
103
+ autopilotByCount.delete(count);
104
+ for (const marker of markers) {
105
+ history.push({
106
+ role: "assistant",
107
+ text: "",
108
+ autopilot: {
109
+ phase: marker.phase,
110
+ ...(marker.reason !== undefined ? { reason: marker.reason } : {}),
111
+ ...(marker.body !== undefined ? { body: marker.body } : {}),
112
+ copySeed: marker.copySeed,
113
+ },
114
+ });
115
+ }
116
+ };
117
+ // App transcript markers (plan banner / task header / error rows /
118
+ // user-bubble hints), same anchor scheme. user_hint markers don't
119
+ // become rows — they decorate the user row at their anchor instead.
120
+ const appMarkersByCount = new Map();
121
+ const userHintByCount = new Map();
122
+ // Compaction-count markers pair with compacted summary rows in file
123
+ // order (FIFO), not by anchor — the summary user message is what
124
+ // positions the notice.
125
+ const compactionCounts = [];
126
+ for (const marker of normalizeAppMarkersForHistory(ctx.session.getAppMarkers(), restoredMessageCount)) {
127
+ if (marker.kind === "user_hint") {
128
+ userHintByCount.set(marker.afterMessageCount, marker.data);
129
+ continue;
130
+ }
131
+ if (marker.kind === "compaction") {
132
+ const d = marker.data;
133
+ if (typeof d.originalCount === "number" && typeof d.newCount === "number") {
134
+ compactionCounts.push({ originalCount: d.originalCount, newCount: d.newCount });
135
+ }
136
+ continue;
137
+ }
138
+ const list = appMarkersByCount.get(marker.afterMessageCount) ?? [];
139
+ list.push(marker);
140
+ appMarkersByCount.set(marker.afterMessageCount, list);
141
+ }
142
+ const flushAppMarkers = (count) => {
143
+ const markers = appMarkersByCount.get(count);
144
+ if (!markers)
145
+ return;
146
+ appMarkersByCount.delete(count);
147
+ for (const marker of markers) {
148
+ const d = marker.data;
149
+ if (marker.kind === "plan") {
150
+ history.push({
151
+ role: "assistant",
152
+ text: "",
153
+ plan: { reason: typeof d.reason === "string" ? d.reason : "" },
154
+ });
155
+ }
156
+ else if (marker.kind === "task") {
157
+ history.push({
158
+ role: "assistant",
159
+ text: "",
160
+ task: { title: typeof d.title === "string" ? d.title : "" },
161
+ });
162
+ }
163
+ else if (marker.kind === "error" && typeof d.headline === "string") {
164
+ const error = restoreAppErrorPayload(d);
165
+ if (error)
166
+ history.push({ role: "assistant", text: "", error });
167
+ }
168
+ else if (marker.kind === "interrupted_run") {
169
+ // Rendered as an error row: the run's tools already changed the
170
+ // repo, so the user needs to see it and decide what to do. We
171
+ // never replay it — that would duplicate those changes.
172
+ history.push({
173
+ role: "assistant",
174
+ text: "",
175
+ error: {
176
+ scope: "interrupted_run",
177
+ headline: "A run was interrupted",
178
+ message: "GG Coder stopped mid-run, so this turn is incomplete. Any files its tools already changed are still on disk.",
179
+ guidance: "Review the working tree, then re-send the request if you still want it.",
180
+ },
181
+ });
182
+ }
183
+ }
184
+ };
185
+ let nonSystemCount = 0;
186
+ // Turns/markers recorded before any build message (anchor 0) render at
187
+ // the top.
188
+ flushKen(0);
189
+ flushAutopilot(0);
190
+ flushAppMarkers(0);
191
+ await replayMessagesInOrder(messages, async (msg, count) => {
192
+ nonSystemCount = count;
193
+ const visibility = getHistoryMessageVisibility(msg);
194
+ if (visibility === "hidden")
195
+ return;
196
+ if (msg.role === "tool") {
197
+ // Tool result messages: check for ImageContent blocks (screenshots,
198
+ // generated images) and emit a toolImages entry.
199
+ for (const tr of msg.content) {
200
+ if (typeof tr.content === "string")
201
+ continue;
202
+ const imageBlocks = tr.content.filter((c) => c.type === "image");
203
+ if (imageBlocks.length === 0)
204
+ continue;
205
+ // Extract the path from the text block so the restored image
206
+ // stays clickable (read / screenshot / generate_image formats).
207
+ const textBlock = tr.content.find((c) => c.type === "text" && "text" in c && typeof c.text === "string");
208
+ const textContent = textBlock && textBlock.type === "text" ? textBlock.text : "";
209
+ const imgPaths = extractToolImagePaths(textContent);
210
+ // Downscale each image for the webview preview. Paths pair with
211
+ // image blocks in order (a tool saves one file per image).
212
+ const toolImages = [];
213
+ let blockIndex = 0;
214
+ for (const block of imageBlocks) {
215
+ if (block.type !== "image")
216
+ continue;
217
+ const imgPath = imgPaths[blockIndex++];
218
+ const previewBuf = await downscaleForPreview(Buffer.from(block.data, "base64"));
219
+ toolImages.push({
220
+ src: `data:${block.mediaType};base64,${previewBuf.toString("base64")}`,
221
+ path: imgPath,
222
+ });
223
+ }
224
+ // generate_image persists only its first image's pixels; the
225
+ // rest exist only on disk, so preview them from their files.
226
+ // Skip silently if a file was moved or deleted since.
227
+ const extraPaths = toolNameById.get(tr.toolCallId) === "generate_image"
228
+ ? imgPaths.slice(blockIndex)
229
+ : [];
230
+ for (const extraPath of extraPaths) {
231
+ const mediaType = IMAGE_MEDIA_TYPES[path.extname(extraPath).toLowerCase()];
232
+ if (!mediaType)
233
+ continue;
234
+ const raw = await readFileBounded(extraPath).catch(() => null);
235
+ if (!raw)
236
+ continue;
237
+ const previewBuf = await downscaleForPreview(raw);
238
+ toolImages.push({
239
+ src: `data:${mediaType};base64,${previewBuf.toString("base64")}`,
240
+ path: extraPath,
241
+ });
242
+ }
243
+ if (toolImages.length > 0) {
244
+ history.push({
245
+ role: "assistant",
246
+ text: "",
247
+ toolImages,
248
+ });
249
+ }
250
+ }
251
+ return;
252
+ }
253
+ // User or assistant message — text/hook/command/compacted extraction,
254
+ // plus sub-agent group detection for assistant tool_calls.
255
+ if (msg.role === "user") {
256
+ // Rebuild the live bubble: strip the steering wrapper, drop
257
+ // attachment/file notes the model saw but the bubble never showed.
258
+ const restored = restoreUserRow(msg.content, msg.provenance);
259
+ const text = restored.text;
260
+ const hook = msg.provenance ? null : detectHookKind(text);
261
+ const compacted = visibility === "summary" ||
262
+ (!msg.provenance && !hook && text.startsWith("[Previous conversation summary]"));
263
+ const hint = userHintByCount.get(nonSystemCount);
264
+ // The typed invocation persisted alongside the prompt is
265
+ // authoritative. Reversing the expanded body only works while the
266
+ // template is byte-identical, and templates drift (edited
267
+ // `.gg/commands/*.md`, reworded built-ins, app-vs-CLI phrasing) —
268
+ // after which the resumed session dumped the raw multi-KB body
269
+ // instead of the `/name` chip. Older sessions have no hint, so the
270
+ // body match stays as the fallback.
271
+ const command = !hook && !compacted
272
+ ? resolveRestoredCommand(typeof hint?.command === "string" ? hint.command : null, text, commandCandidates)
273
+ : null;
274
+ // Autopilot injected this turn — live showed only the Ken-tinted
275
+ // marker for it, never a user bubble. Emitting one here would print
276
+ // the injected instruction a second time, unstyled.
277
+ //
278
+ // Pushed background-status updates are skipped for the same reason:
279
+ // the live run rendered no bubble for them, so showing them here
280
+ // would fill a reopened session with machine-facing status lines
281
+ // the user never saw while working.
282
+ if ((!msg.provenance || (!restored.autopilotInjected && !restored.notification)) &&
283
+ (text.trim() || restored.images.length > 0)) {
284
+ history.push({
285
+ role: "user",
286
+ text: command ?? text,
287
+ images: restored.images,
288
+ hook,
289
+ command: command !== null,
290
+ compacted,
291
+ // Markers accumulate across continuation files (each rewrite
292
+ // re-persists prior ones) but only the LATEST summary row
293
+ // survives compaction — so consume from the newest end.
294
+ ...(compacted && compactionCounts.length > 0
295
+ ? { compactionCounts: compactionCounts.pop() }
296
+ : {}),
297
+ ...(hint?.kenSent === true ? { kenSent: true } : {}),
298
+ ...(Array.isArray(hint?.enhancements) ? { enhancements: hint.enhancements } : {}),
299
+ });
300
+ // Live showed the video-capability warning right after the bubble.
301
+ if (restored.videoWarning) {
302
+ history.push({ role: "assistant", text: "", infoKind: "video_warning" });
303
+ }
304
+ }
305
+ }
306
+ else if (!hiddenIdealDrafts.has(msg)) {
307
+ // Assistant: one wire row per persisted text block — live streaming
308
+ // splits bubbles at server_tool_call boundaries, and the persisted
309
+ // content keeps those blocks separate. Ideal-review candidate drafts
310
+ // are intentionally omitted to match the live pre-final hook flow.
311
+ for (const blockText of restoreAssistantTexts(msg.content)) {
312
+ history.push({
313
+ role: "assistant",
314
+ text: blockText,
315
+ images: [],
316
+ hook: null,
317
+ command: false,
318
+ compacted: false,
319
+ });
320
+ }
321
+ }
322
+ // Assistant tool_call blocks: detect sub-agent delegations.
323
+ if (msg.role === "assistant" && typeof msg.content !== "string") {
324
+ const subagentCalls = msg.content.filter((c) => c.type === "tool_call" && (c.name === "subagent" || c.name === "spawn_agent"));
325
+ if (subagentCalls.length > 0) {
326
+ const agents = subagentCalls.flatMap((c) => {
327
+ const result = toolResultMap.get(c.id);
328
+ // Async workers are intentionally non-resumable; restored rows are historical.
329
+ const status = result?.isError ? "error" : "done";
330
+ if (c.name === "spawn_agent") {
331
+ // One row per child: a batch call starts several.
332
+ return spawnedTasks(c.args).map((spawn) => ({
333
+ agentName: spawn.task_name ?? spawn.agent,
334
+ status,
335
+ toolUseCount: 0,
336
+ }));
337
+ }
338
+ return [
339
+ {
340
+ agentName: typeof c.args?.agent === "string" ? c.args.agent : undefined,
341
+ status,
342
+ toolUseCount: 0,
343
+ },
344
+ ];
345
+ });
346
+ history.push({
347
+ role: "assistant",
348
+ text: "",
349
+ subagentGroup: agents,
350
+ });
351
+ }
352
+ }
353
+ }, (count) => {
354
+ // Markers flush after every physical message, including tools and
355
+ // provenance-hidden runtime context.
356
+ flushKen(count);
357
+ flushAutopilot(count);
358
+ flushAppMarkers(count);
359
+ });
360
+ // Flush remaining Ken turns whose anchor is at/after the message count so
361
+ // none are dropped. Autopilot/app markers beyond the restored message
362
+ // count were already filtered above; any remaining marker here is valid.
363
+ for (const count of [...kenByCount.keys()].sort((a, b) => a - b))
364
+ flushKen(count);
365
+ for (const count of [...autopilotByCount.keys()].sort((a, b) => a - b))
366
+ flushAutopilot(count);
367
+ for (const count of [...appMarkersByCount.keys()].sort((a, b) => a - b))
368
+ flushAppMarkers(count);
369
+ json(res, 200, { history });
370
+ })();
371
+ return true;
372
+ }
373
+ return false;
374
+ }
375
+ //# sourceMappingURL=history-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-routes.js","sourceRoot":"","sources":["../../src/app-sidecar/history-routes.ts"],"names":[],"mappings":"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"}