@oh-my-pi/pi-coding-agent 15.10.9 → 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 (352) hide show
  1. package/CHANGELOG.md +117 -0
  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 +20 -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 -16
  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/debug/terminal-info.d.ts +0 -1
  25. package/dist/types/eval/backend.d.ts +0 -2
  26. package/dist/types/eval/idle-timeout.d.ts +0 -4
  27. package/dist/types/eval/js/shared/rewrite-imports.d.ts +6 -6
  28. package/dist/types/export/html/template.generated.d.ts +1 -1
  29. package/dist/types/extensibility/extensions/types.d.ts +3 -3
  30. package/dist/types/hindsight/mental-models.d.ts +17 -8
  31. package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
  32. package/dist/types/internal-urls/types.d.ts +1 -1
  33. package/dist/types/lsp/edits.d.ts +9 -0
  34. package/dist/types/lsp/index.d.ts +2 -2
  35. package/dist/types/lsp/types.d.ts +2 -0
  36. package/dist/types/lsp/utils.d.ts +3 -0
  37. package/dist/types/mcp/json-rpc.d.ts +5 -0
  38. package/dist/types/mnemopi/state.d.ts +11 -1
  39. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  40. package/dist/types/modes/components/assistant-message.d.ts +3 -1
  41. package/dist/types/modes/components/bash-execution.d.ts +1 -1
  42. package/dist/types/modes/components/copy-selector.d.ts +1 -1
  43. package/dist/types/modes/components/dynamic-border.d.ts +1 -1
  44. package/dist/types/modes/components/extensions/extension-dashboard.d.ts +1 -1
  45. package/dist/types/modes/components/extensions/extension-list.d.ts +1 -1
  46. package/dist/types/modes/components/extensions/inspector-panel.d.ts +1 -1
  47. package/dist/types/modes/components/footer.d.ts +1 -1
  48. package/dist/types/modes/components/hook-editor.d.ts +5 -0
  49. package/dist/types/modes/components/hook-input.d.ts +4 -0
  50. package/dist/types/modes/components/hook-selector.d.ts +1 -1
  51. package/dist/types/modes/components/model-selector.d.ts +1 -1
  52. package/dist/types/modes/components/plan-review-overlay.d.ts +1 -1
  53. package/dist/types/modes/components/session-observer-overlay.d.ts +1 -1
  54. package/dist/types/modes/components/session-selector.d.ts +1 -1
  55. package/dist/types/modes/components/status-line/component.d.ts +1 -1
  56. package/dist/types/modes/components/tiny-title-download-progress.d.ts +1 -1
  57. package/dist/types/modes/components/transcript-container.d.ts +31 -26
  58. package/dist/types/modes/components/tree-selector.d.ts +1 -1
  59. package/dist/types/modes/components/user-message-selector.d.ts +1 -1
  60. package/dist/types/modes/components/user-message.d.ts +2 -1
  61. package/dist/types/modes/components/visual-truncate.d.ts +1 -1
  62. package/dist/types/modes/components/welcome.d.ts +19 -3
  63. package/dist/types/modes/controllers/mcp-command-controller.d.ts +1 -1
  64. package/dist/types/modes/controllers/streaming-reveal.d.ts +1 -1
  65. package/dist/types/modes/interactive-mode.d.ts +1 -1
  66. package/dist/types/modes/setup-wizard/scenes/sign-in.d.ts +1 -1
  67. package/dist/types/modes/setup-wizard/scenes/types.d.ts +1 -1
  68. package/dist/types/modes/setup-wizard/scenes/web-search.d.ts +1 -1
  69. package/dist/types/modes/setup-wizard/wizard-overlay.d.ts +1 -1
  70. package/dist/types/modes/types.d.ts +2 -1
  71. package/dist/types/session/agent-session.d.ts +1 -1
  72. package/dist/types/session/auth-broker-config.d.ts +4 -0
  73. package/dist/types/session/session-manager.d.ts +1 -1
  74. package/dist/types/slash-commands/helpers/stats-dashboard.d.ts +13 -0
  75. package/dist/types/ssh/connection-manager.d.ts +8 -0
  76. package/dist/types/task/discovery.d.ts +1 -2
  77. package/dist/types/task/parallel.d.ts +2 -2
  78. package/dist/types/task/worktree.d.ts +2 -0
  79. package/dist/types/tiny/title-client.d.ts +1 -1
  80. package/dist/types/tools/ask.d.ts +4 -0
  81. package/dist/types/tools/conflict-detect.d.ts +16 -0
  82. package/dist/types/tools/github-cache.d.ts +7 -0
  83. package/dist/types/tools/sqlite-reader.d.ts +3 -0
  84. package/dist/types/tools/todo.d.ts +2 -0
  85. package/dist/types/tui/output-block.d.ts +3 -3
  86. package/dist/types/utils/changelog.d.ts +8 -0
  87. package/dist/types/web/scrapers/readthedocs.d.ts +3 -0
  88. package/dist/types/web/scrapers/types.d.ts +12 -0
  89. package/dist/types/web/search/providers/codex.d.ts +1 -1
  90. package/dist/types/web/search/providers/gemini.d.ts +1 -1
  91. package/examples/extensions/tools.ts +5 -4
  92. package/package.json +14 -11
  93. package/scripts/build-binary.ts +18 -23
  94. package/scripts/bundle-dist.ts +81 -0
  95. package/scripts/{dev-launch → omp} +1 -1
  96. package/scripts/{dev-launch-preload.ts → omp.ts} +1 -1
  97. package/src/async/job-manager.ts +57 -3
  98. package/src/autoresearch/dashboard.ts +1 -1
  99. package/src/autoresearch/prompt-setup.md +6 -6
  100. package/src/autoresearch/prompt.md +6 -6
  101. package/src/capability/fs.ts +10 -0
  102. package/src/cli/args.ts +1 -1
  103. package/src/cli/auth-gateway-cli.ts +1 -3
  104. package/src/cli/dry-balance-cli.ts +1 -1
  105. package/src/cli/gallery-cli.ts +1 -1
  106. package/src/cli/gallery-fixtures/fs.ts +1 -1
  107. package/src/cli/gallery-fixtures/types.ts +5 -1
  108. package/src/cli/list-models.ts +7 -12
  109. package/src/cli/usage-cli.ts +603 -0
  110. package/src/cli-commands.ts +1 -0
  111. package/src/cli.ts +69 -5
  112. package/src/commands/complete.ts +1 -1
  113. package/src/commands/launch.ts +1 -1
  114. package/src/commands/read.ts +6 -3
  115. package/src/commands/usage.ts +35 -0
  116. package/src/commit/agentic/agent.ts +1 -1
  117. package/src/commit/model-selection.ts +1 -1
  118. package/src/config/append-only-context-mode.ts +6 -12
  119. package/src/config/model-discovery.ts +554 -0
  120. package/src/config/model-registry.ts +308 -1025
  121. package/src/config/model-resolver.ts +113 -156
  122. package/src/config/model-roles.ts +74 -0
  123. package/src/config/models-config-schema.ts +57 -8
  124. package/src/config/models-config.ts +129 -0
  125. package/src/config/settings-schema.ts +18 -14
  126. package/src/config/settings.ts +37 -1
  127. package/src/dap/client.ts +124 -37
  128. package/src/dap/session.ts +259 -158
  129. package/src/debug/log-viewer.ts +1 -1
  130. package/src/debug/raw-sse.ts +1 -1
  131. package/src/debug/terminal-info.ts +0 -3
  132. package/src/edit/diff.ts +95 -18
  133. package/src/edit/hashline/block-resolver.ts +20 -1
  134. package/src/edit/hashline/diff.ts +36 -1
  135. package/src/edit/hashline/execute.ts +8 -2
  136. package/src/edit/index.ts +16 -1
  137. package/src/edit/modes/patch.ts +52 -0
  138. package/src/edit/modes/replace.ts +56 -22
  139. package/src/edit/notebook.ts +22 -2
  140. package/src/edit/renderer.ts +36 -10
  141. package/src/eval/__tests__/completion-bridge.test.ts +1 -1
  142. package/src/eval/backend.ts +0 -2
  143. package/src/eval/completion-bridge.ts +2 -1
  144. package/src/eval/idle-timeout.ts +2 -9
  145. package/src/eval/js/context-manager.ts +6 -8
  146. package/src/eval/js/executor.ts +6 -2
  147. package/src/eval/js/index.ts +0 -2
  148. package/src/eval/js/shared/helpers.ts +5 -6
  149. package/src/eval/js/shared/local-module-loader.ts +1 -1
  150. package/src/eval/js/shared/prelude.txt +62 -1
  151. package/src/eval/js/shared/rewrite-imports.ts +49 -23
  152. package/src/eval/js/shared/runtime.ts +1 -1
  153. package/src/eval/py/index.ts +0 -2
  154. package/src/eval/py/kernel.ts +19 -0
  155. package/src/eval/py/runner.py +107 -3
  156. package/src/exec/bash-executor.ts +3 -1
  157. package/src/export/html/template.generated.ts +1 -1
  158. package/src/export/html/template.js +3 -1
  159. package/src/extensibility/extensions/types.ts +3 -2
  160. package/src/extensibility/plugins/legacy-pi-compat.ts +20 -3
  161. package/src/hindsight/mental-models.ts +59 -12
  162. package/src/hindsight/state.ts +6 -1
  163. package/src/internal-urls/artifact-protocol.ts +11 -2
  164. package/src/internal-urls/docs-index.generated.ts +10 -10
  165. package/src/internal-urls/issue-pr-protocol.ts +12 -5
  166. package/src/internal-urls/router.ts +1 -1
  167. package/src/internal-urls/types.ts +1 -1
  168. package/src/lib/xai-http.ts +1 -1
  169. package/src/lsp/client.ts +118 -38
  170. package/src/lsp/clients/biome-client.ts +101 -39
  171. package/src/lsp/edits.ts +143 -95
  172. package/src/lsp/index.ts +31 -22
  173. package/src/lsp/render.ts +1 -1
  174. package/src/lsp/types.ts +2 -0
  175. package/src/lsp/utils.ts +28 -10
  176. package/src/main.ts +165 -17
  177. package/src/mcp/json-rpc.ts +35 -5
  178. package/src/mcp/transports/stdio.ts +7 -1
  179. package/src/memories/index.ts +2 -1
  180. package/src/mnemopi/backend.ts +25 -3
  181. package/src/mnemopi/state.ts +38 -2
  182. package/src/modes/components/agent-dashboard.ts +10 -7
  183. package/src/modes/components/assistant-message.ts +19 -13
  184. package/src/modes/components/bash-execution.ts +1 -1
  185. package/src/modes/components/copy-selector.ts +1 -1
  186. package/src/modes/components/diff.ts +13 -2
  187. package/src/modes/components/dynamic-border.ts +12 -3
  188. package/src/modes/components/extensions/extension-dashboard.ts +8 -5
  189. package/src/modes/components/extensions/extension-list.ts +1 -1
  190. package/src/modes/components/extensions/inspector-panel.ts +1 -1
  191. package/src/modes/components/footer.ts +1 -1
  192. package/src/modes/components/history-search.ts +1 -1
  193. package/src/modes/components/hook-editor.ts +8 -0
  194. package/src/modes/components/hook-input.ts +8 -0
  195. package/src/modes/components/hook-selector.ts +2 -2
  196. package/src/modes/components/model-selector.ts +66 -54
  197. package/src/modes/components/plan-review-overlay.ts +1 -1
  198. package/src/modes/components/session-observer-overlay.ts +2 -2
  199. package/src/modes/components/session-selector.ts +1 -1
  200. package/src/modes/components/settings-selector.ts +5 -1
  201. package/src/modes/components/status-line/component.ts +1 -1
  202. package/src/modes/components/tiny-title-download-progress.ts +1 -1
  203. package/src/modes/components/transcript-container.ts +373 -141
  204. package/src/modes/components/tree-selector.ts +3 -3
  205. package/src/modes/components/user-message-selector.ts +1 -1
  206. package/src/modes/components/user-message.ts +17 -5
  207. package/src/modes/components/visual-truncate.ts +1 -1
  208. package/src/modes/components/welcome.ts +108 -26
  209. package/src/modes/controllers/command-controller.ts +10 -3
  210. package/src/modes/controllers/event-controller.ts +73 -49
  211. package/src/modes/controllers/input-controller.ts +5 -5
  212. package/src/modes/controllers/mcp-command-controller.ts +1 -1
  213. package/src/modes/controllers/selector-controller.ts +1 -5
  214. package/src/modes/controllers/streaming-reveal.ts +85 -18
  215. package/src/modes/interactive-mode.ts +5 -19
  216. package/src/modes/setup-wizard/scenes/glyph.ts +1 -1
  217. package/src/modes/setup-wizard/scenes/providers.ts +1 -1
  218. package/src/modes/setup-wizard/scenes/sign-in.ts +1 -1
  219. package/src/modes/setup-wizard/scenes/theme.ts +1 -1
  220. package/src/modes/setup-wizard/scenes/types.ts +1 -1
  221. package/src/modes/setup-wizard/scenes/web-search.ts +1 -1
  222. package/src/modes/setup-wizard/wizard-overlay.ts +1 -1
  223. package/src/modes/types.ts +2 -1
  224. package/src/prompts/agents/explore.md +2 -2
  225. package/src/prompts/agents/librarian.md +1 -2
  226. package/src/prompts/agents/oracle.md +1 -1
  227. package/src/prompts/agents/plan.md +5 -5
  228. package/src/prompts/agents/task.md +5 -5
  229. package/src/prompts/ci-green-request.md +5 -7
  230. package/src/prompts/goals/goal-budget-limit.md +2 -2
  231. package/src/prompts/goals/goal-continuation.md +4 -4
  232. package/src/prompts/goals/goal-mode-active.md +1 -1
  233. package/src/prompts/memories/read-path.md +1 -1
  234. package/src/prompts/memories/stage_one_system.md +2 -2
  235. package/src/prompts/review-custom-request.md +1 -1
  236. package/src/prompts/system/agent-creation-architect.md +2 -2
  237. package/src/prompts/system/auto-continue.md +1 -1
  238. package/src/prompts/system/background-tan-dispatch.md +1 -1
  239. package/src/prompts/system/btw-user.md +2 -2
  240. package/src/prompts/system/commit-message-system.md +13 -1
  241. package/src/prompts/system/custom-system-prompt.md +1 -1
  242. package/src/prompts/system/eager-todo.md +2 -2
  243. package/src/prompts/system/irc-incoming.md +1 -1
  244. package/src/prompts/system/manual-continue.md +1 -1
  245. package/src/prompts/system/omfg-user.md +3 -4
  246. package/src/prompts/system/orchestrate-notice.md +9 -9
  247. package/src/prompts/system/plan-mode-active.md +4 -4
  248. package/src/prompts/system/plan-mode-subagent.md +4 -5
  249. package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
  250. package/src/prompts/system/project-prompt.md +2 -2
  251. package/src/prompts/system/subagent-system-prompt.md +4 -4
  252. package/src/prompts/system/system-prompt.md +15 -26
  253. package/src/prompts/system/title-system.md +2 -2
  254. package/src/prompts/system/ttsr-tool-reminder.md +1 -1
  255. package/src/prompts/system/workflow-notice.md +1 -1
  256. package/src/prompts/tools/ast-edit.md +1 -1
  257. package/src/prompts/tools/ast-grep.md +2 -2
  258. package/src/prompts/tools/bash.md +8 -10
  259. package/src/prompts/tools/browser.md +7 -7
  260. package/src/prompts/tools/debug.md +1 -1
  261. package/src/prompts/tools/eval.md +3 -3
  262. package/src/prompts/tools/find.md +0 -1
  263. package/src/prompts/tools/github.md +8 -7
  264. package/src/prompts/tools/goal.md +1 -1
  265. package/src/prompts/tools/image-gen.md +1 -1
  266. package/src/prompts/tools/inspect-image-system.md +1 -1
  267. package/src/prompts/tools/irc.md +15 -15
  268. package/src/prompts/tools/lsp.md +2 -2
  269. package/src/prompts/tools/patch.md +2 -2
  270. package/src/prompts/tools/read.md +3 -4
  271. package/src/prompts/tools/recall.md +1 -1
  272. package/src/prompts/tools/reflect.md +1 -1
  273. package/src/prompts/tools/render-mermaid.md +2 -2
  274. package/src/prompts/tools/replace.md +4 -10
  275. package/src/prompts/tools/rewind.md +2 -2
  276. package/src/prompts/tools/search-tool-bm25.md +1 -9
  277. package/src/prompts/tools/search.md +0 -1
  278. package/src/prompts/tools/ssh.md +0 -4
  279. package/src/prompts/tools/task.md +2 -3
  280. package/src/prompts/tools/todo.md +6 -2
  281. package/src/sdk.ts +23 -10
  282. package/src/session/agent-session.ts +44 -10
  283. package/src/session/auth-broker-config.ts +30 -1
  284. package/src/session/session-manager.ts +2 -2
  285. package/src/session/streaming-output.ts +23 -2
  286. package/src/slash-commands/builtin-registry.ts +20 -0
  287. package/src/slash-commands/helpers/stats-dashboard.ts +85 -0
  288. package/src/ssh/connection-manager.ts +27 -0
  289. package/src/task/commands.ts +2 -1
  290. package/src/task/discovery.ts +17 -24
  291. package/src/task/executor.ts +61 -53
  292. package/src/task/index.ts +137 -60
  293. package/src/task/parallel.ts +3 -3
  294. package/src/task/render.ts +2 -2
  295. package/src/task/worktree.ts +64 -56
  296. package/src/thinking.ts +2 -1
  297. package/src/tiny/title-client.ts +32 -14
  298. package/src/tools/archive-reader.ts +30 -2
  299. package/src/tools/ask.ts +104 -21
  300. package/src/tools/ast-edit.ts +25 -5
  301. package/src/tools/auto-generated-guard.ts +20 -3
  302. package/src/tools/bash-interactive.ts +27 -7
  303. package/src/tools/bash.ts +54 -13
  304. package/src/tools/browser/launch.ts +11 -2
  305. package/src/tools/browser/readable.ts +19 -2
  306. package/src/tools/browser/registry.ts +4 -1
  307. package/src/tools/browser/render.ts +2 -2
  308. package/src/tools/browser/tab-supervisor.ts +55 -16
  309. package/src/tools/conflict-detect.ts +50 -4
  310. package/src/tools/debug.ts +1 -1
  311. package/src/tools/eval-render.ts +5 -5
  312. package/src/tools/eval.ts +0 -2
  313. package/src/tools/fetch.ts +33 -10
  314. package/src/tools/gh-cache-invalidation.ts +63 -8
  315. package/src/tools/gh-renderer.ts +1 -1
  316. package/src/tools/gh.ts +172 -29
  317. package/src/tools/github-cache.ts +70 -6
  318. package/src/tools/image-gen.ts +3 -9
  319. package/src/tools/irc.ts +5 -1
  320. package/src/tools/job.ts +1 -1
  321. package/src/tools/read.ts +202 -61
  322. package/src/tools/render-utils.ts +3 -3
  323. package/src/tools/resolve.ts +1 -1
  324. package/src/tools/search.ts +92 -29
  325. package/src/tools/sqlite-reader.ts +17 -5
  326. package/src/tools/ssh.ts +8 -8
  327. package/src/tools/todo.ts +51 -12
  328. package/src/tools/write.ts +118 -18
  329. package/src/tui/output-block.ts +4 -4
  330. package/src/utils/changelog.ts +27 -1
  331. package/src/utils/file-mentions.ts +2 -1
  332. package/src/web/scrapers/arxiv.ts +1 -1
  333. package/src/web/scrapers/go-pkg.ts +1 -1
  334. package/src/web/scrapers/iacr.ts +1 -1
  335. package/src/web/scrapers/readthedocs.ts +1 -1
  336. package/src/web/scrapers/twitter.ts +2 -1
  337. package/src/web/scrapers/types.ts +87 -8
  338. package/src/web/scrapers/wikipedia.ts +1 -1
  339. package/src/web/scrapers/youtube.ts +6 -1
  340. package/src/web/search/index.ts +1 -1
  341. package/src/web/search/providers/anthropic.ts +8 -2
  342. package/src/web/search/providers/codex.ts +2 -1
  343. package/src/web/search/providers/gemini.ts +2 -3
  344. package/src/web/search/render.ts +8 -6
  345. package/dist/types/config/model-equivalence.d.ts +0 -24
  346. package/dist/types/config/model-id-affixes.d.ts +0 -12
  347. package/dist/types/config/model-provider-priority.d.ts +0 -1
  348. package/dist/types/exec/idle-timeout-watchdog.d.ts +0 -18
  349. package/src/config/model-equivalence.ts +0 -875
  350. package/src/config/model-id-affixes.ts +0 -81
  351. package/src/config/model-provider-priority.ts +0 -56
  352. package/src/exec/idle-timeout-watchdog.ts +0 -126
@@ -861,7 +861,9 @@
861
861
  html += '<div class="tool-diff">';
862
862
  for (const line of diffLines) {
863
863
  const cls = line.match(/^\+/) ? 'diff-added' : line.match(/^-/) ? 'diff-removed' : 'diff-context';
864
- html += '<div class="' + cls + '">' + escapeHtml(replaceTabs(line)) + '</div>';
864
+ // Blank gap rows mark non-contiguous regions; show a unicode ellipsis.
865
+ const display = line.trim().length === 0 ? '\u2026' : replaceTabs(line);
866
+ html += '<div class="' + cls + '">' + escapeHtml(display) + '</div>';
865
867
  }
866
868
  html += '</div>';
867
869
  } else if (result) {
@@ -22,6 +22,7 @@ import type {
22
22
  Context,
23
23
  ImageContent,
24
24
  Model,
25
+ ModelSpec,
25
26
  ProviderResponseMetadata,
26
27
  SimpleStreamOptions,
27
28
  Static,
@@ -1081,7 +1082,7 @@ export interface ExtensionAPI {
1081
1082
  * id: "claude-sonnet-4@20250514",
1082
1083
  * name: "Claude Sonnet 4 (Vertex)",
1083
1084
  * reasoning: true,
1084
- * thinking: { mode: "anthropic-adaptive", minLevel: "minimal", maxLevel: "high" },
1085
+ * thinking: { mode: "anthropic-adaptive", efforts: ["minimal", "low", "medium", "high"] },
1085
1086
  * input: ["text", "image"],
1086
1087
  * cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
1087
1088
  * contextWindow: 200000,
@@ -1168,7 +1169,7 @@ export interface ProviderModelConfig {
1168
1169
  /** Custom headers for this model. */
1169
1170
  headers?: Record<string, string>;
1170
1171
  /** OpenAI compatibility settings. */
1171
- compat?: Model<Api>["compat"];
1172
+ compat?: ModelSpec<Api>["compat"];
1172
1173
  }
1173
1174
 
1174
1175
  /** Extension factory function type. Supports both sync and async initialization. */
@@ -110,9 +110,26 @@ function bunfsPath(...segments: string[]): string {
110
110
  return path.join(BUNFS_PACKAGE_ROOT, ...segments);
111
111
  }
112
112
 
113
+ function resolveBundledSelfPackageRoot(): string | undefined {
114
+ if (!process.env.PI_BUNDLED) return undefined;
115
+ try {
116
+ return path.dirname(Bun.resolveSync("@oh-my-pi/pi-coding-agent/package.json", import.meta.dir));
117
+ } catch {
118
+ return undefined;
119
+ }
120
+ }
121
+
122
+ const BUNDLED_SELF_PACKAGE_ROOT = resolveBundledSelfPackageRoot();
123
+
124
+ function sourceShimPath(file: string): string {
125
+ return BUNDLED_SELF_PACKAGE_ROOT
126
+ ? path.join(BUNDLED_SELF_PACKAGE_ROOT, "src", "extensibility", file)
127
+ : path.resolve(import.meta.dir, "..", file);
128
+ }
129
+
113
130
  const TYPEBOX_SHIM_PATH = BUNFS_PACKAGE_ROOT
114
131
  ? bunfsPath("coding-agent", "src", "extensibility", "typebox.js")
115
- : path.resolve(import.meta.dir, "../typebox.ts");
132
+ : sourceShimPath("typebox.ts");
116
133
 
117
134
  // Legacy extensions historically imported `Type` (and `Static`/`TSchema`) from
118
135
  // the package root of `@(scope)/pi-ai`. pi-ai 15.1.0 removed the runtime `Type`
@@ -124,7 +141,7 @@ const TYPEBOX_SHIM_PATH = BUNFS_PACKAGE_ROOT
124
141
  // against the bundled pi-ai package.
125
142
  const LEGACY_PI_AI_SHIM_PATH = BUNFS_PACKAGE_ROOT
126
143
  ? bunfsPath("coding-agent", "src", "extensibility", "legacy-pi-ai-shim.js")
127
- : path.resolve(import.meta.dir, "../legacy-pi-ai-shim.ts");
144
+ : sourceShimPath("legacy-pi-ai-shim.ts");
128
145
 
129
146
  // The coding-agent's own `./src/index.ts` cannot be listed as an extra
130
147
  // `bun --compile` entrypoint alongside the CLI entry without breaking binary
@@ -133,7 +150,7 @@ const LEGACY_PI_AI_SHIM_PATH = BUNFS_PACKAGE_ROOT
133
150
  // avoids that collision while re-exporting the canonical package surface.
134
151
  const LEGACY_PI_CODING_AGENT_SHIM_PATH = BUNFS_PACKAGE_ROOT
135
152
  ? bunfsPath("coding-agent", "src", "extensibility", "legacy-pi-coding-agent-shim.js")
136
- : path.resolve(import.meta.dir, "../legacy-pi-coding-agent-shim.ts");
153
+ : sourceShimPath("legacy-pi-coding-agent-shim.ts");
137
154
 
138
155
  // Package-root overrides. Shim entries are always applied because they replace
139
156
  // (or augment) the canonical surface even in non-compiled installs. The bunfs
@@ -26,8 +26,10 @@
26
26
  * retain side to emit them.
27
27
  *
28
28
  * Seed tags are baked from `seeds.json` plus, for `projectTagged: true`
29
- * entries, the active scope's `retainTags` (i.e. `project:<cwd>`). Untagged
30
- * seeds (e.g. `user-preferences`) read every memory in the bank the
29
+ * entries, the active scope's `retainTags` (i.e. `project:<cwd>`). In
30
+ * `per-project-tagged`, those project seeds also get project-suffixed ids so
31
+ * each tag can own its conventions/decisions models in the shared bank.
32
+ * Untagged seeds (e.g. `user-preferences`) read every memory in the bank — the
31
33
  * reflect call applies no tag filter when `tags` is empty.
32
34
  *
33
35
  * Seed lifecycle is **create-only**: changes to `source_query`, `tags`,
@@ -72,31 +74,52 @@ export interface MentalModelSeed {
72
74
  sourceQuery: string;
73
75
  tags: string[];
74
76
  maxTokens?: number;
77
+ /** Legacy unqualified seed ids accepted as already-present when tags match. */
78
+ legacyIds?: string[];
75
79
  trigger?: MentalModelTrigger;
76
80
  }
77
81
 
78
82
  /**
79
83
  * Resolve the seed list that applies to the active bank scope. Per-project
80
84
  * seeds are skipped in `global` mode (where there is no project axis) and
81
- * `projectTagged` seeds inherit the scope's `retainTags`.
85
+ * `projectTagged` seeds inherit the scope's `retainTags`. In shared tagged
86
+ * banks, project seeds use project-suffixed ids and accept matching legacy
87
+ * bare ids as already present.
82
88
  */
83
89
  export function resolveSeedsForScope(scope: BankScope, scoping: HindsightScoping): MentalModelSeed[] {
84
90
  const out: MentalModelSeed[] = [];
85
91
  for (const seed of BUILTIN_SEEDS) {
86
92
  if (!seed.scopes.includes(scoping)) continue;
87
93
  const tags = collectSeedTags(seed, scope);
94
+ const id = resolveSeedId(seed, tags, scoping);
88
95
  out.push({
89
- id: seed.id,
96
+ id,
90
97
  name: seed.name,
91
98
  sourceQuery: seed.source_query,
92
99
  tags,
93
100
  maxTokens: seed.max_tokens,
94
101
  trigger: seed.trigger,
102
+ legacyIds: id === seed.id ? undefined : [seed.id],
95
103
  });
96
104
  }
97
105
  return out;
98
106
  }
99
107
 
108
+ const PROJECT_TAG_PREFIX = "project:";
109
+
110
+ function resolveSeedId(seed: RawSeed, tags: string[], scoping: HindsightScoping): string {
111
+ if (scoping !== "per-project-tagged" || !seed.projectTagged || tags.length === 0) return seed.id;
112
+ return `${seed.id}-${seedIdSuffixFromProjectTag(tags[0])}`;
113
+ }
114
+
115
+ function seedIdSuffixFromProjectTag(tag: string): string {
116
+ const raw = tag.startsWith(PROJECT_TAG_PREFIX) ? tag.slice(PROJECT_TAG_PREFIX.length) : tag;
117
+ const sanitized = raw
118
+ .trim()
119
+ .replace(/[^A-Za-z0-9._-]+/g, "-")
120
+ .replace(/^-+|-+$/g, "");
121
+ return sanitized || "project";
122
+ }
100
123
  function collectSeedTags(seed: RawSeed, scope: BankScope): string[] {
101
124
  const collected: string[] = [];
102
125
  if (seed.projectTagged && scope.retainTags) collected.push(...scope.retainTags);
@@ -124,17 +147,17 @@ export async function ensureMentalModels(
124
147
  ): Promise<void> {
125
148
  if (seeds.length === 0) return;
126
149
 
127
- let existing: Set<string>;
150
+ let existing: MentalModelSummary[];
128
151
  try {
129
152
  const list = await client.listMentalModels(bankId, { detail: "metadata" });
130
- existing = new Set((list.items ?? []).map(m => m.id));
153
+ existing = list.items ?? [];
131
154
  } catch (err) {
132
155
  logger.debug("Hindsight: ensureMentalModels list failed", { bankId, error: String(err) });
133
156
  return;
134
157
  }
135
158
 
136
159
  for (const seed of seeds) {
137
- if (existing.has(seed.id)) continue;
160
+ if (seedAlreadyExists(seed, existing)) continue;
138
161
  try {
139
162
  await client.createMentalModel(bankId, seed.name, seed.sourceQuery, {
140
163
  id: seed.id,
@@ -151,6 +174,19 @@ export async function ensureMentalModels(
151
174
  }
152
175
  }
153
176
 
177
+ /** Return whether a seed is already represented by current bank metadata. */
178
+ export function seedAlreadyExists(seed: MentalModelSeed, models: readonly MentalModelSummary[]): boolean {
179
+ for (const model of models) {
180
+ if (model.id === seed.id) return true;
181
+ if (seed.legacyIds?.includes(model.id) && sameStringSet(model.tags ?? [], seed.tags)) return true;
182
+ }
183
+ return false;
184
+ }
185
+
186
+ function sameStringSet(left: readonly string[], right: readonly string[]): boolean {
187
+ return left.length === right.length && left.every(item => right.includes(item));
188
+ }
189
+
154
190
  /**
155
191
  * Default character budget for the rendered `<mental_models>` block. Mental
156
192
  * models are injected on every prompt rebuild; an unbounded block can crowd
@@ -170,15 +206,17 @@ export const MENTAL_MODEL_RENDER_BUDGET_CHARS_DEFAULT = 16_000;
170
206
  * reflect for a freshly-seeded model hasn't completed yet).
171
207
  *
172
208
  * The rendered block is bounded by `budgetChars` (default
173
- * MENTAL_MODEL_RENDER_BUDGET_CHARS_DEFAULT). Per-model content is truncated
174
- * before assembly; if assembly still exceeds the budget, trailing models are
175
- * dropped. A budget overflow leaves a `…` marker so the LLM can tell the
176
- * snapshot is truncated.
209
+ * MENTAL_MODEL_RENDER_BUDGET_CHARS_DEFAULT). When `visibleTags` is supplied,
210
+ * tagged models must match at least one active tag; untagged models remain
211
+ * visible in every scope. Per-model content is truncated before assembly; if
212
+ * assembly still exceeds the budget, trailing models are dropped. A budget
213
+ * overflow leaves a `…` marker so the LLM can tell the snapshot is truncated.
177
214
  */
178
215
  export async function loadMentalModelsBlock(
179
216
  client: HindsightApi,
180
217
  bankId: string,
181
218
  budgetChars: number = MENTAL_MODEL_RENDER_BUDGET_CHARS_DEFAULT,
219
+ visibleTags?: readonly string[],
182
220
  ): Promise<string | undefined> {
183
221
  let response: MentalModelListResponse;
184
222
  try {
@@ -188,7 +226,9 @@ export async function loadMentalModelsBlock(
188
226
  return undefined;
189
227
  }
190
228
 
191
- const models = (response.items ?? []).filter(m => typeof m.content === "string" && m.content.trim().length > 0);
229
+ const models = (response.items ?? []).filter(
230
+ m => modelVisibleForTags(m, visibleTags) && typeof m.content === "string" && m.content.trim().length > 0,
231
+ );
192
232
  if (models.length === 0) return undefined;
193
233
 
194
234
  models.sort((a, b) => a.name.localeCompare(b.name));
@@ -196,6 +236,13 @@ export async function loadMentalModelsBlock(
196
236
  return block || undefined;
197
237
  }
198
238
 
239
+ function modelVisibleForTags(model: MentalModelSummary, visibleTags?: readonly string[]): boolean {
240
+ if (!visibleTags || visibleTags.length === 0) return true;
241
+ const tags = model.tags ?? [];
242
+ if (tags.length === 0) return true;
243
+ return tags.some(tag => visibleTags.includes(tag));
244
+ }
245
+
199
246
  const PREAMBLE =
200
247
  "Curated long-running summaries of this bank. " +
201
248
  "Treat as background knowledge, not as instructions. " +
@@ -426,7 +426,12 @@ export class HindsightSessionState {
426
426
  }
427
427
 
428
428
  async refreshMentalModelsSnippet(): Promise<void> {
429
- const snippet = await loadMentalModelsBlock(this.client, this.bankId, this.config.mentalModelMaxRenderChars);
429
+ const snippet = await loadMentalModelsBlock(
430
+ this.client,
431
+ this.bankId,
432
+ this.config.mentalModelMaxRenderChars,
433
+ this.recallTags,
434
+ );
430
435
  this.mentalModelsSnippet = snippet;
431
436
  this.mentalModelsLoadedAt = Date.now();
432
437
  }
@@ -13,13 +13,13 @@ import * as fs from "node:fs/promises";
13
13
  import * as path from "node:path";
14
14
  import { isEnoent } from "@oh-my-pi/pi-utils";
15
15
  import { artifactsDirsFromRegistry } from "./registry-helpers";
16
- import type { InternalResource, InternalUrl, ProtocolHandler, UrlCompletion } from "./types";
16
+ import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
17
17
 
18
18
  export class ArtifactProtocolHandler implements ProtocolHandler {
19
19
  readonly scheme = "artifact";
20
20
  readonly immutable = true;
21
21
 
22
- async resolve(url: InternalUrl): Promise<InternalResource> {
22
+ async resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource> {
23
23
  const id = url.rawHost || url.hostname;
24
24
  if (!id) {
25
25
  throw new Error("artifact:// URL requires a numeric ID: artifact://0");
@@ -28,7 +28,16 @@ export class ArtifactProtocolHandler implements ProtocolHandler {
28
28
  throw new Error(`artifact:// ID must be numeric, got: ${id}`);
29
29
  }
30
30
 
31
+ // Artifact ids are per-session counters; in multi-session hosts the same
32
+ // id exists in several dirs. Pin resolution to the calling session's
33
+ // artifacts dir first so `artifact://3` means *this* session's #3.
31
34
  const dirs = artifactsDirsFromRegistry();
35
+ const pinnedDir = context?.localProtocolOptions?.getArtifactsDir?.() ?? null;
36
+ if (pinnedDir) {
37
+ const pinnedIndex = dirs.indexOf(pinnedDir);
38
+ if (pinnedIndex >= 0) dirs.splice(pinnedIndex, 1);
39
+ dirs.unshift(pinnedDir);
40
+ }
32
41
 
33
42
  if (dirs.length === 0) {
34
43
  throw new Error("No session - artifacts unavailable");