@oh-my-pi/pi-coding-agent 15.10.10 → 15.10.11

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 (345) hide show
  1. package/CHANGELOG.md +95 -4
  2. package/dist/cli.js +23087 -0
  3. package/dist/tokenizers.linux-x64-gnu-xcjh3jwk.node +0 -0
  4. package/dist/types/async/job-manager.d.ts +18 -0
  5. package/dist/types/cli/args.d.ts +1 -1
  6. package/dist/types/cli/dry-balance-cli.d.ts +1 -1
  7. package/dist/types/cli/gallery-cli.d.ts +1 -1
  8. package/dist/types/cli/gallery-fixtures/types.d.ts +1 -1
  9. package/dist/types/cli/usage-cli.d.ts +72 -0
  10. package/dist/types/commands/launch.d.ts +1 -1
  11. package/dist/types/commands/read.d.ts +1 -1
  12. package/dist/types/commands/usage.d.ts +25 -0
  13. package/dist/types/config/append-only-context-mode.d.ts +2 -1
  14. package/dist/types/config/model-discovery.d.ts +55 -0
  15. package/dist/types/config/model-registry.d.ts +7 -219
  16. package/dist/types/config/model-resolver.d.ts +16 -10
  17. package/dist/types/config/model-roles.d.ts +28 -0
  18. package/dist/types/config/models-config-schema.d.ts +523 -42
  19. package/dist/types/config/models-config.d.ts +385 -0
  20. package/dist/types/config/settings-schema.d.ts +12 -7
  21. package/dist/types/config/settings.d.ts +1 -1
  22. package/dist/types/debug/log-viewer.d.ts +1 -1
  23. package/dist/types/debug/raw-sse.d.ts +1 -1
  24. package/dist/types/eval/backend.d.ts +0 -2
  25. package/dist/types/eval/idle-timeout.d.ts +0 -4
  26. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  27. package/dist/types/export/html/template.generated.d.ts +1 -1
  28. package/dist/types/extensibility/extensions/types.d.ts +3 -3
  29. package/dist/types/hindsight/mental-models.d.ts +17 -8
  30. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  31. package/dist/types/internal-urls/types.d.ts +1 -1
  32. package/dist/types/lsp/edits.d.ts +9 -0
  33. package/dist/types/lsp/index.d.ts +2 -2
  34. package/dist/types/lsp/types.d.ts +2 -0
  35. package/dist/types/lsp/utils.d.ts +3 -0
  36. package/dist/types/mcp/json-rpc.d.ts +5 -0
  37. package/dist/types/mnemopi/state.d.ts +11 -1
  38. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  39. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  40. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  41. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  42. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  43. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  44. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  45. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  46. package/dist/types/modes/components/footer.d.ts +1 -1
  47. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  48. package/dist/types/modes/components/hook-input.d.ts +4 -0
  49. package/dist/types/modes/components/hook-selector.d.ts +1 -1
  50. package/dist/types/modes/components/model-selector.d.ts +1 -1
  51. package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
  52. package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
  53. package/dist/types/modes/components/session-selector.d.ts +1 -1
  54. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  55. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  56. package/dist/types/modes/components/transcript-container.d.ts +25 -6
  57. package/dist/types/modes/components/tree-selector.d.ts +1 -1
  58. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  59. package/dist/types/modes/components/user-message.d.ts +2 -1
  60. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  61. package/dist/types/modes/components/welcome.d.ts +19 -3
  62. package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
  63. package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
  64. package/dist/types/modes/interactive-mode.d.ts +1 -1
  65. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
  66. package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
  67. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
  68. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  69. package/dist/types/modes/types.d.ts +2 -1
  70. package/dist/types/session/agent-session.d.ts +1 -1
  71. package/dist/types/session/auth-broker-config.d.ts +4 -0
  72. package/dist/types/session/session-manager.d.ts +1 -1
  73. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  74. package/dist/types/ssh/connection-manager.d.ts +8 -0
  75. package/dist/types/task/parallel.d.ts +2 -2
  76. package/dist/types/task/worktree.d.ts +2 -0
  77. package/dist/types/tools/ask.d.ts +4 -0
  78. package/dist/types/tools/conflict-detect.d.ts +16 -0
  79. package/dist/types/tools/github-cache.d.ts +7 -0
  80. package/dist/types/tools/sqlite-reader.d.ts +3 -0
  81. package/dist/types/tui/output-block.d.ts +3 -3
  82. package/dist/types/utils/changelog.d.ts +8 -0
  83. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  84. package/dist/types/web/scrapers/types.d.ts +12 -0
  85. package/dist/types/web/search/providers/codex.d.ts +1 -1
  86. package/dist/types/web/search/providers/gemini.d.ts +1 -1
  87. package/examples/extensions/tools.ts +5 -4
  88. package/package.json +14 -11
  89. package/scripts/build-binary.ts +18 -23
  90. package/scripts/bundle-dist.ts +81 -0
  91. package/scripts/{dev-launch → omp} +1 -1
  92. package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
  93. package/src/async/job-manager.ts +57 -3
  94. package/src/autoresearch/dashboard.ts +1 -1
  95. package/src/autoresearch/prompt-setup.md +6 -6
  96. package/src/autoresearch/prompt.md +6 -6
  97. package/src/capability/fs.ts +10 -0
  98. package/src/cli/args.ts +1 -1
  99. package/src/cli/auth-gateway-cli.ts +1 -3
  100. package/src/cli/dry-balance-cli.ts +1 -1
  101. package/src/cli/gallery-cli.ts +1 -1
  102. package/src/cli/gallery-fixtures/fs.ts +1 -1
  103. package/src/cli/gallery-fixtures/types.ts +5 -1
  104. package/src/cli/list-models.ts +2 -1
  105. package/src/cli/usage-cli.ts +603 -0
  106. package/src/cli-commands.ts +1 -0
  107. package/src/cli.ts +69 -5
  108. package/src/commands/complete.ts +1 -1
  109. package/src/commands/launch.ts +1 -1
  110. package/src/commands/read.ts +6 -3
  111. package/src/commands/usage.ts +35 -0
  112. package/src/commit/agentic/agent.ts +1 -1
  113. package/src/commit/model-selection.ts +1 -1
  114. package/src/config/append-only-context-mode.ts +6 -12
  115. package/src/config/model-discovery.ts +554 -0
  116. package/src/config/model-registry.ts +231 -1019
  117. package/src/config/model-resolver.ts +113 -156
  118. package/src/config/model-roles.ts +74 -0
  119. package/src/config/models-config-schema.ts +57 -8
  120. package/src/config/models-config.ts +129 -0
  121. package/src/config/settings-schema.ts +18 -4
  122. package/src/config/settings.ts +37 -1
  123. package/src/dap/client.ts +124 -37
  124. package/src/dap/session.ts +259 -158
  125. package/src/debug/log-viewer.ts +1 -1
  126. package/src/debug/raw-sse.ts +1 -1
  127. package/src/edit/diff.ts +47 -3
  128. package/src/edit/hashline/block-resolver.ts +20 -1
  129. package/src/edit/hashline/diff.ts +36 -1
  130. package/src/edit/hashline/execute.ts +8 -2
  131. package/src/edit/index.ts +16 -1
  132. package/src/edit/modes/patch.ts +52 -0
  133. package/src/edit/modes/replace.ts +56 -22
  134. package/src/edit/notebook.ts +22 -2
  135. package/src/edit/renderer.ts +36 -10
  136. package/src/eval/__tests__/completion-bridge.test.ts +1 -1
  137. package/src/eval/backend.ts +0 -2
  138. package/src/eval/completion-bridge.ts +2 -1
  139. package/src/eval/idle-timeout.ts +2 -9
  140. package/src/eval/js/context-manager.ts +6 -8
  141. package/src/eval/js/executor.ts +6 -2
  142. package/src/eval/js/index.ts +0 -2
  143. package/src/eval/js/shared/helpers.ts +5 -6
  144. package/src/eval/js/shared/local-module-loader.ts +1 -1
  145. package/src/eval/js/shared/prelude.txt +62 -1
  146. package/src/eval/js/shared/rewrite-imports.ts +40 -22
  147. package/src/eval/js/shared/runtime.ts +1 -1
  148. package/src/eval/py/index.ts +0 -2
  149. package/src/eval/py/kernel.ts +19 -0
  150. package/src/eval/py/runner.py +107 -3
  151. package/src/exec/bash-executor.ts +3 -1
  152. package/src/export/html/template.generated.ts +1 -1
  153. package/src/export/html/template.js +3 -1
  154. package/src/extensibility/extensions/types.ts +3 -2
  155. package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
  156. package/src/hindsight/mental-models.ts +59 -12
  157. package/src/hindsight/state.ts +6 -1
  158. package/src/internal-urls/artifact-protocol.ts +11 -2
  159. package/src/internal-urls/docs-index.generated.ts +8 -8
  160. package/src/internal-urls/issue-pr-protocol.ts +12 -5
  161. package/src/internal-urls/router.ts +1 -1
  162. package/src/internal-urls/types.ts +1 -1
  163. package/src/lib/xai-http.ts +1 -1
  164. package/src/lsp/client.ts +118 -38
  165. package/src/lsp/clients/biome-client.ts +101 -39
  166. package/src/lsp/edits.ts +143 -95
  167. package/src/lsp/index.ts +31 -22
  168. package/src/lsp/render.ts +1 -1
  169. package/src/lsp/types.ts +2 -0
  170. package/src/lsp/utils.ts +28 -10
  171. package/src/main.ts +165 -17
  172. package/src/mcp/json-rpc.ts +35 -5
  173. package/src/mcp/transports/stdio.ts +7 -1
  174. package/src/memories/index.ts +2 -1
  175. package/src/mnemopi/backend.ts +25 -3
  176. package/src/mnemopi/state.ts +38 -2
  177. package/src/modes/components/agent-dashboard.ts +10 -7
  178. package/src/modes/components/assistant-message.ts +19 -13
  179. package/src/modes/components/bash-execution.ts +1 -1
  180. package/src/modes/components/copy-selector.ts +1 -1
  181. package/src/modes/components/diff.ts +13 -2
  182. package/src/modes/components/dynamic-border.ts +12 -3
  183. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  184. package/src/modes/components/extensions/extension-list.ts +1 -1
  185. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  186. package/src/modes/components/footer.ts +1 -1
  187. package/src/modes/components/history-search.ts +1 -1
  188. package/src/modes/components/hook-editor.ts +8 -0
  189. package/src/modes/components/hook-input.ts +8 -0
  190. package/src/modes/components/hook-selector.ts +2 -2
  191. package/src/modes/components/model-selector.ts +4 -2
  192. package/src/modes/components/plan-review-overlay.ts +1 -1
  193. package/src/modes/components/session-observer-overlay.ts +2 -2
  194. package/src/modes/components/session-selector.ts +1 -1
  195. package/src/modes/components/settings-selector.ts +5 -1
  196. package/src/modes/components/status-line/component.ts +1 -1
  197. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  198. package/src/modes/components/transcript-container.ts +258 -53
  199. package/src/modes/components/tree-selector.ts +3 -3
  200. package/src/modes/components/user-message-selector.ts +1 -1
  201. package/src/modes/components/user-message.ts +17 -5
  202. package/src/modes/components/visual-truncate.ts +1 -1
  203. package/src/modes/components/welcome.ts +108 -26
  204. package/src/modes/controllers/command-controller.ts +10 -3
  205. package/src/modes/controllers/event-controller.ts +73 -4
  206. package/src/modes/controllers/input-controller.ts +1 -1
  207. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  208. package/src/modes/controllers/selector-controller.ts +1 -1
  209. package/src/modes/controllers/streaming-reveal.ts +85 -18
  210. package/src/modes/interactive-mode.ts +3 -9
  211. package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
  212. package/src/modes/setup-wizard/scenes/providers.ts +1 -1
  213. package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
  214. package/src/modes/setup-wizard/scenes/theme.ts +1 -1
  215. package/src/modes/setup-wizard/scenes/types.ts +1 -1
  216. package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
  217. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  218. package/src/modes/types.ts +2 -1
  219. package/src/prompts/agents/explore.md +2 -2
  220. package/src/prompts/agents/librarian.md +1 -2
  221. package/src/prompts/agents/oracle.md +1 -1
  222. package/src/prompts/agents/plan.md +5 -5
  223. package/src/prompts/agents/task.md +5 -5
  224. package/src/prompts/ci-green-request.md +5 -7
  225. package/src/prompts/goals/goal-budget-limit.md +2 -2
  226. package/src/prompts/goals/goal-continuation.md +4 -4
  227. package/src/prompts/goals/goal-mode-active.md +1 -1
  228. package/src/prompts/memories/read-path.md +1 -1
  229. package/src/prompts/memories/stage_one_system.md +2 -2
  230. package/src/prompts/review-custom-request.md +1 -1
  231. package/src/prompts/system/agent-creation-architect.md +2 -2
  232. package/src/prompts/system/auto-continue.md +1 -1
  233. package/src/prompts/system/background-tan-dispatch.md +1 -1
  234. package/src/prompts/system/btw-user.md +2 -2
  235. package/src/prompts/system/commit-message-system.md +13 -1
  236. package/src/prompts/system/custom-system-prompt.md +1 -1
  237. package/src/prompts/system/eager-todo.md +2 -2
  238. package/src/prompts/system/irc-incoming.md +1 -1
  239. package/src/prompts/system/manual-continue.md +1 -1
  240. package/src/prompts/system/omfg-user.md +3 -4
  241. package/src/prompts/system/orchestrate-notice.md +9 -9
  242. package/src/prompts/system/plan-mode-active.md +4 -4
  243. package/src/prompts/system/plan-mode-subagent.md +4 -5
  244. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  245. package/src/prompts/system/project-prompt.md +2 -2
  246. package/src/prompts/system/subagent-system-prompt.md +4 -4
  247. package/src/prompts/system/system-prompt.md +13 -24
  248. package/src/prompts/system/title-system.md +2 -2
  249. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  250. package/src/prompts/system/workflow-notice.md +1 -1
  251. package/src/prompts/tools/ast-edit.md +1 -1
  252. package/src/prompts/tools/ast-grep.md +2 -2
  253. package/src/prompts/tools/bash.md +5 -7
  254. package/src/prompts/tools/browser.md +7 -7
  255. package/src/prompts/tools/debug.md +1 -1
  256. package/src/prompts/tools/eval.md +3 -3
  257. package/src/prompts/tools/find.md +0 -1
  258. package/src/prompts/tools/github.md +8 -7
  259. package/src/prompts/tools/goal.md +1 -1
  260. package/src/prompts/tools/image-gen.md +1 -1
  261. package/src/prompts/tools/inspect-image-system.md +1 -1
  262. package/src/prompts/tools/irc.md +15 -15
  263. package/src/prompts/tools/lsp.md +2 -2
  264. package/src/prompts/tools/patch.md +2 -2
  265. package/src/prompts/tools/read.md +3 -4
  266. package/src/prompts/tools/recall.md +1 -1
  267. package/src/prompts/tools/reflect.md +1 -1
  268. package/src/prompts/tools/render-mermaid.md +2 -2
  269. package/src/prompts/tools/replace.md +4 -10
  270. package/src/prompts/tools/rewind.md +2 -2
  271. package/src/prompts/tools/search-tool-bm25.md +1 -9
  272. package/src/prompts/tools/search.md +0 -1
  273. package/src/prompts/tools/ssh.md +0 -4
  274. package/src/prompts/tools/task.md +2 -3
  275. package/src/prompts/tools/todo.md +1 -1
  276. package/src/sdk.ts +23 -10
  277. package/src/session/agent-session.ts +44 -10
  278. package/src/session/auth-broker-config.ts +30 -1
  279. package/src/session/session-manager.ts +2 -2
  280. package/src/session/streaming-output.ts +23 -2
  281. package/src/slash-commands/builtin-registry.ts +20 -0
  282. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  283. package/src/ssh/connection-manager.ts +27 -0
  284. package/src/task/commands.ts +2 -1
  285. package/src/task/executor.ts +61 -53
  286. package/src/task/index.ts +137 -60
  287. package/src/task/parallel.ts +3 -3
  288. package/src/task/render.ts +2 -2
  289. package/src/task/worktree.ts +64 -56
  290. package/src/thinking.ts +2 -1
  291. package/src/tiny/title-client.ts +26 -11
  292. package/src/tools/archive-reader.ts +30 -2
  293. package/src/tools/ask.ts +104 -21
  294. package/src/tools/ast-edit.ts +25 -5
  295. package/src/tools/auto-generated-guard.ts +20 -3
  296. package/src/tools/bash-interactive.ts +27 -7
  297. package/src/tools/bash.ts +54 -13
  298. package/src/tools/browser/launch.ts +11 -2
  299. package/src/tools/browser/readable.ts +19 -2
  300. package/src/tools/browser/registry.ts +4 -1
  301. package/src/tools/browser/render.ts +2 -2
  302. package/src/tools/browser/tab-supervisor.ts +55 -16
  303. package/src/tools/conflict-detect.ts +50 -4
  304. package/src/tools/debug.ts +1 -1
  305. package/src/tools/eval-render.ts +5 -5
  306. package/src/tools/eval.ts +0 -2
  307. package/src/tools/fetch.ts +33 -10
  308. package/src/tools/gh-cache-invalidation.ts +63 -8
  309. package/src/tools/gh-renderer.ts +1 -1
  310. package/src/tools/gh.ts +172 -29
  311. package/src/tools/github-cache.ts +70 -6
  312. package/src/tools/image-gen.ts +3 -9
  313. package/src/tools/irc.ts +5 -1
  314. package/src/tools/job.ts +1 -1
  315. package/src/tools/read.ts +202 -61
  316. package/src/tools/render-utils.ts +3 -3
  317. package/src/tools/resolve.ts +1 -1
  318. package/src/tools/search.ts +92 -29
  319. package/src/tools/sqlite-reader.ts +17 -5
  320. package/src/tools/ssh.ts +8 -8
  321. package/src/tools/todo.ts +38 -8
  322. package/src/tools/write.ts +118 -18
  323. package/src/tui/output-block.ts +4 -4
  324. package/src/utils/changelog.ts +27 -1
  325. package/src/utils/file-mentions.ts +2 -1
  326. package/src/web/scrapers/arxiv.ts +1 -1
  327. package/src/web/scrapers/go-pkg.ts +1 -1
  328. package/src/web/scrapers/iacr.ts +1 -1
  329. package/src/web/scrapers/readthedocs.ts +1 -1
  330. package/src/web/scrapers/twitter.ts +2 -1
  331. package/src/web/scrapers/types.ts +87 -8
  332. package/src/web/scrapers/wikipedia.ts +1 -1
  333. package/src/web/scrapers/youtube.ts +6 -1
  334. package/src/web/search/index.ts +1 -1
  335. package/src/web/search/providers/codex.ts +2 -1
  336. package/src/web/search/providers/gemini.ts +2 -3
  337. package/src/web/search/render.ts +8 -6
  338. package/dist/types/config/model-equivalence.d.ts +0 -24
  339. package/dist/types/config/model-id-affixes.d.ts +0 -12
  340. package/dist/types/config/model-provider-priority.d.ts +0 -1
  341. package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
  342. package/src/config/model-equivalence.ts +0 -875
  343. package/src/config/model-id-affixes.ts +0 -81
  344. package/src/config/model-provider-priority.ts +0 -56
  345. package/src/exec/idle-timeout-watchdog.ts +0 -126
@@ -0,0 +1,13 @@
1
+ export declare const DEFAULT_STATS_DASHBOARD_PORT = 3847;
2
+ export interface StatsDashboardArgs {
3
+ port: number;
4
+ }
5
+ export interface StatsDashboardLaunchResult {
6
+ url: string;
7
+ message: string;
8
+ }
9
+ export declare function parseStatsDashboardArgs(args: string): StatsDashboardArgs | {
10
+ error: string;
11
+ };
12
+ export declare function launchStatsDashboard(args: StatsDashboardArgs): Promise<StatsDashboardLaunchResult>;
13
+ export declare function stopStatsDashboard(): void;
@@ -22,6 +22,14 @@ interface SSHArgsOptions {
22
22
  }
23
23
  export declare function getHostInfo(hostName: string): Promise<SSHHostInfo | undefined>;
24
24
  export declare function getHostInfoForHost(host: SSHConnectionTarget): Promise<SSHHostInfo | undefined>;
25
+ /**
26
+ * Synchronous, probe-free host info lookup for startup paths.
27
+ *
28
+ * Checks the in-memory cache, then falls back to a synchronous read of the
29
+ * persisted host-info cache file. Never opens a connection or probes the
30
+ * remote host — callers get `undefined` when nothing is cached yet.
31
+ */
32
+ export declare function getCachedHostInfoSync(host: SSHConnectionTarget): SSHHostInfo | undefined;
25
33
  export declare function ensureHostInfo(host: SSHConnectionTarget): Promise<SSHHostInfo>;
26
34
  export declare function buildRemoteCommand(host: SSHConnectionTarget, command: string, options?: SSHArgsOptions): Promise<string[]>;
27
35
  export declare function ensureConnection(host: SSHConnectionTarget): Promise<void>;
@@ -19,10 +19,10 @@ export interface ParallelResult<R> {
19
19
  *
20
20
  * @param items - Items to process
21
21
  * @param concurrency - Maximum concurrent operations
22
- * @param fn - Async function to execute for each item
22
+ * @param fn - Async function to execute for each item; receives a worker signal that fires on abort or fail-fast so in-flight siblings can cancel
23
23
  * @param signal - Optional abort signal to stop scheduling new work
24
24
  */
25
- export declare function mapWithConcurrencyLimit<T, R>(items: T[], concurrency: number, fn: (item: T, index: number) => Promise<R>, signal?: AbortSignal): Promise<ParallelResult<R>>;
25
+ export declare function mapWithConcurrencyLimit<T, R>(items: T[], concurrency: number, fn: (item: T, index: number, signal: AbortSignal) => Promise<R>, signal?: AbortSignal): Promise<ParallelResult<R>>;
26
26
  /**
27
27
  * Simple counting semaphore for limiting concurrency across independently-scheduled async work.
28
28
  */
@@ -78,6 +78,8 @@ export interface MergeBranchResult {
78
78
  merged: string[];
79
79
  failed: string[];
80
80
  conflict?: string;
81
+ /** Set when cherry-picks landed on HEAD but restoring the stashed working tree failed. */
82
+ stashConflict?: string;
81
83
  }
82
84
  /**
83
85
  * Cherry-pick task branch commits sequentially onto HEAD.
@@ -41,6 +41,8 @@ export interface QuestionResult {
41
41
  multi: boolean;
42
42
  selectedOptions: string[];
43
43
  customInput?: string;
44
+ /** True when the answer was auto-selected because the dialog timed out. */
45
+ timedOut?: boolean;
44
46
  }
45
47
  export interface AskToolDetails {
46
48
  question?: string;
@@ -48,6 +50,8 @@ export interface AskToolDetails {
48
50
  multi?: boolean;
49
51
  selectedOptions?: string[];
50
52
  customInput?: string;
53
+ /** True when the answer was auto-selected because the dialog timed out. */
54
+ timedOut?: boolean;
51
55
  /** Multi-part question mode */
52
56
  results?: QuestionResult[];
53
57
  }
@@ -128,6 +128,22 @@ export declare function parseConflictUri(raw: string): ParsedConflictUri | null;
128
128
  * has actually been altered or removed.
129
129
  */
130
130
  export declare function spliceConflict(originalText: string, entry: ConflictEntry, replacement: string): string;
131
+ /**
132
+ * True when two registered blocks record the same marker-block content
133
+ * (labels and all sides). Out-of-band edits can shift a block's line
134
+ * numbers between reads, registering a fresh id while the stale one
135
+ * persists; callers use content identity to treat a locate-miss for the
136
+ * stale twin as "already resolved" instead of a hard failure.
137
+ */
138
+ export declare function conflictRegionsEqual(a: ConflictBlock, b: ConflictBlock): boolean;
139
+ /**
140
+ * True when the entry's recorded marker block still occurs in `content`
141
+ * (LF-normalized — recorded sections are stored LF). Distinguishes a stale
142
+ * re-registration of a just-resolved region (no longer present) from a
143
+ * DISTINCT conflict block that happens to be byte-identical (still present
144
+ * elsewhere in the file and must stay addressable).
145
+ */
146
+ export declare function conflictRegionPresent(content: string, entry: ConflictBlock): boolean;
131
147
  /**
132
148
  * Expand `@ours` / `@theirs` / `@base` / `@both` line tokens against the
133
149
  * recorded sections of `entry`. A token only triggers when it is the
@@ -69,6 +69,13 @@ export declare function invalidate(repo: string, kind: CacheKind, number: number
69
69
  export declare function invalidateAllForNumber(number: number, repo?: string): void;
70
70
  /** Drop every cached row. Test helper. */
71
71
  export declare function clearAll(): void;
72
+ /**
73
+ * Drop every cached row for a repo, or all rows when the repo is unknown.
74
+ * Fallback for current-branch `gh pr merge`/`gh pr close`-style mutations
75
+ * where the bash command names no PR number or URL, so the target row cannot
76
+ * be identified. Over-invalidation is deliberate (see module header).
77
+ */
78
+ export declare function invalidateAllForRepo(repo?: string): void;
72
79
  /**
73
80
  * Test/maintenance helper. Closes and forgets the cached connection so the
74
81
  * next access reopens against (possibly) a different DB path.
@@ -1,5 +1,7 @@
1
1
  import type { Database } from "bun:sqlite";
2
2
  export declare function looksLikeSqlite(bytes: Uint8Array): boolean;
3
+ /** Row cap for raw `?q=` SQL — protects against `SELECT *` on multi-million-row tables. */
4
+ export declare const MAX_RAW_QUERY_ROWS = 1000;
3
5
  export interface SqlitePathCandidate {
4
6
  sqlitePath: string;
5
7
  subPath: string;
@@ -84,6 +86,7 @@ export declare function getRowByRowId(db: Database, table: string, key: string):
84
86
  export declare function executeReadQuery(db: Database, sql: string): {
85
87
  columns: string[];
86
88
  rows: Record<string, unknown>[];
89
+ truncated: boolean;
87
90
  };
88
91
  export declare function insertRow(db: Database, table: string, data: Record<string, unknown>): void;
89
92
  export declare function updateRowByKey(db: Database, table: string, pk: {
@@ -10,7 +10,7 @@ export interface OutputBlockOptions {
10
10
  state?: State;
11
11
  sections?: Array<{
12
12
  label?: string;
13
- lines: string[];
13
+ lines: readonly string[];
14
14
  separator?: boolean;
15
15
  }>;
16
16
  width: number;
@@ -36,8 +36,8 @@ export declare function renderOutputBlock(options: OutputBlockOptions, theme: Th
36
36
  */
37
37
  export declare class CachedOutputBlock {
38
38
  #private;
39
- /** Render with caching. Returns cached result if options haven't changed. */
40
- render(options: OutputBlockOptions, theme: Theme): string[];
39
+ /** Render with caching. Returns the cached (shared, caller-immutable) lines if options haven't changed. */
40
+ render(options: OutputBlockOptions, theme: Theme): readonly string[];
41
41
  /** Invalidate the cache, forcing a rebuild on next render. */
42
42
  invalidate(): void;
43
43
  }
@@ -23,3 +23,11 @@ export declare function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry):
23
23
  */
24
24
  export declare function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[];
25
25
  export { getChangelogPath } from "../config";
26
+ /**
27
+ * Last omp version whose changelog the user has seen. Stored as a plain-text
28
+ * marker file (`~/.omp/agent/last-changelog-version`) rather than in
29
+ * `config.yml`, so version bumps never dirty user-tracked config files.
30
+ */
31
+ export declare function readLastChangelogVersion(agentDir?: string): Promise<string | undefined>;
32
+ /** Persist the last-seen changelog version marker. Best-effort: failures are logged, never thrown. */
33
+ export declare function writeLastChangelogVersion(version: string, agentDir?: string): Promise<void>;
@@ -1,2 +1,5 @@
1
+ /**
2
+ * Read the Docs handler for web-fetch
3
+ */
1
4
  import { type SpecialHandler } from "./types";
2
5
  export declare const handleReadTheDocs: SpecialHandler;
@@ -27,6 +27,12 @@ export interface LoadPageOptions {
27
27
  body?: string;
28
28
  maxBytes?: number;
29
29
  signal?: AbortSignal;
30
+ /**
31
+ * Return true to skip reading the response body for this content type
32
+ * (lowercased mime, no params). The caller is expected to re-fetch the
33
+ * payload as binary; this avoids streaming + decoding huge binaries twice.
34
+ */
35
+ skipBodyForContentType?: (contentType: string) => boolean;
30
36
  }
31
37
  export interface LoadPageResult {
32
38
  content: string;
@@ -34,6 +40,12 @@ export interface LoadPageResult {
34
40
  finalUrl: string;
35
41
  ok: boolean;
36
42
  status?: number;
43
+ /** True when the body was cut mid-stream at maxBytes. */
44
+ truncated?: boolean;
45
+ /** Last transport-level error message when ok is false. */
46
+ error?: string;
47
+ /** True when the body read was skipped via skipBodyForContentType. */
48
+ bodySkipped?: boolean;
37
49
  }
38
50
  /**
39
51
  * Fetch a page with timeout and size limit
@@ -1,4 +1,4 @@
1
- import { type AuthStorage, type FetchImpl } from "@oh-my-pi/pi-ai";
1
+ import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
2
2
  import type { SearchResponse } from "../../../web/search/types";
3
3
  import type { SearchParams } from "./base";
4
4
  import { SearchProvider } from "./base";
@@ -8,7 +8,7 @@
8
8
  * sibling SQLite store and never POSTs the broker sentinel to a Google token
9
9
  * endpoint.
10
10
  */
11
- import { type AuthStorage, type FetchImpl } from "@oh-my-pi/pi-ai";
11
+ import type { AuthStorage, FetchImpl } from "@oh-my-pi/pi-ai";
12
12
  import type { SearchResponse } from "../../../web/search/types";
13
13
  import type { SearchParams } from "./base";
14
14
  import { SearchProvider } from "./base";
@@ -68,7 +68,7 @@ export default function toolsExtension(pi: ExtensionAPI) {
68
68
  // Refresh tool list
69
69
  allTools = pi.getAllTools();
70
70
 
71
- await ctx.ui.custom((tui, theme, done) => {
71
+ await ctx.ui.custom((tui, theme, _keybindings, done) => {
72
72
  // Build settings items for each tool
73
73
  const items: SettingItem[] = allTools.map(tool => ({
74
74
  id: tool,
@@ -78,10 +78,11 @@ export default function toolsExtension(pi: ExtensionAPI) {
78
78
  }));
79
79
 
80
80
  const container = new Container();
81
+ const header: readonly string[] = [theme.fg("accent", theme.bold("Tool Configuration")), ""];
81
82
  container.addChild(
82
83
  new (class {
83
- render(_width: number) {
84
- return [theme.fg("accent", theme.bold("Tool Configuration")), ""];
84
+ render(_width: number): readonly string[] {
85
+ return header;
85
86
  }
86
87
  invalidate() {}
87
88
  })(),
@@ -110,7 +111,7 @@ export default function toolsExtension(pi: ExtensionAPI) {
110
111
  container.addChild(settingsList);
111
112
 
112
113
  const component = {
113
- render(width: number) {
114
+ render(width: number): readonly string[] {
114
115
  return container.render(width);
115
116
  },
116
117
  invalidate() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "15.10.10",
4
+ "version": "15.10.11",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -28,7 +28,7 @@
28
28
  "main": "./src/index.ts",
29
29
  "types": "./dist/types/index.d.ts",
30
30
  "bin": {
31
- "omp": "src/cli.ts"
31
+ "omp": "dist/cli.js"
32
32
  },
33
33
  "scripts": {
34
34
  "build": "bun scripts/build-binary.ts",
@@ -40,21 +40,22 @@
40
40
  "fmt": "biome format --write . && bun run format-prompts",
41
41
  "format-prompts": "bun scripts/format-prompts.ts",
42
42
  "generate-docs-index": "bun scripts/generate-docs-index.ts",
43
- "prepack": "bun scripts/generate-docs-index.ts",
43
+ "prepack": "bun scripts/generate-docs-index.ts && bun scripts/bundle-dist.ts",
44
44
  "generate-template": "bun scripts/generate-template.ts"
45
45
  },
46
46
  "dependencies": {
47
47
  "@agentclientprotocol/sdk": "0.22.1",
48
48
  "@babel/parser": "^7.29.7",
49
49
  "@mozilla/readability": "^0.6.0",
50
- "@oh-my-pi/hashline": "15.10.10",
51
- "@oh-my-pi/omp-stats": "15.10.10",
52
- "@oh-my-pi/pi-agent-core": "15.10.10",
53
- "@oh-my-pi/pi-ai": "15.10.10",
54
- "@oh-my-pi/pi-mnemopi": "15.10.10",
55
- "@oh-my-pi/pi-natives": "15.10.10",
56
- "@oh-my-pi/pi-tui": "15.10.10",
57
- "@oh-my-pi/pi-utils": "15.10.10",
50
+ "@oh-my-pi/hashline": "15.10.11",
51
+ "@oh-my-pi/omp-stats": "15.10.11",
52
+ "@oh-my-pi/pi-agent-core": "15.10.11",
53
+ "@oh-my-pi/pi-ai": "15.10.11",
54
+ "@oh-my-pi/pi-catalog": "15.10.11",
55
+ "@oh-my-pi/pi-mnemopi": "15.10.11",
56
+ "@oh-my-pi/pi-natives": "15.10.11",
57
+ "@oh-my-pi/pi-tui": "15.10.11",
58
+ "@oh-my-pi/pi-utils": "15.10.11",
58
59
  "@opentelemetry/api": "^1.9.1",
59
60
  "@opentelemetry/context-async-hooks": "^2.7.1",
60
61
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -87,6 +88,8 @@
87
88
  },
88
89
  "files": [
89
90
  "src",
91
+ "dist/cli.js",
92
+ "dist/*.node",
90
93
  "scripts",
91
94
  "examples",
92
95
  "README.md",
@@ -4,6 +4,7 @@ import { createRequire } from "node:module";
4
4
  import * as path from "node:path";
5
5
 
6
6
  const packageDir = path.join(import.meta.dir, "..");
7
+ const repoRoot = path.join(packageDir, "..", "..");
7
8
  const outputPath = path.join(packageDir, "dist", "omp");
8
9
 
9
10
  // Transformers.js is an optional, native-heavy dependency that is never bundled
@@ -19,9 +20,13 @@ function shouldAdhocSignDarwinBinary(): boolean {
19
20
  return process.platform === "darwin";
20
21
  }
21
22
 
22
- async function runCommand(command: string[], env: NodeJS.ProcessEnv = Bun.env): Promise<void> {
23
+ async function runCommand(
24
+ command: string[],
25
+ env: NodeJS.ProcessEnv = Bun.env,
26
+ cwd: string = packageDir,
27
+ ): Promise<void> {
23
28
  const proc = Bun.spawn(command, {
24
- cwd: packageDir,
29
+ cwd,
25
30
  env,
26
31
  stdout: "inherit",
27
32
  stderr: "inherit",
@@ -55,19 +60,8 @@ async function main(): Promise<void> {
55
60
  "--external",
56
61
  "mupdf",
57
62
  "--root",
58
- "../..",
59
- "./src/cli.ts",
60
- // Worker entrypoints. Bun's `--compile` discovers the literal in
61
- // `new Worker("…", …)` at each spawn site, but only actually
62
- // emits the worker into the bunfs root when it is listed here as
63
- // an explicit additional entry. Paths are relative to this
64
- // script's cwd (packages/coding-agent) and the `--root` above
65
- // (../..) makes them appear inside the binary at
66
- // `/$bunfs/root/packages/<pkg>/src/<worker>.js`, which is
67
- // exactly what the literals at the spawn sites resolve to.
68
- "../stats/src/sync-worker.ts",
69
- "./src/tools/browser/tab-worker-entry.ts",
70
- "./src/eval/js/worker-entry.ts",
63
+ ".",
64
+ "./packages/coding-agent/src/cli.ts",
71
65
  // Legacy pi-* extension compat entrypoints served by
72
66
  // `legacy-pi-compat.ts`. These are reached via computed bunfs paths
73
67
  // (which `--compile`'s static analyzer cannot trace), so each must be
@@ -77,17 +71,18 @@ async function main(): Promise<void> {
77
71
  // breaks the CLI entry when the same package's barrel appears as an
78
72
  // extra entrypoint (issue #1474), so legacy `pi-coding-agent` imports
79
73
  // resolve through `legacy-pi-coding-agent-shim.ts` instead.
80
- "../agent/src/index.ts",
81
- "../natives/native/index.js",
82
- "../tui/src/index.ts",
83
- "../utils/src/index.ts",
84
- "./src/extensibility/typebox.ts",
85
- "./src/extensibility/legacy-pi-ai-shim.ts",
86
- "./src/extensibility/legacy-pi-coding-agent-shim.ts",
74
+ "./packages/agent/src/index.ts",
75
+ "./packages/natives/native/index.js",
76
+ "./packages/tui/src/index.ts",
77
+ "./packages/utils/src/index.ts",
78
+ "./packages/coding-agent/src/extensibility/typebox.ts",
79
+ "./packages/coding-agent/src/extensibility/legacy-pi-ai-shim.ts",
80
+ "./packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts",
87
81
  "--outfile",
88
- "dist/omp",
82
+ "packages/coding-agent/dist/omp",
89
83
  ],
90
84
  buildEnv,
85
+ repoRoot,
91
86
  );
92
87
 
93
88
  // Bun 1.3.12 emits a truncated Mach-O signature on darwin builds.
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import * as fs from "node:fs/promises";
4
+ import * as path from "node:path";
5
+ import { isEnoent } from "@oh-my-pi/pi-utils";
6
+
7
+ const packageDir = path.join(import.meta.dir, "..");
8
+ const outDir = path.join(packageDir, "dist");
9
+ const cliPath = path.join(outDir, "cli.js");
10
+ const shebang = "#!/usr/bin/env bun\n";
11
+
12
+ async function runCommand(command: string[]): Promise<void> {
13
+ const proc = Bun.spawn(command, {
14
+ cwd: packageDir,
15
+ stdout: "inherit",
16
+ stderr: "inherit",
17
+ });
18
+ const exitCode = await proc.exited;
19
+ if (exitCode !== 0) throw new Error(`Command failed with exit code ${exitCode}: ${command.join(" ")}`);
20
+ }
21
+
22
+ async function ensureShebang(): Promise<void> {
23
+ const text = await Bun.file(cliPath).text();
24
+ if (text.startsWith(shebang)) return;
25
+ const withoutExisting = text.startsWith("#!") ? text.slice(text.indexOf("\n") + 1) : text;
26
+ await Bun.write(cliPath, shebang + withoutExisting);
27
+ }
28
+
29
+ function formatBytes(bytes: number): string {
30
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
31
+ return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;
32
+ }
33
+
34
+ async function cleanBundleOutputs(): Promise<void> {
35
+ // dist/ is shared with the dev binary (dist/omp); only remove this
36
+ // script's own outputs (entry bundle + copied native assets).
37
+ let entries: string[];
38
+ try {
39
+ entries = await fs.readdir(outDir);
40
+ } catch (err) {
41
+ if (isEnoent(err)) return;
42
+ throw err;
43
+ }
44
+ await Promise.all(
45
+ entries
46
+ .filter(entry => entry === "cli.js" || entry.endsWith(".node") || entry.endsWith(".js.map"))
47
+ .map(entry => fs.rm(path.join(outDir, entry), { force: true })),
48
+ );
49
+ }
50
+
51
+ async function main(): Promise<void> {
52
+ const start = Bun.nanoseconds();
53
+ await cleanBundleOutputs();
54
+ await runCommand([
55
+ "bun",
56
+ "build",
57
+ "--target=bun",
58
+ "--outdir",
59
+ "dist",
60
+ "--minify-whitespace",
61
+ "--minify-syntax",
62
+ "--keep-names",
63
+ "--external",
64
+ "mupdf",
65
+ "--external",
66
+ "@oh-my-pi/pi-natives",
67
+ "--external",
68
+ "@huggingface/transformers",
69
+ "--define",
70
+ 'process.env.PI_BUNDLED="true"',
71
+ "./src/cli.ts",
72
+ ]);
73
+ await ensureShebang();
74
+ const stat = await fs.stat(cliPath);
75
+ const elapsedMs = (Bun.nanoseconds() - start) / 1_000_000;
76
+ process.stdout.write(
77
+ `Bundled coding-agent CLI to dist/cli.js (${formatBytes(stat.size)}) in ${elapsedMs.toFixed(0)}ms\n`,
78
+ );
79
+ }
80
+
81
+ await main();
@@ -27,7 +27,7 @@ while [ -L "$self" ]; do
27
27
  done
28
28
  scripts_dir=$(CDPATH= cd -- "$(dirname -- "$self")" && pwd -P)
29
29
  cli=$scripts_dir/../src/cli.ts
30
- preload=$scripts_dir/dev-launch-preload.ts
30
+ preload=$scripts_dir/omp.ts
31
31
  timing_preload=$scripts_dir/../../utils/src/module-timer.ts
32
32
 
33
33
  launch_dir=${OMP_DEV_LAUNCH_DIR:-${HOME}/.omp/.dev-cwd}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Bun `--preload` shim for the omp dev launcher (`scripts/dev-launch`).
2
+ * Bun `--preload` shim for the omp dev launcher (`scripts/omp`).
3
3
  *
4
4
  * The launcher starts Bun from an empty, bunfig-free directory so a foreign
5
5
  * project's `bunfig.toml` `preload` cannot run inside the omp CLI: Bun reads
@@ -23,6 +23,12 @@ export interface AsyncJob {
23
23
  * supply an id (e.g. legacy tests, SDK consumers without an agent context).
24
24
  */
25
25
  ownerId?: string;
26
+ /**
27
+ * Job is registered but parked behind a caller-managed gate (e.g. a task
28
+ * batch semaphore). Queued jobs do not count toward the running-job limit
29
+ * until the caller invokes `markRunning()` from the run context.
30
+ */
31
+ queued?: boolean;
26
32
  }
27
33
 
28
34
  export interface AsyncJobManagerOptions {
@@ -53,6 +59,8 @@ export interface AsyncJobRegisterOptions {
53
59
  /** Registry id of the agent that owns this job; used to scope cancelAll. */
54
60
  ownerId?: string;
55
61
  onProgress?: (text: string, details?: Record<string, unknown>) => void | Promise<void>;
62
+ /** Register the job in queued state; see {@link AsyncJob.queued}. */
63
+ queued?: boolean;
56
64
  }
57
65
 
58
66
  /**
@@ -110,6 +118,17 @@ export class AsyncJobManager {
110
118
  this.#retentionMs = Math.max(0, Math.floor(options.retentionMs ?? DEFAULT_RETENTION_MS));
111
119
  }
112
120
 
121
+ /** True when the running-job count has reached the configured cap. */
122
+ get atCapacity(): boolean {
123
+ if (this.#disposed) return true;
124
+ // Mirror register(): queued jobs hold no execution slot.
125
+ let activeCount = 0;
126
+ for (const job of this.#jobs.values()) {
127
+ if (job.status === "running" && !job.queued) activeCount++;
128
+ }
129
+ return activeCount >= this.#maxRunningJobs;
130
+ }
131
+
113
132
  register(
114
133
  type: "bash" | "task",
115
134
  label: string,
@@ -117,14 +136,21 @@ export class AsyncJobManager {
117
136
  jobId: string;
118
137
  signal: AbortSignal;
119
138
  reportProgress: (text: string, details?: Record<string, unknown>) => Promise<void>;
139
+ /** Clear the queued flag once the job actually starts executing. */
140
+ markRunning: () => void;
120
141
  }) => Promise<string>,
121
142
  options?: AsyncJobRegisterOptions,
122
143
  ): string {
123
144
  if (this.#disposed) {
124
145
  throw new Error("Async job manager is disposed");
125
146
  }
126
- const runningCount = this.getRunningJobs().length;
127
- if (runningCount >= this.#maxRunningJobs) {
147
+ // Queued jobs hold no execution slot yet — only count jobs that are
148
+ // actually running so a large parked batch cannot starve registration.
149
+ let activeCount = 0;
150
+ for (const existing of this.#jobs.values()) {
151
+ if (existing.status === "running" && !existing.queued) activeCount++;
152
+ }
153
+ if (activeCount >= this.#maxRunningJobs) {
128
154
  throw new Error(
129
155
  `Background job limit reached (${this.#maxRunningJobs}). Wait for running jobs to finish or cancel one.`,
130
156
  );
@@ -144,6 +170,7 @@ export class AsyncJobManager {
144
170
  abortController,
145
171
  promise: Promise.resolve(),
146
172
  ownerId: options?.ownerId,
173
+ queued: options?.queued === true,
147
174
  };
148
175
 
149
176
  const reportProgress = async (text: string, details?: Record<string, unknown>): Promise<void> => {
@@ -159,7 +186,14 @@ export class AsyncJobManager {
159
186
  };
160
187
  job.promise = (async () => {
161
188
  try {
162
- const text = await run({ jobId: id, signal: abortController.signal, reportProgress });
189
+ const text = await run({
190
+ jobId: id,
191
+ signal: abortController.signal,
192
+ reportProgress,
193
+ markRunning: () => {
194
+ job.queued = false;
195
+ },
196
+ });
163
197
  if (job.status === "cancelled") {
164
198
  job.resultText = text;
165
199
  this.#scheduleEviction(id);
@@ -278,6 +312,26 @@ export class AsyncJobManager {
278
312
  return before - this.#deliveries.length;
279
313
  }
280
314
 
315
+ /**
316
+ * Lift a foreground-wait suppression set via `acknowledgeDeliveries`. If the
317
+ * job already finished while suppressed (its delivery enqueue was skipped),
318
+ * re-enqueue the completion so the result is still delivered exactly once.
319
+ */
320
+ resumeDeliveries(jobIds: string[]): void {
321
+ for (const rawId of jobIds) {
322
+ const jobId = rawId.trim();
323
+ if (!jobId) continue;
324
+ if (!this.#suppressedDeliveries.delete(jobId)) continue;
325
+ const job = this.#jobs.get(jobId);
326
+ if (!job || (job.status !== "completed" && job.status !== "failed")) continue;
327
+ const queued =
328
+ this.#deliveries.some(delivery => delivery.jobId === jobId) ||
329
+ this.#inFlightDeliveries.some(delivery => delivery.jobId === jobId);
330
+ if (queued) continue;
331
+ this.#enqueueDelivery(jobId, job.status === "completed" ? (job.resultText ?? "") : (job.errorText ?? ""));
332
+ }
333
+ }
334
+
281
335
  /**
282
336
  * Cancel running jobs. With `filter.ownerId` set, cancels only jobs the
283
337
  * matching agent registered; with no filter, cancels every running job
@@ -66,7 +66,7 @@ export function createDashboardController(): DashboardController {
66
66
 
67
67
  let scrollOffset = 0;
68
68
  return {
69
- render(width: number): string[] {
69
+ render(width: number): readonly string[] {
70
70
  const terminalRows = process.stdout.rows ?? 40;
71
71
  const header = renderExpandedHeader(runtime, width, theme);
72
72
  const body = renderDashboardLines(runtime, width, theme, 0);
@@ -18,16 +18,16 @@ Working directory: `{{working_dir}}`
18
18
  {{baseline_warning}}
19
19
  {{/if}}
20
20
 
21
- ### What you must produce
21
+ ### What you MUST produce
22
22
 
23
- Write `./autoresearch.sh` at the working directory. It is the canonical benchmark entrypoint and must:
23
+ Write `./autoresearch.sh` at the working directory. It is the canonical benchmark entrypoint and MUST:
24
24
 
25
25
  - exit 0 on success and non-zero on failure;
26
26
  - print the primary metric as a single line `METRIC <name>=<value>`;
27
27
  - print any secondary metrics as additional `METRIC <name>=<value>` lines;
28
28
  - run the same workload deterministically every time (no live network, no time-of-day dependencies, fixed seeds where applicable).
29
29
 
30
- You **may** edit anything else needed to make `autoresearch.sh` work — benchmark binaries, `Cargo.toml`, `package.json`, helper scripts, fixtures. All those edits are part of the harness baseline and will be committed for you when you call `init_experiment` on an autoresearch branch.
30
+ You MAY edit anything else needed to make `autoresearch.sh` work — benchmark binaries, `Cargo.toml`, `package.json`, helper scripts, fixtures. All those edits are part of the harness baseline and will be committed for you when you call `init_experiment` on an autoresearch branch.
31
31
 
32
32
  ### Steps
33
33
 
@@ -38,6 +38,6 @@ You **may** edit anything else needed to make `autoresearch.sh` work — benchma
38
38
 
39
39
  ### Rules
40
40
 
41
- - Do **not** call `run_experiment`, `log_experiment`, or `update_notes` yet. They will error with "no active autoresearch session" until `init_experiment` runs.
42
- - Do **not** treat a compile-only check as a benchmark. The harness must actually execute the workload and emit `METRIC`.
43
- - Do **not** create `autoresearch.md`, `autoresearch.checks.sh`, `autoresearch.program.md`, `autoresearch.ideas.md`, `autoresearch.jsonl`, `.autoresearch/`, or `autoresearch.config.json`. Session state is tracked for you.
41
+ - NEVER call `run_experiment`, `log_experiment`, or `update_notes` yet. They will error with "no active autoresearch session" until `init_experiment` runs.
42
+ - NEVER treat a compile-only check as a benchmark. The harness MUST actually execute the workload and emit `METRIC`.
43
+ - NEVER create `autoresearch.md`, `autoresearch.checks.sh`, `autoresearch.program.md`, `autoresearch.ideas.md`, `autoresearch.jsonl`, `.autoresearch/`, or `autoresearch.config.json`. Session state is tracked for you.