@oh-my-pi/pi-coding-agent 8.0.20 → 8.2.0

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 (421) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/docs/session.md +111 -46
  3. package/examples/custom-tools/hello/index.ts +1 -1
  4. package/examples/custom-tools/todo/index.ts +3 -4
  5. package/examples/extensions/api-demo.ts +0 -1
  6. package/examples/extensions/chalk-logger.ts +2 -3
  7. package/examples/extensions/hello.ts +0 -1
  8. package/examples/extensions/pirate.ts +0 -1
  9. package/examples/extensions/plan-mode.ts +15 -16
  10. package/examples/extensions/todo.ts +3 -4
  11. package/examples/extensions/tools.ts +1 -2
  12. package/examples/extensions/with-deps/index.ts +0 -1
  13. package/examples/hooks/auto-commit-on-exit.ts +1 -2
  14. package/examples/hooks/confirm-destructive.ts +0 -1
  15. package/examples/hooks/custom-compaction.ts +1 -2
  16. package/examples/hooks/dirty-repo-guard.ts +0 -1
  17. package/examples/hooks/file-trigger.ts +3 -4
  18. package/examples/hooks/git-checkpoint.ts +0 -1
  19. package/examples/hooks/handoff.ts +3 -4
  20. package/examples/hooks/permission-gate.ts +1 -2
  21. package/examples/hooks/protected-paths.ts +1 -2
  22. package/examples/hooks/qna.ts +2 -3
  23. package/examples/hooks/snake.ts +4 -5
  24. package/examples/hooks/status-line.ts +0 -1
  25. package/examples/sdk/01-minimal.ts +2 -3
  26. package/examples/sdk/02-custom-model.ts +2 -3
  27. package/examples/sdk/03-custom-prompt.ts +3 -4
  28. package/examples/sdk/04-skills.ts +2 -3
  29. package/examples/sdk/06-extensions.ts +1 -2
  30. package/examples/sdk/06-hooks.ts +6 -7
  31. package/examples/sdk/07-context-files.ts +0 -1
  32. package/examples/sdk/08-prompt-templates.ts +0 -1
  33. package/examples/sdk/08-slash-commands.ts +0 -1
  34. package/examples/sdk/09-api-keys-and-oauth.ts +0 -1
  35. package/examples/sdk/10-settings.ts +0 -1
  36. package/examples/sdk/11-sessions.ts +0 -1
  37. package/package.json +54 -23
  38. package/scripts/format-prompts.ts +0 -1
  39. package/src/capability/context-file.ts +3 -4
  40. package/src/capability/extension-module.ts +3 -4
  41. package/src/capability/extension.ts +3 -4
  42. package/src/capability/fs.ts +20 -21
  43. package/src/capability/hook.ts +3 -4
  44. package/src/capability/index.ts +15 -16
  45. package/src/capability/instruction.ts +3 -4
  46. package/src/capability/mcp.ts +3 -4
  47. package/src/capability/prompt.ts +3 -4
  48. package/src/capability/rule.ts +3 -4
  49. package/src/capability/settings.ts +2 -3
  50. package/src/capability/skill.ts +3 -4
  51. package/src/capability/slash-command.ts +3 -4
  52. package/src/capability/ssh.ts +3 -4
  53. package/src/capability/system-prompt.ts +3 -4
  54. package/src/capability/tool.ts +3 -4
  55. package/src/cli/args.ts +5 -6
  56. package/src/cli/config-cli.ts +6 -7
  57. package/src/cli/file-processor.ts +19 -17
  58. package/src/cli/jupyter-cli.ts +105 -0
  59. package/src/cli/list-models.ts +10 -11
  60. package/src/cli/plugin-cli.ts +20 -25
  61. package/src/cli/session-picker.ts +2 -3
  62. package/src/cli/setup-cli.ts +2 -3
  63. package/src/cli/stats-cli.ts +2 -3
  64. package/src/cli/update-cli.ts +25 -22
  65. package/src/commit/agentic/agent.ts +307 -0
  66. package/src/commit/agentic/fallback.ts +96 -0
  67. package/src/commit/agentic/index.ts +351 -0
  68. package/src/commit/agentic/prompts/analyze-file.md +22 -0
  69. package/src/commit/agentic/prompts/session-user.md +26 -0
  70. package/src/commit/agentic/prompts/split-confirm.md +1 -0
  71. package/src/commit/agentic/prompts/system.md +40 -0
  72. package/src/commit/agentic/state.ts +69 -0
  73. package/src/commit/agentic/tools/analyze-file.ts +131 -0
  74. package/src/commit/agentic/tools/git-file-diff.ts +194 -0
  75. package/src/commit/agentic/tools/git-hunk.ts +50 -0
  76. package/src/commit/agentic/tools/git-overview.ts +84 -0
  77. package/src/commit/agentic/tools/index.ts +56 -0
  78. package/src/commit/agentic/tools/propose-changelog.ts +128 -0
  79. package/src/commit/agentic/tools/propose-commit.ts +154 -0
  80. package/src/commit/agentic/tools/recent-commits.ts +81 -0
  81. package/src/commit/agentic/tools/split-commit.ts +280 -0
  82. package/src/commit/agentic/topo-sort.ts +44 -0
  83. package/src/commit/agentic/trivial.ts +51 -0
  84. package/src/commit/agentic/validation.ts +200 -0
  85. package/src/commit/analysis/conventional.ts +165 -0
  86. package/src/commit/analysis/index.ts +4 -0
  87. package/src/commit/analysis/scope.ts +242 -0
  88. package/src/commit/analysis/summary.ts +112 -0
  89. package/src/commit/analysis/validation.ts +66 -0
  90. package/src/commit/changelog/detect.ts +36 -0
  91. package/src/commit/changelog/generate.ts +110 -0
  92. package/src/commit/changelog/index.ts +233 -0
  93. package/src/commit/changelog/parse.ts +44 -0
  94. package/src/commit/cli.ts +93 -0
  95. package/src/commit/git/diff.ts +148 -0
  96. package/src/commit/git/errors.ts +11 -0
  97. package/src/commit/git/index.ts +212 -0
  98. package/src/commit/git/operations.ts +53 -0
  99. package/src/commit/index.ts +5 -0
  100. package/src/commit/map-reduce/index.ts +63 -0
  101. package/src/commit/map-reduce/map-phase.ts +178 -0
  102. package/src/commit/map-reduce/reduce-phase.ts +145 -0
  103. package/src/commit/map-reduce/utils.ts +9 -0
  104. package/src/commit/message.ts +11 -0
  105. package/src/commit/model-selection.ts +80 -0
  106. package/src/commit/pipeline.ts +240 -0
  107. package/src/commit/prompts/analysis-system.md +155 -0
  108. package/src/commit/prompts/analysis-user.md +41 -0
  109. package/src/commit/prompts/changelog-system.md +56 -0
  110. package/src/commit/prompts/changelog-user.md +19 -0
  111. package/src/commit/prompts/file-observer-system.md +26 -0
  112. package/src/commit/prompts/file-observer-user.md +9 -0
  113. package/src/commit/prompts/reduce-system.md +60 -0
  114. package/src/commit/prompts/reduce-user.md +17 -0
  115. package/src/commit/prompts/summary-retry.md +4 -0
  116. package/src/commit/prompts/summary-system.md +52 -0
  117. package/src/commit/prompts/summary-user.md +13 -0
  118. package/src/commit/prompts/types-description.md +2 -0
  119. package/src/commit/types.ts +109 -0
  120. package/src/commit/utils/exclusions.ts +42 -0
  121. package/src/config/file-lock.ts +121 -0
  122. package/src/config/keybindings.ts +6 -8
  123. package/src/config/model-registry.ts +65 -38
  124. package/src/config/model-resolver.ts +18 -19
  125. package/src/config/prompt-templates.ts +11 -11
  126. package/src/config/settings-manager.ts +141 -50
  127. package/src/config.ts +64 -66
  128. package/src/cursor.ts +11 -9
  129. package/src/discovery/agents-md.ts +11 -12
  130. package/src/discovery/builtin.ts +68 -73
  131. package/src/discovery/claude.ts +41 -42
  132. package/src/discovery/cline.ts +11 -12
  133. package/src/discovery/codex.ts +52 -53
  134. package/src/discovery/cursor.ts +9 -10
  135. package/src/discovery/gemini.ts +17 -22
  136. package/src/discovery/github.ts +13 -14
  137. package/src/discovery/helpers.ts +35 -34
  138. package/src/discovery/index.ts +22 -24
  139. package/src/discovery/mcp-json.ts +8 -9
  140. package/src/discovery/ssh.ts +8 -9
  141. package/src/discovery/vscode.ts +4 -5
  142. package/src/discovery/windsurf.ts +6 -7
  143. package/src/exa/company.ts +1 -2
  144. package/src/exa/index.ts +2 -3
  145. package/src/exa/linkedin.ts +1 -2
  146. package/src/exa/mcp-client.ts +14 -16
  147. package/src/exa/render.ts +10 -11
  148. package/src/exa/researcher.ts +1 -2
  149. package/src/exa/search.ts +1 -2
  150. package/src/exa/types.ts +0 -1
  151. package/src/exa/websets.ts +1 -2
  152. package/src/exec/bash-executor.ts +3 -4
  153. package/src/exec/exec.ts +0 -1
  154. package/src/export/custom-share.ts +5 -6
  155. package/src/export/html/index.ts +24 -21
  156. package/src/export/ttsr.ts +2 -3
  157. package/src/extensibility/custom-commands/bundled/review/index.ts +7 -8
  158. package/src/extensibility/custom-commands/loader.ts +18 -15
  159. package/src/extensibility/custom-commands/types.ts +2 -3
  160. package/src/extensibility/custom-tools/loader.ts +11 -12
  161. package/src/extensibility/custom-tools/types.ts +7 -8
  162. package/src/extensibility/custom-tools/wrapper.ts +2 -3
  163. package/src/extensibility/extensions/loader.ts +76 -54
  164. package/src/extensibility/extensions/runner.ts +11 -12
  165. package/src/extensibility/extensions/types.ts +20 -27
  166. package/src/extensibility/extensions/wrapper.ts +3 -4
  167. package/src/extensibility/hooks/index.ts +1 -1
  168. package/src/extensibility/hooks/loader.ts +9 -10
  169. package/src/extensibility/hooks/runner.ts +7 -8
  170. package/src/extensibility/hooks/tool-wrapper.ts +0 -1
  171. package/src/extensibility/hooks/types.ts +11 -18
  172. package/src/extensibility/plugins/doctor.ts +3 -3
  173. package/src/extensibility/plugins/installer.ts +27 -27
  174. package/src/extensibility/plugins/loader.ts +59 -56
  175. package/src/extensibility/plugins/manager.ts +211 -171
  176. package/src/extensibility/plugins/parser.ts +1 -1
  177. package/src/extensibility/plugins/paths.ts +8 -8
  178. package/src/extensibility/skills.ts +63 -60
  179. package/src/extensibility/slash-commands.ts +10 -10
  180. package/src/index.ts +54 -54
  181. package/src/internal-urls/agent-protocol.ts +21 -11
  182. package/src/internal-urls/artifact-protocol.ts +17 -13
  183. package/src/internal-urls/router.ts +1 -2
  184. package/src/internal-urls/rule-protocol.ts +3 -4
  185. package/src/internal-urls/skill-protocol.ts +3 -4
  186. package/src/ipy/executor.ts +109 -9
  187. package/src/ipy/gateway-coordinator.ts +79 -90
  188. package/src/ipy/kernel.ts +32 -30
  189. package/src/ipy/modules.ts +13 -13
  190. package/src/lsp/client.ts +21 -10
  191. package/src/lsp/clients/biome-client.ts +1 -2
  192. package/src/lsp/clients/index.ts +3 -3
  193. package/src/lsp/clients/lsp-linter-client.ts +4 -5
  194. package/src/lsp/config.ts +15 -15
  195. package/src/lsp/edits.ts +4 -5
  196. package/src/lsp/index.ts +43 -44
  197. package/src/lsp/lspmux.ts +8 -8
  198. package/src/lsp/render.ts +99 -61
  199. package/src/lsp/utils.ts +3 -3
  200. package/src/main.ts +71 -37
  201. package/src/mcp/client.ts +2 -3
  202. package/src/mcp/config.ts +5 -6
  203. package/src/mcp/json-rpc.ts +0 -1
  204. package/src/mcp/loader.ts +6 -7
  205. package/src/mcp/manager.ts +17 -18
  206. package/src/mcp/tool-bridge.ts +4 -9
  207. package/src/mcp/tool-cache.ts +2 -3
  208. package/src/mcp/transports/http.ts +2 -4
  209. package/src/mcp/transports/stdio.ts +1 -2
  210. package/src/migrations.ts +63 -52
  211. package/src/modes/components/armin.ts +4 -5
  212. package/src/modes/components/assistant-message.ts +33 -5
  213. package/src/modes/components/bash-execution.ts +7 -8
  214. package/src/modes/components/bordered-loader.ts +3 -3
  215. package/src/modes/components/branch-summary-message.ts +3 -3
  216. package/src/modes/components/compaction-summary-message.ts +3 -3
  217. package/src/modes/components/countdown-timer.ts +0 -1
  218. package/src/modes/components/custom-message.ts +5 -5
  219. package/src/modes/components/diff.ts +1 -1
  220. package/src/modes/components/dynamic-border.ts +2 -2
  221. package/src/modes/components/extensions/extension-dashboard.ts +6 -7
  222. package/src/modes/components/extensions/extension-list.ts +2 -3
  223. package/src/modes/components/extensions/inspector-panel.ts +3 -4
  224. package/src/modes/components/extensions/state-manager.ts +25 -26
  225. package/src/modes/components/extensions/types.ts +1 -2
  226. package/src/modes/components/footer.ts +47 -43
  227. package/src/modes/components/history-search.ts +2 -2
  228. package/src/modes/components/hook-editor.ts +3 -4
  229. package/src/modes/components/hook-input.ts +2 -3
  230. package/src/modes/components/hook-message.ts +5 -5
  231. package/src/modes/components/hook-selector.ts +2 -3
  232. package/src/modes/components/keybinding-hints.ts +2 -3
  233. package/src/modes/components/login-dialog.ts +2 -2
  234. package/src/modes/components/model-selector.ts +12 -12
  235. package/src/modes/components/oauth-selector.ts +2 -2
  236. package/src/modes/components/plugin-settings.ts +20 -20
  237. package/src/modes/components/python-execution.ts +7 -8
  238. package/src/modes/components/queue-mode-selector.ts +3 -3
  239. package/src/modes/components/read-tool-group.ts +2 -2
  240. package/src/modes/components/session-selector.ts +4 -4
  241. package/src/modes/components/settings-defs.ts +77 -69
  242. package/src/modes/components/settings-selector.ts +16 -16
  243. package/src/modes/components/show-images-selector.ts +2 -2
  244. package/src/modes/components/status-line/segments.ts +4 -4
  245. package/src/modes/components/status-line/separators.ts +1 -1
  246. package/src/modes/components/status-line/types.ts +2 -2
  247. package/src/modes/components/status-line-segment-editor.ts +7 -8
  248. package/src/modes/components/status-line.ts +12 -12
  249. package/src/modes/components/theme-selector.ts +8 -7
  250. package/src/modes/components/thinking-selector.ts +4 -4
  251. package/src/modes/components/todo-display.ts +2 -2
  252. package/src/modes/components/todo-reminder.ts +4 -4
  253. package/src/modes/components/tool-execution.ts +16 -19
  254. package/src/modes/components/tree-selector.ts +12 -12
  255. package/src/modes/components/ttsr-notification.ts +5 -5
  256. package/src/modes/components/user-message-selector.ts +1 -1
  257. package/src/modes/components/user-message.ts +1 -1
  258. package/src/modes/components/visual-truncate.ts +0 -1
  259. package/src/modes/components/welcome.ts +4 -4
  260. package/src/modes/controllers/command-controller.ts +46 -47
  261. package/src/modes/controllers/event-controller.ts +16 -20
  262. package/src/modes/controllers/extension-ui-controller.ts +40 -46
  263. package/src/modes/controllers/input-controller.ts +17 -18
  264. package/src/modes/controllers/selector-controller.ts +103 -91
  265. package/src/modes/index.ts +3 -3
  266. package/src/modes/interactive-mode.ts +31 -31
  267. package/src/modes/print-mode.ts +12 -13
  268. package/src/modes/rpc/rpc-client.ts +7 -8
  269. package/src/modes/rpc/rpc-mode.ts +24 -28
  270. package/src/modes/rpc/rpc-types.ts +3 -4
  271. package/src/modes/theme/mermaid-cache.ts +89 -0
  272. package/src/modes/theme/theme.ts +130 -53
  273. package/src/modes/types.ts +10 -10
  274. package/src/modes/utils/ui-helpers.ts +17 -17
  275. package/src/patch/applicator.ts +18 -19
  276. package/src/patch/diff.ts +1 -2
  277. package/src/patch/fuzzy.ts +1 -2
  278. package/src/patch/index.ts +11 -18
  279. package/src/patch/normalize.ts +4 -4
  280. package/src/patch/normative.ts +1 -2
  281. package/src/patch/parser.ts +8 -9
  282. package/src/patch/shared.ts +43 -16
  283. package/src/prompts/tools/task.md +2 -0
  284. package/src/sdk.ts +100 -65
  285. package/src/session/agent-session.ts +84 -85
  286. package/src/session/agent-storage.ts +43 -39
  287. package/src/session/artifacts.ts +32 -10
  288. package/src/session/auth-storage.ts +50 -39
  289. package/src/session/compaction/branch-summarization.ts +7 -10
  290. package/src/session/compaction/compaction.ts +8 -19
  291. package/src/session/compaction/utils.ts +6 -9
  292. package/src/session/history-storage.ts +10 -10
  293. package/src/session/messages.ts +4 -5
  294. package/src/session/session-manager.ts +76 -65
  295. package/src/session/session-storage.ts +57 -69
  296. package/src/session/storage-migration.ts +14 -56
  297. package/src/session/streaming-output.ts +2 -2
  298. package/src/ssh/connection-manager.ts +43 -50
  299. package/src/ssh/ssh-executor.ts +2 -2
  300. package/src/ssh/sshfs-mount.ts +11 -18
  301. package/src/system-prompt.ts +28 -35
  302. package/src/task/agents.ts +45 -30
  303. package/src/task/commands.ts +6 -7
  304. package/src/task/discovery.ts +39 -76
  305. package/src/task/executor.ts +14 -15
  306. package/src/task/index.ts +40 -34
  307. package/src/task/output-manager.ts +93 -0
  308. package/src/task/parallel.ts +0 -1
  309. package/src/task/render.ts +24 -30
  310. package/src/task/subprocess-tool-registry.ts +1 -2
  311. package/src/task/worker-protocol.ts +3 -3
  312. package/src/task/worker.ts +33 -39
  313. package/src/task/worktree.ts +19 -19
  314. package/src/tools/ask.ts +41 -20
  315. package/src/tools/bash-interceptor.ts +1 -5
  316. package/src/tools/bash.ts +91 -97
  317. package/src/tools/calculator.ts +49 -47
  318. package/src/tools/complete.ts +4 -5
  319. package/src/tools/context.ts +2 -2
  320. package/src/tools/fetch.ts +84 -124
  321. package/src/tools/find.ts +94 -98
  322. package/src/tools/gemini-image.ts +14 -14
  323. package/src/tools/grep.ts +100 -116
  324. package/src/tools/index.ts +80 -55
  325. package/src/tools/list-limit.ts +1 -1
  326. package/src/tools/ls.ts +44 -70
  327. package/src/tools/notebook.ts +51 -67
  328. package/src/tools/output-meta.ts +3 -4
  329. package/src/tools/output-utils.ts +2 -2
  330. package/src/tools/path-utils.ts +5 -5
  331. package/src/tools/python.ts +104 -217
  332. package/src/tools/read.ts +92 -33
  333. package/src/tools/render-utils.ts +8 -23
  334. package/src/tools/renderers.ts +6 -7
  335. package/src/tools/review.ts +8 -11
  336. package/src/tools/ssh.ts +69 -49
  337. package/src/tools/todo-write.ts +37 -25
  338. package/src/tools/tool-errors.ts +3 -3
  339. package/src/tools/tool-result.ts +3 -8
  340. package/src/tools/write.ts +99 -75
  341. package/src/tui/code-cell.ts +109 -0
  342. package/src/tui/file-list.ts +47 -0
  343. package/src/tui/index.ts +11 -0
  344. package/src/tui/output-block.ts +72 -0
  345. package/src/tui/status-line.ts +39 -0
  346. package/src/tui/tree-list.ts +55 -0
  347. package/src/tui/types.ts +16 -0
  348. package/src/tui/utils.ts +48 -0
  349. package/src/utils/changelog.ts +9 -10
  350. package/src/utils/clipboard.ts +11 -11
  351. package/src/utils/file-mentions.ts +4 -10
  352. package/src/utils/frontmatter.ts +6 -3
  353. package/src/utils/fuzzy.ts +2 -2
  354. package/src/utils/image-convert.ts +1 -1
  355. package/src/utils/image-resize.ts +1 -1
  356. package/src/utils/mime.ts +2 -2
  357. package/src/utils/shell-snapshot.ts +11 -13
  358. package/src/utils/shell.ts +4 -5
  359. package/src/utils/title-generator.ts +8 -9
  360. package/src/utils/tools-manager.ts +23 -23
  361. package/src/vendor/photon/index.js +1099 -1059
  362. package/src/vendor/photon/photon_rs_bg.wasm +0 -0
  363. package/src/web/scrapers/artifacthub.ts +1 -1
  364. package/src/web/scrapers/arxiv.ts +2 -2
  365. package/src/web/scrapers/bluesky.ts +2 -2
  366. package/src/web/scrapers/cheatsh.ts +1 -1
  367. package/src/web/scrapers/chocolatey.ts +2 -2
  368. package/src/web/scrapers/choosealicense.ts +5 -5
  369. package/src/web/scrapers/cisa-kev.ts +1 -1
  370. package/src/web/scrapers/crossref.ts +2 -2
  371. package/src/web/scrapers/devto.ts +3 -3
  372. package/src/web/scrapers/discogs.ts +3 -4
  373. package/src/web/scrapers/discourse.ts +1 -1
  374. package/src/web/scrapers/dockerhub.ts +1 -1
  375. package/src/web/scrapers/fdroid.ts +2 -2
  376. package/src/web/scrapers/firefox-addons.ts +3 -3
  377. package/src/web/scrapers/flathub.ts +1 -1
  378. package/src/web/scrapers/github.ts +3 -3
  379. package/src/web/scrapers/gitlab.ts +4 -4
  380. package/src/web/scrapers/hackernews.ts +2 -2
  381. package/src/web/scrapers/huggingface.ts +1 -1
  382. package/src/web/scrapers/iacr.ts +2 -2
  383. package/src/web/scrapers/index.ts +0 -1
  384. package/src/web/scrapers/jetbrains-marketplace.ts +1 -1
  385. package/src/web/scrapers/lemmy.ts +2 -2
  386. package/src/web/scrapers/maven.ts +2 -2
  387. package/src/web/scrapers/mdn.ts +2 -4
  388. package/src/web/scrapers/metacpan.ts +2 -2
  389. package/src/web/scrapers/musicbrainz.ts +1 -2
  390. package/src/web/scrapers/npm.ts +1 -1
  391. package/src/web/scrapers/nuget.ts +2 -2
  392. package/src/web/scrapers/nvd.ts +3 -3
  393. package/src/web/scrapers/ollama.ts +7 -9
  394. package/src/web/scrapers/opencorporates.ts +2 -2
  395. package/src/web/scrapers/openlibrary.ts +6 -6
  396. package/src/web/scrapers/orcid.ts +0 -1
  397. package/src/web/scrapers/osv.ts +2 -2
  398. package/src/web/scrapers/packagist.ts +1 -1
  399. package/src/web/scrapers/pubmed.ts +1 -2
  400. package/src/web/scrapers/rawg.ts +2 -2
  401. package/src/web/scrapers/readthedocs.ts +1 -2
  402. package/src/web/scrapers/repology.ts +2 -2
  403. package/src/web/scrapers/rfc.ts +1 -1
  404. package/src/web/scrapers/searchcode.ts +2 -2
  405. package/src/web/scrapers/semantic-scholar.ts +1 -1
  406. package/src/web/scrapers/snapcraft.ts +2 -2
  407. package/src/web/scrapers/sourcegraph.ts +1 -1
  408. package/src/web/scrapers/spdx.ts +3 -3
  409. package/src/web/scrapers/spotify.ts +0 -1
  410. package/src/web/scrapers/twitter.ts +1 -1
  411. package/src/web/scrapers/types.ts +1 -2
  412. package/src/web/scrapers/utils.ts +5 -5
  413. package/src/web/scrapers/wikidata.ts +3 -3
  414. package/src/web/scrapers/youtube.ts +9 -14
  415. package/src/web/search/auth.ts +5 -10
  416. package/src/web/search/index.ts +11 -21
  417. package/src/web/search/providers/anthropic.ts +3 -9
  418. package/src/web/search/providers/exa.ts +6 -10
  419. package/src/web/search/providers/perplexity.ts +5 -5
  420. package/src/web/search/render.ts +129 -175
  421. package/tsconfig.json +0 -42
@@ -0,0 +1,80 @@
1
+ import type { Api, Model } from "@oh-my-pi/pi-ai";
2
+ import { parseModelPattern, parseModelString, SMOL_MODEL_PRIORITY } from "../config/model-resolver";
3
+ import type { SettingsManager } from "../config/settings-manager";
4
+
5
+ export async function resolvePrimaryModel(
6
+ override: string | undefined,
7
+ settingsManager: SettingsManager,
8
+ modelRegistry: {
9
+ getAvailable: () => Model<Api>[];
10
+ getApiKey: (model: Model<Api>) => Promise<string | undefined>;
11
+ },
12
+ ): Promise<{ model: Model<Api>; apiKey: string }> {
13
+ const available = modelRegistry.getAvailable();
14
+ const model = override
15
+ ? resolveModelFromString(expandRoleAlias(override, settingsManager), available)
16
+ : resolveModelFromSettings(settingsManager, available);
17
+ if (!model) {
18
+ throw new Error("No model available for commit generation");
19
+ }
20
+ const apiKey = await modelRegistry.getApiKey(model);
21
+ if (!apiKey) {
22
+ throw new Error(`No API key available for model ${model.provider}/${model.id}`);
23
+ }
24
+ return { model, apiKey };
25
+ }
26
+
27
+ export async function resolveSmolModel(
28
+ settingsManager: SettingsManager,
29
+ modelRegistry: {
30
+ getAvailable: () => Model<Api>[];
31
+ getApiKey: (model: Model<Api>) => Promise<string | undefined>;
32
+ },
33
+ fallbackModel: Model<Api>,
34
+ fallbackApiKey: string,
35
+ ): Promise<{ model: Model<Api>; apiKey: string }> {
36
+ const available = modelRegistry.getAvailable();
37
+ const role = settingsManager.getModelRole("smol");
38
+ const roleModel = role ? resolveModelFromString(role, available) : undefined;
39
+ if (roleModel) {
40
+ const apiKey = await modelRegistry.getApiKey(roleModel);
41
+ if (apiKey) return { model: roleModel, apiKey };
42
+ }
43
+
44
+ for (const pattern of SMOL_MODEL_PRIORITY) {
45
+ const candidate = parseModelPattern(pattern, available).model;
46
+ if (!candidate) continue;
47
+ const apiKey = await modelRegistry.getApiKey(candidate);
48
+ if (apiKey) return { model: candidate, apiKey };
49
+ }
50
+
51
+ return { model: fallbackModel, apiKey: fallbackApiKey };
52
+ }
53
+
54
+ function resolveModelFromSettings(settingsManager: SettingsManager, available: Model<Api>[]): Model<Api> | undefined {
55
+ const roles = ["commit", "smol", "default"];
56
+ for (const role of roles) {
57
+ const configured = settingsManager.getModelRole(role);
58
+ if (!configured) continue;
59
+ const resolved = resolveModelFromString(expandRoleAlias(configured, settingsManager), available);
60
+ if (resolved) return resolved;
61
+ }
62
+ return available[0];
63
+ }
64
+
65
+ function resolveModelFromString(value: string, available: Model<Api>[]): Model<Api> | undefined {
66
+ const parsed = parseModelString(value);
67
+ if (parsed) {
68
+ return available.find(model => model.provider === parsed.provider && model.id === parsed.id);
69
+ }
70
+ return parseModelPattern(value, available).model;
71
+ }
72
+
73
+ function expandRoleAlias(value: string, settingsManager: SettingsManager): string {
74
+ const lower = value.toLowerCase();
75
+ if (lower.startsWith("pi/") || lower.startsWith("omp/")) {
76
+ const role = lower.startsWith("pi/") ? value.slice(3) : value.slice(4);
77
+ return settingsManager.getModelRole(role) ?? value;
78
+ }
79
+ return value;
80
+ }
@@ -0,0 +1,240 @@
1
+ import * as path from "node:path";
2
+ import type { Api, Model } from "@oh-my-pi/pi-ai";
3
+ import { logger } from "@oh-my-pi/pi-utils";
4
+ import { renderPromptTemplate } from "../config/prompt-templates";
5
+ import { SettingsManager } from "../config/settings-manager";
6
+ import { discoverAuthStorage, discoverModels } from "../sdk";
7
+ import { loadProjectContextFiles } from "../system-prompt";
8
+ import { runAgenticCommit } from "./agentic";
9
+ import {
10
+ extractScopeCandidates,
11
+ generateConventionalAnalysis,
12
+ generateSummary,
13
+ validateAnalysis,
14
+ validateSummary,
15
+ } from "./analysis";
16
+ import { runChangelogFlow } from "./changelog";
17
+ import { ControlledGit } from "./git";
18
+ import { runMapReduceAnalysis, shouldUseMapReduce } from "./map-reduce";
19
+ import { formatCommitMessage } from "./message";
20
+ import { resolvePrimaryModel, resolveSmolModel } from "./model-selection";
21
+ import summaryRetryPrompt from "./prompts/summary-retry.md" with { type: "text" };
22
+ import typesDescriptionPrompt from "./prompts/types-description.md" with { type: "text" };
23
+ import type { CommitCommandArgs, ConventionalAnalysis } from "./types";
24
+
25
+ const SUMMARY_MAX_CHARS = 72;
26
+ const RECENT_COMMITS_COUNT = 8;
27
+ const TYPES_DESCRIPTION = renderPromptTemplate(typesDescriptionPrompt);
28
+
29
+ /**
30
+ * Execute the omp commit pipeline for staged changes.
31
+ */
32
+ export async function runCommitCommand(args: CommitCommandArgs): Promise<void> {
33
+ if (args.legacy) {
34
+ return runLegacyCommitCommand(args);
35
+ }
36
+ return runAgenticCommit(args);
37
+ }
38
+
39
+ async function runLegacyCommitCommand(args: CommitCommandArgs): Promise<void> {
40
+ const cwd = process.cwd();
41
+ const settingsManager = await SettingsManager.create(cwd);
42
+ const commitSettings = settingsManager.getCommitSettings();
43
+ const authStorage = await discoverAuthStorage();
44
+ const modelRegistry = discoverModels(authStorage);
45
+
46
+ const { model: primaryModel, apiKey: primaryApiKey } = await resolvePrimaryModel(
47
+ args.model,
48
+ settingsManager,
49
+ modelRegistry,
50
+ );
51
+ const { model: smolModel, apiKey: smolApiKey } = await resolveSmolModel(
52
+ settingsManager,
53
+ modelRegistry,
54
+ primaryModel,
55
+ primaryApiKey,
56
+ );
57
+
58
+ const git = new ControlledGit(cwd);
59
+ let stagedFiles = await git.getStagedFiles();
60
+ if (stagedFiles.length === 0) {
61
+ writeStdout("No staged changes detected, staging all changes...");
62
+ await git.stageAll();
63
+ stagedFiles = await git.getStagedFiles();
64
+ }
65
+ if (stagedFiles.length === 0) {
66
+ writeStderr("No changes to commit.");
67
+ return;
68
+ }
69
+
70
+ if (!args.noChangelog) {
71
+ await runChangelogFlow({
72
+ git,
73
+ cwd,
74
+ model: primaryModel,
75
+ apiKey: primaryApiKey,
76
+ stagedFiles,
77
+ dryRun: args.dryRun,
78
+ maxDiffChars: commitSettings.changelogMaxDiffChars,
79
+ });
80
+ }
81
+
82
+ const diff = await git.getDiff(true);
83
+ const stat = await git.getStat(true);
84
+ const numstat = await git.getNumstat(true);
85
+ const scopeCandidates = extractScopeCandidates(numstat).scopeCandidates;
86
+ const recentCommits = await git.getRecentCommits(RECENT_COMMITS_COUNT);
87
+ const contextFiles = await loadProjectContextFiles({ cwd });
88
+ const formattedContextFiles = contextFiles.map(file => ({
89
+ path: path.relative(cwd, file.path),
90
+ content: file.content,
91
+ }));
92
+
93
+ const analysis = await generateAnalysis({
94
+ diff,
95
+ stat,
96
+ scopeCandidates,
97
+ recentCommits,
98
+ contextFiles: formattedContextFiles,
99
+ userContext: args.context,
100
+ primaryModel,
101
+ primaryApiKey,
102
+ smolModel,
103
+ smolApiKey,
104
+ commitSettings,
105
+ });
106
+
107
+ const analysisValidation = validateAnalysis(analysis);
108
+ if (!analysisValidation.valid) {
109
+ logger.warn("commit analysis validation failed", { errors: analysisValidation.errors });
110
+ }
111
+
112
+ const summary = await generateSummaryWithRetry({
113
+ analysis,
114
+ stat,
115
+ model: primaryModel,
116
+ apiKey: primaryApiKey,
117
+ userContext: args.context,
118
+ });
119
+
120
+ const commitMessage = formatCommitMessage(analysis, summary.summary);
121
+
122
+ if (args.dryRun) {
123
+ writeStdout("\nGenerated commit message:\n");
124
+ writeStdout(commitMessage);
125
+ return;
126
+ }
127
+
128
+ await git.commit(commitMessage);
129
+ writeStdout("Commit created.");
130
+ if (args.push) {
131
+ await git.push();
132
+ writeStdout("Pushed to remote.");
133
+ }
134
+ }
135
+
136
+ async function generateAnalysis(input: {
137
+ diff: string;
138
+ stat: string;
139
+ scopeCandidates: string;
140
+ recentCommits: string[];
141
+ contextFiles: Array<{ path: string; content: string }>;
142
+ userContext?: string;
143
+ primaryModel: Model<Api>;
144
+ primaryApiKey: string;
145
+ smolModel: Model<Api>;
146
+ smolApiKey: string;
147
+ commitSettings: {
148
+ mapReduceEnabled: boolean;
149
+ mapReduceMinFiles: number;
150
+ mapReduceMaxFileTokens: number;
151
+ mapReduceTimeoutMs: number;
152
+ mapReduceMaxConcurrency: number;
153
+ changelogMaxDiffChars: number;
154
+ };
155
+ }): Promise<ConventionalAnalysis> {
156
+ if (
157
+ shouldUseMapReduce(input.diff, {
158
+ enabled: input.commitSettings.mapReduceEnabled,
159
+ minFiles: input.commitSettings.mapReduceMinFiles,
160
+ maxFileTokens: input.commitSettings.mapReduceMaxFileTokens,
161
+ })
162
+ ) {
163
+ writeStdout("Large diff detected, using map-reduce analysis...");
164
+ return runMapReduceAnalysis({
165
+ model: input.primaryModel,
166
+ apiKey: input.primaryApiKey,
167
+ smolModel: input.smolModel,
168
+ smolApiKey: input.smolApiKey,
169
+ diff: input.diff,
170
+ stat: input.stat,
171
+ scopeCandidates: input.scopeCandidates,
172
+ typesDescription: TYPES_DESCRIPTION,
173
+ settings: {
174
+ enabled: input.commitSettings.mapReduceEnabled,
175
+ minFiles: input.commitSettings.mapReduceMinFiles,
176
+ maxFileTokens: input.commitSettings.mapReduceMaxFileTokens,
177
+ maxConcurrency: input.commitSettings.mapReduceMaxConcurrency,
178
+ timeoutMs: input.commitSettings.mapReduceTimeoutMs,
179
+ },
180
+ });
181
+ }
182
+
183
+ return generateConventionalAnalysis({
184
+ model: input.primaryModel,
185
+ apiKey: input.primaryApiKey,
186
+ contextFiles: input.contextFiles,
187
+ userContext: input.userContext,
188
+ typesDescription: TYPES_DESCRIPTION,
189
+ recentCommits: input.recentCommits,
190
+ scopeCandidates: input.scopeCandidates,
191
+ stat: input.stat,
192
+ diff: input.diff,
193
+ });
194
+ }
195
+
196
+ async function generateSummaryWithRetry(input: {
197
+ analysis: ConventionalAnalysis;
198
+ stat: string;
199
+ model: Model<Api>;
200
+ apiKey: string;
201
+ userContext?: string;
202
+ }): Promise<{ summary: string }> {
203
+ let context = input.userContext;
204
+ for (let attempt = 0; attempt < 3; attempt += 1) {
205
+ const result = await generateSummary({
206
+ model: input.model,
207
+ apiKey: input.apiKey,
208
+ commitType: input.analysis.type,
209
+ scope: input.analysis.scope,
210
+ details: input.analysis.details.map(detail => detail.text),
211
+ stat: input.stat,
212
+ maxChars: SUMMARY_MAX_CHARS,
213
+ userContext: context,
214
+ });
215
+ const validation = validateSummary(result.summary, SUMMARY_MAX_CHARS);
216
+ if (validation.valid) {
217
+ return result;
218
+ }
219
+ if (attempt === 2) {
220
+ return result;
221
+ }
222
+ context = buildRetryContext(input.userContext, validation.errors);
223
+ }
224
+ throw new Error("Summary generation failed");
225
+ }
226
+
227
+ function buildRetryContext(base: string | undefined, errors: string[]): string {
228
+ return renderPromptTemplate(summaryRetryPrompt, {
229
+ base_context: base,
230
+ errors: errors.join("; "),
231
+ });
232
+ }
233
+
234
+ function writeStdout(message: string): void {
235
+ process.stdout.write(`${message}\n`);
236
+ }
237
+
238
+ function writeStderr(message: string): void {
239
+ process.stderr.write(`${message}\n`);
240
+ }
@@ -0,0 +1,155 @@
1
+ <context>
2
+ You are a senior release engineer who writes precise, changelog-ready commit classifications. Your output feeds directly into automated release tooling.
3
+ </context>
4
+
5
+ <instructions>
6
+ Classify this git diff into conventional commit format. Get this right — it affects release notes and semantic versioning.
7
+
8
+ ## 1. Determine Scope
9
+
10
+ Apply scope when 60%+ of line changes target a single component:
11
+ - 150 lines in src/api/, 30 in src/lib.rs -> "api"
12
+ - 50 lines in src/api/, 50 in src/types/ -> null (50/50 split)
13
+
14
+ Use null for: cross-cutting changes, no dominant component, project-wide refactoring.
15
+
16
+ Forbidden scopes (use null): src, lib, include, tests, benches, examples, docs, project name, app, main, entire, all, misc.
17
+
18
+ Prefer scopes from <common_scopes> over inventing new ones.
19
+
20
+ ## 2. Generate Details (0-6 items)
21
+
22
+ Each detail:
23
+ 1. Past-tense verb, ends with period
24
+ 2. Explains impact/rationale (skip trivial what-changed)
25
+ 3. Uses precise names (modules, APIs, files)
26
+ 4. Under 120 characters
27
+
28
+ Abstraction preference:
29
+ - BEST: "Replaced polling with event-driven model for 10x throughput."
30
+ - GOOD: "Consolidated three HTTP builders into unified API."
31
+ - SKIP: "Renamed workspacePath to locate."
32
+
33
+ Group 3+ similar changes: "Updated 5 test files for new API." (not five bullets).
34
+
35
+ Issue references inline: (#123), (#123, #456), (#123-#125).
36
+
37
+ Priority: user-visible -> perf/security -> architecture -> internal.
38
+
39
+ Exclude: import changes, whitespace, formatting, trivial renames, debug prints, comment-only, file moves without modification.
40
+
41
+ State only visible rationale. If unclear, use neutral: "Updated logic for correctness."
42
+
43
+ ## 3. Assign Changelog Metadata
44
+
45
+ | Condition | changelog_category |
46
+ |-----------|--------------------|
47
+ | New public API, feature, capability | "Added" |
48
+ | Modified existing behavior | "Changed" |
49
+ | Bug fix, correction | "Fixed" |
50
+ | Feature marked for removal | "Deprecated" |
51
+ | Feature/API removed | "Removed" |
52
+ | Security fix or improvement | "Security" |
53
+
54
+ user_visible: true for: new features, APIs, breaking changes, user-affecting bug fixes, user-facing docs, security fixes.
55
+
56
+ user_visible: false for: internal refactoring, performance optimizations (unless documented), test/build/CI, code style.
57
+
58
+ Omit changelog_category when user_visible is false.
59
+ </instructions>
60
+
61
+ <output_format>
62
+ Call create_conventional_analysis with:
63
+
64
+ {
65
+ "type": "feat|fix|refactor|docs|test|chore|style|perf|build|ci|revert",
66
+ "scope": "component-name" | null,
67
+ "details": [
68
+ {
69
+ "text": "Past-tense description ending with period.",
70
+ "changelog_category": "Added|Changed|Fixed|Deprecated|Removed|Security",
71
+ "user_visible": true
72
+ },
73
+ {
74
+ "text": "Internal change description.",
75
+ "user_visible": false
76
+ }
77
+ ],
78
+ "issue_refs": []
79
+ }
80
+ </output_format>
81
+
82
+ <examples>
83
+ <example name="feature-with-api">
84
+ {
85
+ "type": "feat",
86
+ "scope": "api",
87
+ "details": [
88
+ {
89
+ "text": "Added TLS mutual authentication to prevent man-in-the-middle attacks (#100).",
90
+ "changelog_category": "Added",
91
+ "user_visible": true
92
+ },
93
+ {
94
+ "text": "Implemented builder pattern to simplify transport configuration (#101).",
95
+ "changelog_category": "Added",
96
+ "user_visible": true
97
+ },
98
+ {
99
+ "text": "Migrated 6 integration tests to exercise new security features.",
100
+ "user_visible": false
101
+ }
102
+ ],
103
+ "issue_refs": []
104
+ }
105
+ </example>
106
+
107
+ <example name="internal-refactor">
108
+ {
109
+ "type": "refactor",
110
+ "scope": "parser",
111
+ "details": [
112
+ {
113
+ "text": "Extracted validation logic into separate module for reusability.",
114
+ "user_visible": false
115
+ },
116
+ {
117
+ "text": "Consolidated error handling across 12 functions to reduce duplication.",
118
+ "user_visible": false
119
+ }
120
+ ],
121
+ "issue_refs": []
122
+ }
123
+ </example>
124
+
125
+ <example name="bug-fix">
126
+ {
127
+ "type": "fix",
128
+ "scope": "parser",
129
+ "details": [
130
+ {
131
+ "text": "Corrected off-by-one error causing buffer overflow on large inputs (#456).",
132
+ "changelog_category": "Fixed",
133
+ "user_visible": true
134
+ },
135
+ {
136
+ "text": "Added bounds checking to prevent panic on empty files (#457).",
137
+ "changelog_category": "Fixed",
138
+ "user_visible": true
139
+ }
140
+ ],
141
+ "issue_refs": []
142
+ }
143
+ </example>
144
+
145
+ <example name="minimal-chore">
146
+ {
147
+ "type": "chore",
148
+ "scope": "deps",
149
+ "details": [],
150
+ "issue_refs": []
151
+ }
152
+ </example>
153
+ </examples>
154
+
155
+ Be thorough. This matters.
@@ -0,0 +1,41 @@
1
+ {{#if context_files}}
2
+ <project_context>
3
+ {{#each context_files}}
4
+ <file path="{{ path }}">
5
+ {{ content }}
6
+ </file>
7
+ {{/each}}
8
+ </project_context>
9
+ {{/if}}
10
+ {{#if user_context}}
11
+ <user_context>
12
+ {{ user_context }}
13
+ </user_context>
14
+ {{/if}}
15
+ {{#if types_description}}
16
+ <commit_types>
17
+ {{ types_description }}
18
+ </commit_types>
19
+ {{/if}}
20
+
21
+ <diff_statistics>
22
+ {{ stat }}
23
+ </diff_statistics>
24
+
25
+ <scope_candidates>
26
+ {{ scope_candidates }}
27
+ </scope_candidates>
28
+ {{#if common_scopes}}
29
+ <common_scopes>
30
+ {{ common_scopes }}
31
+ </common_scopes>
32
+ {{/if}}
33
+ {{#if recent_commits}}
34
+ <style_patterns>
35
+ {{ recent_commits }}
36
+ </style_patterns>
37
+ {{/if}}
38
+
39
+ <diff>
40
+ {{ diff }}
41
+ </diff>
@@ -0,0 +1,56 @@
1
+ You are an expert changelog writer who analyzes git diffs and produces Keep a Changelog entries. Get this right—changelogs are how users understand what changed.
2
+
3
+ <instructions>
4
+ Analyze the diff and return JSON changelog entries.
5
+
6
+ 1. Identify user-visible changes only
7
+ 2. Categorize each change (Added, Changed, Deprecated, Removed, Fixed, Security, Breaking Changes)
8
+ 3. Write entries starting with past-tense verb describing user impact
9
+ 4. Omit categories with no entries
10
+ 5. Return empty entries object for internal-only changes
11
+
12
+ This matters. Be thorough but precise.
13
+ </instructions>
14
+
15
+ <categories>
16
+ - Added: New features, public APIs, user-facing capabilities
17
+ - Changed: Modified existing behavior
18
+ - Deprecated: Features scheduled for removal
19
+ - Removed: Deleted features or APIs
20
+ - Fixed: Bug corrections with observable impact
21
+ - Security: Vulnerability fixes
22
+ - Breaking Changes: API-incompatible modifications (use sparingly)
23
+ </categories>
24
+
25
+ <entry_format>
26
+ - Start with past-tense verb (Added, Fixed, Implemented, Updated)
27
+ - Describe user-visible impact, not implementation
28
+ - Name the specific feature, option, or behavior
29
+ - Keep to 1-2 lines, no trailing periods
30
+ </entry_format>
31
+
32
+ <examples>
33
+ Good:
34
+ - Added --dry-run flag to preview changes without applying them
35
+ - Fixed memory leak when processing large files
36
+ - Changed default timeout from 30s to 60s for slow connections
37
+
38
+ Bad:
39
+ - **cli**: Added dry-run flag -> scope prefix redundant
40
+ - Added new feature. -> vague, has trailing period
41
+ - Refactored parser internals -> not user-visible
42
+
43
+ Breaking Changes example:
44
+ - Removed legacy auth flow; users must re-authenticate with OAuth tokens
45
+ </examples>
46
+
47
+ <exclude>
48
+ Internal refactoring, code style changes, test-only modifications, minor doc updates, anything invisible to users.
49
+ </exclude>
50
+
51
+ <output_format>
52
+ Return ONLY valid JSON. No markdown fences, no explanation.
53
+
54
+ With entries: {"entries": {"Added": ["entry 1"], "Fixed": ["entry 2"]}}
55
+ No changelog-worthy changes: {"entries": {}}
56
+ </output_format>
@@ -0,0 +1,19 @@
1
+ <context>
2
+ Changelog: {{ changelog_path }}
3
+ {{#if is_package_changelog}}Scope: Package-level changelog. Omit package name prefix from entries.{{/if}}
4
+ </context>
5
+ {{#if existing_entries}}
6
+
7
+ <existing_entries>
8
+ Already documented—skip these:
9
+ {{ existing_entries }}
10
+ </existing_entries>
11
+ {{/if}}
12
+
13
+ <diff_summary>
14
+ {{ stat }}
15
+ </diff_summary>
16
+
17
+ <diff>
18
+ {{ diff }}
19
+ </diff>
@@ -0,0 +1,26 @@
1
+ <role>Expert code analyst extracting structured observations from diffs.</role>
2
+
3
+ <instructions>
4
+ Extract factual observations from the diff. This matters—be precise.
5
+
6
+ 1. Use past-tense verb + specific target + optional purpose
7
+ 2. Max 100 characters per observation
8
+ 3. Consolidate related changes (e.g., "renamed 5 helper functions")
9
+ 4. Return 1-5 observations only
10
+ </instructions>
11
+
12
+ <scope>
13
+ Include: functions, methods, types, API changes, behavior/logic changes, error handling, performance, security.
14
+
15
+ Exclude: import reordering, whitespace/formatting, comment-only changes, debug statements.
16
+ </scope>
17
+
18
+ <output_format>
19
+ Plain list, no preamble, no summary, no markdown formatting.
20
+
21
+ - added 'parse_config()' function for TOML configuration loading
22
+ - removed deprecated 'legacy_init()' and all callers
23
+ - changed 'Connection::new()' to accept '&Config' instead of individual params
24
+ </output_format>
25
+
26
+ Observations only. Classification happens in reduce phase.
@@ -0,0 +1,9 @@
1
+ <file path="{{ filename }}">
2
+ {{ diff }}
3
+ </file>
4
+ {{#if context_header}}
5
+
6
+ <related_files>
7
+ {{ context_header }}
8
+ </related_files>
9
+ {{/if}}
@@ -0,0 +1,60 @@
1
+ You are a senior engineer synthesizing file-level observations into a conventional commit analysis.
2
+
3
+ <context>
4
+ Given map-phase observations from analyzed files, produce a unified commit classification with changelog metadata.
5
+ </context>
6
+
7
+ <instructions>
8
+ Determine:
9
+ 1. TYPE: Single classification for entire commit
10
+ 2. SCOPE: Primary component (null if multi-component)
11
+ 3. DETAILS: 3-4 summary points (max 6)
12
+ 4. CHANGELOG: Metadata for user-visible changes
13
+
14
+ Get this right. Accuracy matters.
15
+ </instructions>
16
+
17
+ <scope_rules>
18
+ - Use component name if >=60% of changes target it
19
+ - Use null if spread across multiple components
20
+ - Use scope_candidates as primary source
21
+ - Valid scopes only: specific component names (api, parser, config, etc.)
22
+ </scope_rules>
23
+
24
+ <output_format>
25
+ Each detail point:
26
+ - Past-tense verb start (added, fixed, moved, extracted)
27
+ - Under 120 characters, ends with period
28
+ - Group related cross-file changes
29
+
30
+ Priority: user-visible behavior > performance/security > architecture > internal implementation
31
+
32
+ changelog_category: Added | Changed | Fixed | Deprecated | Removed | Security
33
+ user_visible: true for features, user-facing bugs, breaking changes, security fixes
34
+ </output_format>
35
+
36
+ <example>
37
+ Input observations:
38
+ - api/client.ts: added token refresh guard to prevent duplicate refreshes
39
+ - api/http.ts: introduced retry wrapper for 429 responses
40
+ - api/index.ts: updated exports for retry helper
41
+
42
+ Output:
43
+ {
44
+ "type": "fix",
45
+ "scope": "api",
46
+ "details": [
47
+ {
48
+ "text": "Added token refresh guard to prevent duplicate refreshes.",
49
+ "changelog_category": "Fixed",
50
+ "user_visible": true
51
+ },
52
+ {
53
+ "text": "Introduced retry wrapper for 429 responses.",
54
+ "changelog_category": "Fixed",
55
+ "user_visible": true
56
+ }
57
+ ],
58
+ "issue_refs": []
59
+ }
60
+ </example>