@xopcai/xopc 0.0.122 → 0.0.124

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 (273) hide show
  1. package/README.md +28 -11
  2. package/README.zh-CN.md +28 -11
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CK3s5cJo.js → agent-avatar-dicebear-B5uSVAyJ.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +2 -0
  7. package/dist/gateway/static/root/assets/{app-management-settings-panel-CWsNHtTs.js → app-management-settings-panel-CYCONLIL.js} +1 -1
  8. package/dist/gateway/static/root/assets/{appearance-settings-C4b8y6iZ.js → appearance-settings-Clw3ryKg.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-DAtNW3Ia.js → archive-plugin-CXUGRp2i.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-Dm-RY54y.js → attachment-load-Cmiub3Wg.js} +1 -1
  12. package/dist/gateway/static/root/assets/{automation-suggestion-card-BKHewSVT.js → automation-suggestion-card-CU0-4nQ-.js} +1 -1
  13. package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +1 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-BG6Xnk71.js → binary-plugins-0Izz-N3p.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-DfndiO3h.js → block-editor-C1Kv0IkJ.js} +28 -28
  16. package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +8 -0
  17. package/dist/gateway/static/root/assets/{capability-presets-api-Cx93GLdw.js → capability-presets-api-BmQTM9Il.js} +1 -1
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +1 -0
  19. package/dist/gateway/static/root/assets/{channel-recipient-api-DdPTtEs8.js → channel-recipient-api-BeA2aVor.js} +1 -1
  20. package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +1 -0
  21. package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.js +2 -0
  22. package/dist/gateway/static/root/assets/{directory-picker-path-field-D835EHJd.js → directory-picker-path-field-2rjzUu57.js} +1 -1
  23. package/dist/gateway/static/root/assets/{dreaming-settings-CCa1F7Fg.js → dreaming-settings-DnHO686d.js} +1 -1
  24. package/dist/gateway/static/root/assets/{extension-debug-page-W2ITCPSA.js → extension-debug-page-BGLRuWVN.js} +1 -1
  25. package/dist/gateway/static/root/assets/{extension-page-DrvUytvn.js → extension-page-D978ePp9.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-settings-page-qM8aLT5u.js → extension-settings-page-B6Ih4Swx.js} +1 -1
  27. package/dist/gateway/static/root/assets/{fetch-ovkvM8KQ.js → fetch-BU5S0Sn7.js} +1 -1
  28. package/dist/gateway/static/root/assets/{gateway-config-api-BB3biuD0.js → gateway-config-api-BIPGwrl1.js} +1 -1
  29. package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +1 -0
  30. package/dist/gateway/static/root/assets/{gateway-startup-retry-CanQ8UcR.js → gateway-startup-retry-Cd0Zz30N.js} +1 -1
  31. package/dist/gateway/static/root/assets/{goal-create-dialog-CNqNdEkQ.js → goal-create-dialog-B-KHKeXN.js} +1 -1
  32. package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +1 -0
  33. package/dist/gateway/static/root/assets/{goals-config-api-BBOX6mUl.js → goals-config-api-B95KdGMj.js} +1 -1
  34. package/dist/gateway/static/root/assets/{goals-page-BP1kfvWv.js → goals-page-BTJzIl28.js} +2 -2
  35. package/dist/gateway/static/root/assets/{goals-settings-Bh3A7OZV.js → goals-settings-BJyEuLLm.js} +1 -1
  36. package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +1 -0
  37. package/dist/gateway/static/root/assets/index-BLaXr6Ev.css +1 -0
  38. package/dist/gateway/static/root/assets/index-c_9TVr_C.js +191 -0
  39. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B4TKJHla.js → keyboard-shortcuts-settings-BT8T4DyC.js} +1 -1
  40. package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +2 -0
  41. package/dist/gateway/static/root/assets/{markdown-split-DcFtdLci.js → markdown-split-Dv66bO2b.js} +1 -1
  42. package/dist/gateway/static/root/assets/{media-plugins-B6SmeLVB.js → media-plugins-BhIQU5yS.js} +1 -1
  43. package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +3 -0
  44. package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +2 -0
  45. package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +1 -0
  46. package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +2 -0
  47. package/dist/gateway/static/root/assets/{preview-open-alternatives-C29O19s7.js → preview-open-alternatives-DGzet1d7.js} +1 -1
  48. package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +1 -0
  49. package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +1 -0
  50. package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +1 -0
  51. package/dist/gateway/static/root/assets/{save-bar-controls-B4ad9GfB.js → save-bar-controls-Cqgb-jqa.js} +1 -1
  52. package/dist/gateway/static/root/assets/{schedule-field-DdYncfLR.js → schedule-field-DVZcI8Yt.js} +1 -1
  53. package/dist/gateway/static/root/assets/{schema-form-BMTrDE-7.js → schema-form-Bj7sOxC8.js} +1 -1
  54. package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +1 -0
  56. package/dist/gateway/static/root/assets/{settings-collapsible-section-MwTW2eK4.js → settings-collapsible-section-BmXn-8N6.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-form-section-Dg6LBbcr.js → settings-form-section-BnqYMWHR.js} +1 -1
  58. package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +1 -0
  59. package/dist/gateway/static/root/assets/{settings-page-layout-BX4T-OLF.js → settings-page-layout-CdWZU1hd.js} +1 -1
  60. package/dist/gateway/static/root/assets/{setup-status-panel-Ce1pcFtR.js → setup-status-panel-CWtPM7RK.js} +1 -1
  61. package/dist/gateway/static/root/assets/{share-preview-page-DWE-dUFh.js → share-preview-page-IB1v8i86.js} +1 -1
  62. package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +1 -0
  63. package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +1 -0
  64. package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +2 -0
  65. package/dist/gateway/static/root/assets/{system-settings-panel-Dd6Y35Cm.js → system-settings-panel-BxQ384RC.js} +1 -1
  66. package/dist/gateway/static/root/assets/{typed-models-lib-Cx6XV5A2.js → typed-models-lib-BkcpvFYO.js} +1 -1
  67. package/dist/gateway/static/root/assets/{use-channel-catalog-D4sMbmy7.js → use-channel-catalog-Cd0FaEQ4.js} +1 -1
  68. package/dist/gateway/static/root/assets/{user-profile-settings-panel-Bx-hjMQc.js → user-profile-settings-panel-DQ7NnRSY.js} +1 -1
  69. package/dist/gateway/static/root/assets/{utils-D7b_vZnv.js → utils-YKhVf7Ka.js} +1 -1
  70. package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +1 -0
  71. package/dist/gateway/static/root/assets/{workflow-run-setup-panel--TdohF5N.js → workflow-run-setup-panel-BYD9BtOq.js} +2 -2
  72. package/dist/gateway/static/root/assets/{workflow-start-dialog-B0lavx_o.js → workflow-start-dialog-BNJVCWoS.js} +1 -1
  73. package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +18 -0
  74. package/dist/gateway/static/root/index.html +5 -5
  75. package/dist/package.js +1 -1
  76. package/dist/src/agent/agent-manager.d.ts +6 -1
  77. package/dist/src/agent/agent-manager.js +28 -12
  78. package/dist/src/agent/agent-manager.js.map +1 -1
  79. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  80. package/dist/src/agent/embedded/xopc-tools-bridge.js +11 -7
  81. package/dist/src/agent/embedded/xopc-tools-bridge.js.map +1 -1
  82. package/dist/src/agent/lifecycle/progress.js +3 -1
  83. package/dist/src/agent/lifecycle/progress.js.map +1 -1
  84. package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +2 -2
  85. package/dist/src/agent/lifecycle/timeout-wrapper.js +4 -4
  86. package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
  87. package/dist/src/agent/memory/summary-generator.d.ts +1 -1
  88. package/dist/src/agent/memory/summary-generator.js +1 -2
  89. package/dist/src/agent/memory/summary-generator.js.map +1 -1
  90. package/dist/src/agent/middleware/index.d.ts +1 -1
  91. package/dist/src/agent/middleware/self-verify.d.ts +44 -14
  92. package/dist/src/agent/middleware/self-verify.js +214 -44
  93. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  94. package/dist/src/agent/orchestration/agent-event-handler.js +57 -15
  95. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  96. package/dist/src/agent/prompt/sections/tooling.js +18 -13
  97. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  98. package/dist/src/agent/prompt/system-reminder.js +2 -2
  99. package/dist/src/agent/prompt/system-reminder.js.map +1 -1
  100. package/dist/src/agent/sandbox/sanitize-env-vars.d.ts +2 -2
  101. package/dist/src/agent/sandbox/sanitize-env-vars.js +2 -2
  102. package/dist/src/agent/sandbox/sanitize-env-vars.js.map +1 -1
  103. package/dist/src/agent/sandbox/types.d.ts +2 -2
  104. package/dist/src/agent/sandbox/types.js.map +1 -1
  105. package/dist/src/agent/service/btw-query.js +1 -1
  106. package/dist/src/agent/service/btw-query.js.map +1 -1
  107. package/dist/src/agent/service/process-direct-one-shot.js +6 -2
  108. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  109. package/dist/src/agent/service/process-direct-streaming.js +12 -7
  110. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  111. package/dist/src/agent/service.js +2 -1
  112. package/dist/src/agent/service.js.map +1 -1
  113. package/dist/src/agent/skills/skill-tool-gating.js +1 -1
  114. package/dist/src/agent/skills/skill-tool-gating.js.map +1 -1
  115. package/dist/src/agent/starter-agents.js +9 -9
  116. package/dist/src/agent/starter-agents.js.map +1 -1
  117. package/dist/src/agent/tools/apply-patch.d.ts +25 -0
  118. package/dist/src/agent/tools/apply-patch.js +256 -0
  119. package/dist/src/agent/tools/apply-patch.js.map +1 -0
  120. package/dist/src/agent/tools/delegate-tool.d.ts +1 -1
  121. package/dist/src/agent/tools/delegate-tool.js +3 -3
  122. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  123. package/dist/src/agent/tools/exec-command.d.ts +30 -0
  124. package/dist/src/agent/tools/exec-command.js +224 -0
  125. package/dist/src/agent/tools/exec-command.js.map +1 -0
  126. package/dist/src/agent/tools/execute-code-tool.js +7 -4
  127. package/dist/src/agent/tools/execute-code-tool.js.map +1 -1
  128. package/dist/src/agent/tools/factory.d.ts +3 -3
  129. package/dist/src/agent/tools/factory.js +8 -9
  130. package/dist/src/agent/tools/factory.js.map +1 -1
  131. package/dist/src/agent/tools/goal-tool.d.ts +5 -1
  132. package/dist/src/agent/tools/goal-tool.js +8 -2
  133. package/dist/src/agent/tools/goal-tool.js.map +1 -1
  134. package/dist/src/agent/tools/index.d.ts +4 -3
  135. package/dist/src/agent/tools/index.js +5 -4
  136. package/dist/src/agent/tools/skills-tools.d.ts +1 -1
  137. package/dist/src/agent/tools/skills-tools.js.map +1 -1
  138. package/dist/src/agent/tools/update-plan-tool.d.ts +11 -0
  139. package/dist/src/agent/tools/update-plan-tool.js +72 -0
  140. package/dist/src/agent/tools/update-plan-tool.js.map +1 -0
  141. package/dist/src/agent/workflow/builtins/debug-incident.d.ts +1 -1
  142. package/dist/src/agent/workflow/builtins/debug-incident.js +1 -1
  143. package/dist/src/agent/workflow/builtins/debug-incident.js.map +1 -1
  144. package/dist/src/agent/workflow/builtins/pr-review.d.ts +1 -1
  145. package/dist/src/agent/workflow/builtins/pr-review.js +1 -1
  146. package/dist/src/agent/workflow/builtins/pr-review.js.map +1 -1
  147. package/dist/src/agent/workflow/builtins/release-check.d.ts +1 -1
  148. package/dist/src/agent/workflow/builtins/release-check.js +1 -1
  149. package/dist/src/agent/workflow/builtins/release-check.js.map +1 -1
  150. package/dist/src/agent/workflow/step-labels.js +7 -3
  151. package/dist/src/agent/workflow/step-labels.js.map +1 -1
  152. package/dist/src/chat-commands/agent-edit.js +1 -1
  153. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  154. package/dist/src/chat-commands/builtins/goal.js +4 -1
  155. package/dist/src/chat-commands/builtins/goal.js.map +1 -1
  156. package/dist/src/chat-commands/builtins/review.d.ts +1 -0
  157. package/dist/src/chat-commands/builtins/review.js +167 -0
  158. package/dist/src/chat-commands/builtins/review.js.map +1 -0
  159. package/dist/src/chat-commands/index.d.ts +1 -0
  160. package/dist/src/chat-commands/index.js +3 -1
  161. package/dist/src/chat-commands/index.js.map +1 -1
  162. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  163. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  164. package/dist/src/config/agent-profile.js +1 -1
  165. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  166. package/dist/src/gateway/agent-builtin-tools.js +3 -2
  167. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  168. package/dist/src/gateway/agents-admin.js +1 -1
  169. package/dist/src/gateway/chat-stream/mapper.d.ts +6 -0
  170. package/dist/src/gateway/chat-stream/mapper.js +149 -6
  171. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  172. package/dist/src/gateway/chat-stream/protocol.d.ts +51 -1
  173. package/dist/src/gateway/hono/routes/commands-skills.js +21 -0
  174. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  175. package/dist/src/gateway/hono/routes/index.js +2 -0
  176. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  177. package/dist/src/gateway/hono/routes/lazy-bundles.js +1 -0
  178. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  179. package/dist/src/gateway/hono/routes/projects.js +136 -14
  180. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  181. package/dist/src/gateway/hono/routes/search.d.ts +3 -0
  182. package/dist/src/gateway/hono/routes/search.js +47 -0
  183. package/dist/src/gateway/hono/routes/search.js.map +1 -0
  184. package/dist/src/gateway/security/dangerous-tools.js +1 -1
  185. package/dist/src/gateway/security/dangerous-tools.js.map +1 -1
  186. package/dist/src/infra/update-restart.js +1 -1
  187. package/dist/src/projects/index.d.ts +3 -0
  188. package/dist/src/projects/index.js +4 -1
  189. package/dist/src/projects/project-agent-suggestion.d.ts +14 -0
  190. package/dist/src/projects/project-agent-suggestion.js +19 -0
  191. package/dist/src/projects/project-agent-suggestion.js.map +1 -0
  192. package/dist/src/projects/project-kind.d.ts +13 -0
  193. package/dist/src/projects/project-kind.js +147 -0
  194. package/dist/src/projects/project-kind.js.map +1 -0
  195. package/dist/src/projects/project-service.d.ts +15 -0
  196. package/dist/src/projects/project-service.js +96 -3
  197. package/dist/src/projects/project-service.js.map +1 -1
  198. package/dist/src/projects/project-store.js +32 -8
  199. package/dist/src/projects/project-store.js.map +1 -1
  200. package/dist/src/projects/types.d.ts +4 -1
  201. package/dist/src/projects/workspace-project.d.ts +22 -0
  202. package/dist/src/projects/workspace-project.js +143 -0
  203. package/dist/src/projects/workspace-project.js.map +1 -0
  204. package/dist/src/review/review-git.d.ts +48 -0
  205. package/dist/src/review/review-git.js +333 -0
  206. package/dist/src/review/review-git.js.map +1 -0
  207. package/dist/src/review/review-types.d.ts +22 -0
  208. package/dist/src/review/review-types.js +29 -0
  209. package/dist/src/review/review-types.js.map +1 -0
  210. package/dist/src/session/session-context-for-llm.js +151 -0
  211. package/dist/src/session/session-context-for-llm.js.map +1 -1
  212. package/dist/src/storage/sqlite/migrations/021_projects_fts.sql +21 -0
  213. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  214. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  215. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  216. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  217. package/dist/src/storage/sqlite/schema.js +1 -1
  218. package/dist/src/tui/backends/embedded-backend.d.ts +8 -1
  219. package/dist/src/tui/backends/embedded-backend.js +60 -1
  220. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  221. package/dist/src/tui/backends/gateway-sse-backend.d.ts +9 -1
  222. package/dist/src/tui/backends/gateway-sse-backend.js +29 -0
  223. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  224. package/dist/src/tui/components/assistant-message.js +35 -0
  225. package/dist/src/tui/components/assistant-message.js.map +1 -1
  226. package/dist/src/tui/tui-agent-events.js +25 -0
  227. package/dist/src/tui/tui-agent-events.js.map +1 -1
  228. package/dist/src/tui/tui-backend.d.ts +20 -0
  229. package/dist/src/tui/tui-commands.d.ts +1 -0
  230. package/dist/src/tui/tui-commands.js +110 -4
  231. package/dist/src/tui/tui-commands.js.map +1 -1
  232. package/dist/src/tui/tui-picker-overlay.d.ts +2 -0
  233. package/dist/src/tui/tui-picker-overlay.js +153 -1
  234. package/dist/src/tui/tui-picker-overlay.js.map +1 -1
  235. package/dist/src/tui/tui.js +36 -2
  236. package/dist/src/tui/tui.js.map +1 -1
  237. package/dist/src/workflows/service/workflow-run-service.js +1 -1
  238. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  239. package/package.json +1 -1
  240. package/dist/gateway/static/root/assets/agents-SsQrj9B-.js +0 -2
  241. package/dist/gateway/static/root/assets/apps-page-CYb6fame.js +0 -1
  242. package/dist/gateway/static/root/assets/automations-page-DpOOq1nk.js +0 -1
  243. package/dist/gateway/static/root/assets/browser-settings-page-9nXxgh4u.js +0 -8
  244. package/dist/gateway/static/root/assets/capability-presets-settings-panel-D528_YFy.js +0 -1
  245. package/dist/gateway/static/root/assets/channels-settings-Ck-3h5lI.js +0 -1
  246. package/dist/gateway/static/root/assets/connectors-page-DL-fAqE_.js +0 -2
  247. package/dist/gateway/static/root/assets/gateway-settings-mmmnIH27.js +0 -1
  248. package/dist/gateway/static/root/assets/goal-detail-page-Ceu5zrN6.js +0 -1
  249. package/dist/gateway/static/root/assets/heartbeat-settings-YoYgKlfX.js +0 -1
  250. package/dist/gateway/static/root/assets/index-DdqSO9R2.js +0 -191
  251. package/dist/gateway/static/root/assets/index-jGB-2nI-.css +0 -1
  252. package/dist/gateway/static/root/assets/logs-page-BgVk5DvZ.js +0 -2
  253. package/dist/gateway/static/root/assets/messages-B5O4OIEo.js +0 -3
  254. package/dist/gateway/static/root/assets/models-hub-panel-BU0x8PGP.js +0 -2
  255. package/dist/gateway/static/root/assets/notes-page-D6JYVP4I.js +0 -1
  256. package/dist/gateway/static/root/assets/notes-workbench-mqRJYnJS.js +0 -2
  257. package/dist/gateway/static/root/assets/project-detail-page-DOTgzoeh.js +0 -1
  258. package/dist/gateway/static/root/assets/projects-page-DGUIb4y5.js +0 -1
  259. package/dist/gateway/static/root/assets/remote-access-hub-DVKKUj3u.js +0 -1
  260. package/dist/gateway/static/root/assets/sessions-page-BVbzUWxW.js +0 -1
  261. package/dist/gateway/static/root/assets/settings-advanced-gate-DrNNoSqE.js +0 -1
  262. package/dist/gateway/static/root/assets/settings-page-CMDqgeMR.js +0 -1
  263. package/dist/gateway/static/root/assets/shares-settings-aKSraR8l.js +0 -1
  264. package/dist/gateway/static/root/assets/skill-reload-api-CS-FU_B-.js +0 -1
  265. package/dist/gateway/static/root/assets/skills-page-BaF3u0LA.js +0 -2
  266. package/dist/gateway/static/root/assets/voice-api-key-field-CkhbRt1q.js +0 -1
  267. package/dist/gateway/static/root/assets/workflows-page-CZR05Bu_.js +0 -18
  268. package/dist/src/agent/tools/edit.d.ts +0 -14
  269. package/dist/src/agent/tools/edit.js +0 -132
  270. package/dist/src/agent/tools/edit.js.map +0 -1
  271. package/dist/src/agent/tools/shell.d.ts +0 -15
  272. package/dist/src/agent/tools/shell.js +0 -158
  273. package/dist/src/agent/tools/shell.js.map +0 -1
@@ -7,10 +7,11 @@ const MAX_DETAIL_LEN = 120;
7
7
  function workflowStepLabel(toolName, args) {
8
8
  const n = toolName.toLowerCase().replace(/-/g, "_").trim();
9
9
  let label = toolName.trim() || "tool";
10
- if (n === "shell") label = "Run command";
10
+ if (n === "exec_command") label = "Run command";
11
+ else if (n === "update_plan") label = "Update plan";
11
12
  else if (n === "list_dir" || n === "ls") label = "List directory";
12
13
  else if (n === "write_file") label = "Write file";
13
- else if (n === "edit_file") label = "Edit file";
14
+ else if (n === "apply_patch") label = "Edit file";
14
15
  else if (n === "web_fetch") label = "Fetch URL";
15
16
  else if (n === "open_url") label = "Open URL";
16
17
  else if (n === "grep" || n === "rg" || n === "file_grep") label = "Search files";
@@ -34,7 +35,10 @@ function extractStepDetail(toolKey, args) {
34
35
  const v = args[key];
35
36
  if (typeof v === "string" && v.trim()) return truncate(v.trim());
36
37
  }
37
- if (toolKey === "shell" && typeof args.command === "string" && args.command.trim()) return truncate(args.command.trim());
38
+ if (toolKey === "exec_command") {
39
+ const command = typeof args.cmd === "string" ? args.cmd : typeof args.command === "string" ? args.command : "";
40
+ if (command.trim()) return truncate(command.trim());
41
+ }
38
42
  if ((toolKey.includes("search") || toolKey === "grep" || toolKey === "rg" || toolKey === "file_grep") && typeof args.query === "string" && args.query.trim()) return truncate(args.query.trim());
39
43
  if (typeof args.url === "string" && args.url.trim()) return truncate(args.url.trim());
40
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"step-labels.js","names":[],"sources":["../../../../src/agent/workflow/step-labels.ts"],"sourcesContent":["/**\n * Human-readable labels for workflow subagent tool steps (server-side snapshot).\n * Mirrors the web `tool-friendly-title` rules so IM/TUI and gateway stay aligned.\n */\n\nconst MAX_DETAIL_LEN = 120;\n\nexport function workflowStepLabel(\n toolName: string,\n args: Record<string, unknown>,\n): { label: string; detail?: string } {\n const n = toolName.toLowerCase().replace(/-/g, '_').trim();\n let label = toolName.trim() || 'tool';\n if (n === 'shell') label = 'Run command';\n else if (n === 'list_dir' || n === 'ls') label = 'List directory';\n else if (n === 'write_file') label = 'Write file';\n else if (n === 'edit_file') label = 'Edit file';\n else if (n === 'web_fetch') label = 'Fetch URL';\n else if (n === 'open_url') label = 'Open URL';\n else if (n === 'grep' || n === 'rg' || n === 'file_grep') label = 'Search files';\n else if (n === 'web_search' || n === 'brave_search' || n.includes('search')) label = 'Search web';\n else if (n === 'read_file' || n.includes('read_file') || n.includes('file_read')) label = 'Read file';\n else if (n === 'delegate_task' || n === 'workflow') label = toolName;\n\n const detail = extractStepDetail(n, args);\n return detail ? { label, detail } : { label };\n}\n\nfunction extractStepDetail(toolKey: string, args: Record<string, unknown>): string | undefined {\n const pathKeys = ['path', 'file_path', 'filePath', 'target_file', 'targetFile'];\n for (const key of pathKeys) {\n const v = args[key];\n if (typeof v === 'string' && v.trim()) return truncate(v.trim());\n }\n if (toolKey === 'shell' && typeof args.command === 'string' && args.command.trim()) {\n return truncate(args.command.trim());\n }\n if (\n (toolKey.includes('search') || toolKey === 'grep' || toolKey === 'rg' || toolKey === 'file_grep') &&\n typeof args.query === 'string' &&\n args.query.trim()\n ) {\n return truncate(args.query.trim());\n }\n if (typeof args.url === 'string' && args.url.trim()) return truncate(args.url.trim());\n return undefined;\n}\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_DETAIL_LEN) return text;\n return `${text.slice(0, MAX_DETAIL_LEN - 1)}…`;\n}\n"],"mappings":";;;;;AAKA,MAAM,iBAAiB;AAEvB,SAAgB,kBACd,UACA,MACoC;CACpC,MAAM,IAAI,SAAS,aAAa,CAAC,QAAQ,MAAM,IAAI,CAAC,MAAM;CAC1D,IAAI,QAAQ,SAAS,MAAM,IAAI;AAC/B,KAAI,MAAM,QAAS,SAAQ;UAClB,MAAM,cAAc,MAAM,KAAM,SAAQ;UACxC,MAAM,aAAc,SAAQ;UAC5B,MAAM,YAAa,SAAQ;UAC3B,MAAM,YAAa,SAAQ;UAC3B,MAAM,WAAY,SAAQ;UAC1B,MAAM,UAAU,MAAM,QAAQ,MAAM,YAAa,SAAQ;UACzD,MAAM,gBAAgB,MAAM,kBAAkB,EAAE,SAAS,SAAS,CAAE,SAAQ;UAC5E,MAAM,eAAe,EAAE,SAAS,YAAY,IAAI,EAAE,SAAS,YAAY,CAAE,SAAQ;UACjF,MAAM,mBAAmB,MAAM,WAAY,SAAQ;CAE5D,MAAM,SAAS,kBAAkB,GAAG,KAAK;AACzC,QAAO,SAAS;EAAE;EAAO;EAAQ,GAAG,EAAE,OAAO;;AAG/C,SAAS,kBAAkB,SAAiB,MAAmD;AAE7F,MAAK,MAAM,OAAO;EADA;EAAQ;EAAa;EAAY;EAAe;EACxC,EAAE;EAC1B,MAAM,IAAI,KAAK;AACf,MAAI,OAAO,MAAM,YAAY,EAAE,MAAM,CAAE,QAAO,SAAS,EAAE,MAAM,CAAC;;AAElE,KAAI,YAAY,WAAW,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,MAAM,CAChF,QAAO,SAAS,KAAK,QAAQ,MAAM,CAAC;AAEtC,MACG,QAAQ,SAAS,SAAS,IAAI,YAAY,UAAU,YAAY,QAAQ,YAAY,gBACrF,OAAO,KAAK,UAAU,YACtB,KAAK,MAAM,MAAM,CAEjB,QAAO,SAAS,KAAK,MAAM,MAAM,CAAC;AAEpC,KAAI,OAAO,KAAK,QAAQ,YAAY,KAAK,IAAI,MAAM,CAAE,QAAO,SAAS,KAAK,IAAI,MAAM,CAAC;;AAIvF,SAAS,SAAS,MAAsB;AACtC,KAAI,KAAK,UAAU,eAAgB,QAAO;AAC1C,QAAO,GAAG,KAAK,MAAM,GAAG,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"step-labels.js","names":[],"sources":["../../../../src/agent/workflow/step-labels.ts"],"sourcesContent":["/**\n * Human-readable labels for workflow subagent tool steps (server-side snapshot).\n * Mirrors the web `tool-friendly-title` rules so IM/TUI and gateway stay aligned.\n */\n\nconst MAX_DETAIL_LEN = 120;\n\nexport function workflowStepLabel(\n toolName: string,\n args: Record<string, unknown>,\n): { label: string; detail?: string } {\n const n = toolName.toLowerCase().replace(/-/g, '_').trim();\n let label = toolName.trim() || 'tool';\n if (n === 'exec_command') label = 'Run command';\n else if (n === 'update_plan') label = 'Update plan';\n else if (n === 'list_dir' || n === 'ls') label = 'List directory';\n else if (n === 'write_file') label = 'Write file';\n else if (n === 'apply_patch') label = 'Edit file';\n else if (n === 'web_fetch') label = 'Fetch URL';\n else if (n === 'open_url') label = 'Open URL';\n else if (n === 'grep' || n === 'rg' || n === 'file_grep') label = 'Search files';\n else if (n === 'web_search' || n === 'brave_search' || n.includes('search')) label = 'Search web';\n else if (n === 'read_file' || n.includes('read_file') || n.includes('file_read')) label = 'Read file';\n else if (n === 'delegate_task' || n === 'workflow') label = toolName;\n\n const detail = extractStepDetail(n, args);\n return detail ? { label, detail } : { label };\n}\n\nfunction extractStepDetail(toolKey: string, args: Record<string, unknown>): string | undefined {\n const pathKeys = ['path', 'file_path', 'filePath', 'target_file', 'targetFile'];\n for (const key of pathKeys) {\n const v = args[key];\n if (typeof v === 'string' && v.trim()) return truncate(v.trim());\n }\n if (toolKey === 'exec_command') {\n const command = typeof args.cmd === 'string' ? args.cmd : typeof args.command === 'string' ? args.command : '';\n if (command.trim()) return truncate(command.trim());\n }\n if (\n (toolKey.includes('search') || toolKey === 'grep' || toolKey === 'rg' || toolKey === 'file_grep') &&\n typeof args.query === 'string' &&\n args.query.trim()\n ) {\n return truncate(args.query.trim());\n }\n if (typeof args.url === 'string' && args.url.trim()) return truncate(args.url.trim());\n return undefined;\n}\n\nfunction truncate(text: string): string {\n if (text.length <= MAX_DETAIL_LEN) return text;\n return `${text.slice(0, MAX_DETAIL_LEN - 1)}…`;\n}\n"],"mappings":";;;;;AAKA,MAAM,iBAAiB;AAEvB,SAAgB,kBACd,UACA,MACoC;CACpC,MAAM,IAAI,SAAS,aAAa,CAAC,QAAQ,MAAM,IAAI,CAAC,MAAM;CAC1D,IAAI,QAAQ,SAAS,MAAM,IAAI;AAC/B,KAAI,MAAM,eAAgB,SAAQ;UACzB,MAAM,cAAe,SAAQ;UAC7B,MAAM,cAAc,MAAM,KAAM,SAAQ;UACxC,MAAM,aAAc,SAAQ;UAC5B,MAAM,cAAe,SAAQ;UAC7B,MAAM,YAAa,SAAQ;UAC3B,MAAM,WAAY,SAAQ;UAC1B,MAAM,UAAU,MAAM,QAAQ,MAAM,YAAa,SAAQ;UACzD,MAAM,gBAAgB,MAAM,kBAAkB,EAAE,SAAS,SAAS,CAAE,SAAQ;UAC5E,MAAM,eAAe,EAAE,SAAS,YAAY,IAAI,EAAE,SAAS,YAAY,CAAE,SAAQ;UACjF,MAAM,mBAAmB,MAAM,WAAY,SAAQ;CAE5D,MAAM,SAAS,kBAAkB,GAAG,KAAK;AACzC,QAAO,SAAS;EAAE;EAAO;EAAQ,GAAG,EAAE,OAAO;;AAG/C,SAAS,kBAAkB,SAAiB,MAAmD;AAE7F,MAAK,MAAM,OAAO;EADA;EAAQ;EAAa;EAAY;EAAe;EACxC,EAAE;EAC1B,MAAM,IAAI,KAAK;AACf,MAAI,OAAO,MAAM,YAAY,EAAE,MAAM,CAAE,QAAO,SAAS,EAAE,MAAM,CAAC;;AAElE,KAAI,YAAY,gBAAgB;EAC9B,MAAM,UAAU,OAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;AAC5G,MAAI,QAAQ,MAAM,CAAE,QAAO,SAAS,QAAQ,MAAM,CAAC;;AAErD,MACG,QAAQ,SAAS,SAAS,IAAI,YAAY,UAAU,YAAY,QAAQ,YAAY,gBACrF,OAAO,KAAK,UAAU,YACtB,KAAK,MAAM,MAAM,CAEjB,QAAO,SAAS,KAAK,MAAM,MAAM,CAAC;AAEpC,KAAI,OAAO,KAAK,QAAQ,YAAY,KAAK,IAAI,MAAM,CAAE,QAAO,SAAS,KAAK,IAAI,MAAM,CAAC;;AAIvF,SAAS,SAAS,MAAsB;AACtC,KAAI,KAAK,UAAU,eAAgB,QAAO;AAC1C,QAAO,GAAG,KAAK,MAAM,GAAG,iBAAiB,EAAE,CAAC"}
@@ -74,7 +74,7 @@ function buildEditInstructions(agentId, fileNames) {
74
74
  "- “Read `SOUL.md` first, propose changes, then write them back.”",
75
75
  "",
76
76
  `Editable profile files: ${files}.`,
77
- "I can read and update these by bare filename with `read_file`, `edit_file`, and `write_file`."
77
+ "I can read and update these by bare filename with `read_file`, `apply_patch`, and `write_file`."
78
78
  ].join("\n");
79
79
  }
80
80
  const agentEditCommand = {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-edit.js","names":[],"sources":["../../../src/chat-commands/agent-edit.ts"],"sourcesContent":["/**\n * /agent-edit — open the current chat as an agent profile editing session.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport type { CommandContext, CommandDefinition } from './types.js';\nimport { commandRegistry } from './registry.js';\nimport { resolveAgentIdFromSessionKey } from '../routing/agent-session-key.js';\nimport { normalizeAgentId, resolveAgentProfileDir } from '../agent/agent-scope.js';\nimport { WORKSPACE_FILES } from '../config/paths.js';\n\nconst PROFILE_FILE_NAMES = [\n WORKSPACE_FILES.SOUL,\n WORKSPACE_FILES.IDENTITY,\n WORKSPACE_FILES.TOOLS,\n WORKSPACE_FILES.AGENTS,\n WORKSPACE_FILES.HEARTBEAT,\n WORKSPACE_FILES.MEMORY,\n] as const;\n\nconst DEFAULT_PREVIEW_CHARS = 900;\nconst MAX_PREVIEW_CHARS = 4_000;\n\nfunction parseArgs(args: string): { fileName?: string; previewChars: number } {\n const trimmed = args.trim();\n if (!trimmed) {\n return { previewChars: DEFAULT_PREVIEW_CHARS };\n }\n\n const parts = trimmed.split(/\\s+/);\n let fileName: string | undefined;\n let previewChars = DEFAULT_PREVIEW_CHARS;\n\n for (const part of parts) {\n const limitMatch = /^--limit=(\\d+)$/.exec(part);\n if (limitMatch) {\n previewChars = Math.min(Number(limitMatch[1]), MAX_PREVIEW_CHARS);\n continue;\n }\n if (!fileName) {\n fileName = part;\n }\n }\n\n return { fileName, previewChars };\n}\n\nfunction normalizeProfileFileName(input: string | undefined): string | undefined {\n if (!input) {\n return undefined;\n }\n const basename = input.trim().replace(/\\\\/g, '/').split('/').pop();\n const matched = PROFILE_FILE_NAMES.find((name) => name.toLowerCase() === basename?.toLowerCase());\n return matched;\n}\n\nasync function readPreview(path: string, limit: number): Promise<{ content: string; missing: boolean }> {\n try {\n const content = await readFile(path, 'utf-8');\n const trimmed = content.trimEnd();\n if (trimmed.length <= limit) {\n return { content: trimmed, missing: false };\n }\n return {\n content: `${trimmed.slice(0, limit)}\\n\\n… truncated, ask me to read the full file before editing …`,\n missing: false,\n };\n } catch {\n return { content: '', missing: true };\n }\n}\n\nfunction buildEditInstructions(agentId: string, fileNames: readonly string[]): string {\n const files = fileNames.map((name) => `\\`${name}\\``).join(', ');\n return [\n `You are editing agent \\`${agentId}\\`.`,\n '',\n 'Tell me what to change, or say things like:',\n '- “Refine `SOUL.md` to sound warmer and more concise.”',\n '- “Update `IDENTITY.md` so this agent is focused on data analysis.”',\n '- “Read `SOUL.md` first, propose changes, then write them back.”',\n '',\n `Editable profile files: ${files}.`,\n 'I can read and update these by bare filename with `read_file`, `edit_file`, and `write_file`.',\n ].join('\\n');\n}\n\nconst agentEditCommand: CommandDefinition = {\n id: 'agent.edit',\n name: 'agent-edit',\n aliases: ['agentedit'],\n description: 'Show editable profile files for the current agent and prepare this chat for profile edits.',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/agent-edit', '/agent-edit SOUL.md', '/agent-edit IDENTITY.md --limit=2000'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n\n const { fileName: rawFileName, previewChars } = parseArgs(args);\n const fileName = normalizeProfileFileName(rawFileName);\n if (rawFileName && !fileName) {\n return {\n content: `⚠️ Unsupported profile file: \\`${rawFileName}\\`. Use one of: ${PROFILE_FILE_NAMES.map((name) => `\\`${name}\\``).join(', ')}.`,\n success: false,\n };\n }\n\n const agentId = normalizeAgentId(resolveAgentIdFromSessionKey(ctx.sessionKey));\n const profileDir = resolveAgentProfileDir(ctx.config, agentId);\n const namesToShow = fileName ? [fileName] : [WORKSPACE_FILES.SOUL, WORKSPACE_FILES.IDENTITY];\n\n const sections: string[] = [];\n for (const name of namesToShow) {\n const preview = await readPreview(join(profileDir, name), previewChars);\n if (preview.missing) {\n sections.push(`## ${name}\\n_missing_`);\n } else {\n sections.push(`## ${name}\\n\\`\\`\\`markdown\\n${preview.content}\\n\\`\\`\\``);\n }\n }\n\n return {\n content: [\n '🛠️ Agent editor mode',\n '',\n buildEditInstructions(agentId, PROFILE_FILE_NAMES),\n '',\n `Profile directory: \\`${profileDir}\\``,\n '',\n ...sections,\n ].join('\\n'),\n success: true,\n };\n },\n};\n\nexport function registerAgentEditCommand(): void {\n commandRegistry.register(agentEditCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agent-edit.js","names":[],"sources":["../../../src/chat-commands/agent-edit.ts"],"sourcesContent":["/**\n * /agent-edit — open the current chat as an agent profile editing session.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nimport type { CommandContext, CommandDefinition } from './types.js';\nimport { commandRegistry } from './registry.js';\nimport { resolveAgentIdFromSessionKey } from '../routing/agent-session-key.js';\nimport { normalizeAgentId, resolveAgentProfileDir } from '../agent/agent-scope.js';\nimport { WORKSPACE_FILES } from '../config/paths.js';\n\nconst PROFILE_FILE_NAMES = [\n WORKSPACE_FILES.SOUL,\n WORKSPACE_FILES.IDENTITY,\n WORKSPACE_FILES.TOOLS,\n WORKSPACE_FILES.AGENTS,\n WORKSPACE_FILES.HEARTBEAT,\n WORKSPACE_FILES.MEMORY,\n] as const;\n\nconst DEFAULT_PREVIEW_CHARS = 900;\nconst MAX_PREVIEW_CHARS = 4_000;\n\nfunction parseArgs(args: string): { fileName?: string; previewChars: number } {\n const trimmed = args.trim();\n if (!trimmed) {\n return { previewChars: DEFAULT_PREVIEW_CHARS };\n }\n\n const parts = trimmed.split(/\\s+/);\n let fileName: string | undefined;\n let previewChars = DEFAULT_PREVIEW_CHARS;\n\n for (const part of parts) {\n const limitMatch = /^--limit=(\\d+)$/.exec(part);\n if (limitMatch) {\n previewChars = Math.min(Number(limitMatch[1]), MAX_PREVIEW_CHARS);\n continue;\n }\n if (!fileName) {\n fileName = part;\n }\n }\n\n return { fileName, previewChars };\n}\n\nfunction normalizeProfileFileName(input: string | undefined): string | undefined {\n if (!input) {\n return undefined;\n }\n const basename = input.trim().replace(/\\\\/g, '/').split('/').pop();\n const matched = PROFILE_FILE_NAMES.find((name) => name.toLowerCase() === basename?.toLowerCase());\n return matched;\n}\n\nasync function readPreview(path: string, limit: number): Promise<{ content: string; missing: boolean }> {\n try {\n const content = await readFile(path, 'utf-8');\n const trimmed = content.trimEnd();\n if (trimmed.length <= limit) {\n return { content: trimmed, missing: false };\n }\n return {\n content: `${trimmed.slice(0, limit)}\\n\\n… truncated, ask me to read the full file before editing …`,\n missing: false,\n };\n } catch {\n return { content: '', missing: true };\n }\n}\n\nfunction buildEditInstructions(agentId: string, fileNames: readonly string[]): string {\n const files = fileNames.map((name) => `\\`${name}\\``).join(', ');\n return [\n `You are editing agent \\`${agentId}\\`.`,\n '',\n 'Tell me what to change, or say things like:',\n '- “Refine `SOUL.md` to sound warmer and more concise.”',\n '- “Update `IDENTITY.md` so this agent is focused on data analysis.”',\n '- “Read `SOUL.md` first, propose changes, then write them back.”',\n '',\n `Editable profile files: ${files}.`,\n 'I can read and update these by bare filename with `read_file`, `apply_patch`, and `write_file`.',\n ].join('\\n');\n}\n\nconst agentEditCommand: CommandDefinition = {\n id: 'agent.edit',\n name: 'agent-edit',\n aliases: ['agentedit'],\n description: 'Show editable profile files for the current agent and prepare this chat for profile edits.',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/agent-edit', '/agent-edit SOUL.md', '/agent-edit IDENTITY.md --limit=2000'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n\n const { fileName: rawFileName, previewChars } = parseArgs(args);\n const fileName = normalizeProfileFileName(rawFileName);\n if (rawFileName && !fileName) {\n return {\n content: `⚠️ Unsupported profile file: \\`${rawFileName}\\`. Use one of: ${PROFILE_FILE_NAMES.map((name) => `\\`${name}\\``).join(', ')}.`,\n success: false,\n };\n }\n\n const agentId = normalizeAgentId(resolveAgentIdFromSessionKey(ctx.sessionKey));\n const profileDir = resolveAgentProfileDir(ctx.config, agentId);\n const namesToShow = fileName ? [fileName] : [WORKSPACE_FILES.SOUL, WORKSPACE_FILES.IDENTITY];\n\n const sections: string[] = [];\n for (const name of namesToShow) {\n const preview = await readPreview(join(profileDir, name), previewChars);\n if (preview.missing) {\n sections.push(`## ${name}\\n_missing_`);\n } else {\n sections.push(`## ${name}\\n\\`\\`\\`markdown\\n${preview.content}\\n\\`\\`\\``);\n }\n }\n\n return {\n content: [\n '🛠️ Agent editor mode',\n '',\n buildEditInstructions(agentId, PROFILE_FILE_NAMES),\n '',\n `Profile directory: \\`${profileDir}\\``,\n '',\n ...sections,\n ].join('\\n'),\n success: true,\n };\n },\n};\n\nexport function registerAgentEditCommand(): void {\n commandRegistry.register(agentEditCommand);\n}\n"],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
2
2
  import { GoalService } from "../../goals/goal-service.js";
3
3
  import "../../goals/index.js";
4
+ import { getSessionMetadata } from "../../storage/sqlite/session-repository.js";
5
+ import "../../storage/sqlite/index.js";
4
6
  import { commandRegistry } from "../registry.js";
5
7
  //#region src/chat-commands/builtins/goal.ts
6
8
  init_resolve_route();
@@ -101,7 +103,8 @@ const goalCommand = {
101
103
  sessionKey: ctx.sessionKey,
102
104
  agentId: getDefaultAgentId(ctx.config),
103
105
  config: ctx.config,
104
- source: ctx.source === "cli" ? "cli" : ctx.source === "api" ? "api" : "channel"
106
+ source: ctx.source === "cli" ? "cli" : ctx.source === "api" ? "api" : "channel",
107
+ projectId: getSessionMetadata(ctx.sessionKey)?.projectId
105
108
  });
106
109
  ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, goal.title);
107
110
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"goal.js","names":[],"sources":["../../../../src/chat-commands/builtins/goal.ts"],"sourcesContent":["/**\n * `/goal` — first-class goal control from any command surface.\n */\n\nimport { getDefaultAgentId } from '../../routing/resolve-route.js';\nimport { GoalService, type GoalWithDetails } from '../../goals/index.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nconst goals = new GoalService();\n\nfunction statusLine(goal: GoalWithDetails): string {\n const turns = `${goal.turnsUsed}/${goal.maxTurns} turns`;\n const progress = goal.checklist.length\n ? ` · ${goal.checklist.filter((it) => it.status === 'completed' || it.status === 'impossible').length}/${goal.checklist.length} criteria`\n : '';\n if (goal.status === 'active') return `⊙ Goal (active, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'paused') return `⏸ Goal (paused, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'blocked' || goal.status === 'needs_input') {\n const reason = goal.blockedReason ? ` — ${goal.blockedReason}` : '';\n return `⏸ Goal (${goal.status}, ${turns}${progress}${reason}): ${goal.title}`;\n }\n if (goal.status === 'done') return `✓ Goal done (${turns}${progress}): ${goal.title}`;\n return `Goal (${goal.status}, ${turns}${progress}): ${goal.title}`;\n}\n\nfunction activeGoal(ctx: CommandContext): GoalWithDetails | null {\n return goals.getActiveForSession(ctx.sessionKey);\n}\n\nconst goalCommand: CommandDefinition = {\n id: 'system.goal',\n name: 'goal',\n description: 'Create and manage a durable goal: checklist + judge loop; /subgoal edits criteria',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/goal Ship the fix', '/goal status', '/goal pause', '/goal resume', '/goal clear'],\n handler: async (ctx: CommandContext, args: string) => {\n const t = args.trim();\n const lower = t.toLowerCase();\n\n if (!t || lower === 'status') {\n const goal = activeGoal(ctx);\n return {\n content: goal ? statusLine(goal) : 'No active goal. Set one with /goal <text>.',\n success: true,\n };\n }\n\n if (lower === 'pause') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n const next = goals.pause(goal.id);\n return { content: `⏸ Goal paused: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'resume') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No goal to resume.', success: true };\n const next = goals.resume(goal.id);\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, next?.nextAction || next?.title || goal.title);\n return { content: `▶ Goal resumed: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'clear' || lower === 'stop' || lower === 'archive') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n goals.archive(goal.id);\n try {\n await ctx.abortCurrentTurn?.();\n } catch {\n return { content: '✓ Goal archived. Current turn could not be stopped automatically.', success: true };\n }\n return { content: '✓ Goal archived.', success: true };\n }\n\n const depth = ctx.persistentGoalApis?.inboundConcurrentDepth(ctx.sessionKey) ?? 0;\n if (depth > 1) {\n return {\n content:\n 'Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.',\n success: false,\n };\n }\n\n const goal = goals.create({\n title: t,\n sessionKey: ctx.sessionKey,\n agentId: getDefaultAgentId(ctx.config),\n config: ctx.config,\n source: ctx.source === 'cli' ? 'cli' : ctx.source === 'api' ? 'api' : 'channel',\n });\n\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, goal.title);\n\n return {\n content:\n `⊙ Goal set (${goal.maxTurns}-turn budget): ${goal.title}\\n` +\n \"I'll keep working until the goal is done, you pause/archive it, or the budget is exhausted.\\n\" +\n 'Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal',\n success: true,\n };\n },\n};\n\nexport function registerGoalCommand(): void {\n commandRegistry.register(goalCommand);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"goal.js","names":[],"sources":["../../../../src/chat-commands/builtins/goal.ts"],"sourcesContent":["/**\n * `/goal` — first-class goal control from any command surface.\n */\n\nimport { getDefaultAgentId } from '../../routing/resolve-route.js';\nimport { GoalService, type GoalWithDetails } from '../../goals/index.js';\nimport { getSessionMetadata } from '../../storage/sqlite/index.js';\nimport type { CommandContext, CommandDefinition } from '../types.js';\nimport { commandRegistry } from '../registry.js';\n\nconst goals = new GoalService();\n\nfunction statusLine(goal: GoalWithDetails): string {\n const turns = `${goal.turnsUsed}/${goal.maxTurns} turns`;\n const progress = goal.checklist.length\n ? ` · ${goal.checklist.filter((it) => it.status === 'completed' || it.status === 'impossible').length}/${goal.checklist.length} criteria`\n : '';\n if (goal.status === 'active') return `⊙ Goal (active, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'paused') return `⏸ Goal (paused, ${turns}${progress}): ${goal.title}`;\n if (goal.status === 'blocked' || goal.status === 'needs_input') {\n const reason = goal.blockedReason ? ` — ${goal.blockedReason}` : '';\n return `⏸ Goal (${goal.status}, ${turns}${progress}${reason}): ${goal.title}`;\n }\n if (goal.status === 'done') return `✓ Goal done (${turns}${progress}): ${goal.title}`;\n return `Goal (${goal.status}, ${turns}${progress}): ${goal.title}`;\n}\n\nfunction activeGoal(ctx: CommandContext): GoalWithDetails | null {\n return goals.getActiveForSession(ctx.sessionKey);\n}\n\nconst goalCommand: CommandDefinition = {\n id: 'system.goal',\n name: 'goal',\n description: 'Create and manage a durable goal: checklist + judge loop; /subgoal edits criteria',\n category: 'system',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/goal Ship the fix', '/goal status', '/goal pause', '/goal resume', '/goal clear'],\n handler: async (ctx: CommandContext, args: string) => {\n const t = args.trim();\n const lower = t.toLowerCase();\n\n if (!t || lower === 'status') {\n const goal = activeGoal(ctx);\n return {\n content: goal ? statusLine(goal) : 'No active goal. Set one with /goal <text>.',\n success: true,\n };\n }\n\n if (lower === 'pause') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n const next = goals.pause(goal.id);\n return { content: `⏸ Goal paused: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'resume') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No goal to resume.', success: true };\n const next = goals.resume(goal.id);\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, next?.nextAction || next?.title || goal.title);\n return { content: `▶ Goal resumed: ${next?.title ?? goal.title}`, success: true };\n }\n\n if (lower === 'clear' || lower === 'stop' || lower === 'archive') {\n const goal = activeGoal(ctx);\n if (!goal) return { content: 'No active goal.', success: true };\n goals.archive(goal.id);\n try {\n await ctx.abortCurrentTurn?.();\n } catch {\n return { content: '✓ Goal archived. Current turn could not be stopped automatically.', success: true };\n }\n return { content: '✓ Goal archived.', success: true };\n }\n\n const depth = ctx.persistentGoalApis?.inboundConcurrentDepth(ctx.sessionKey) ?? 0;\n if (depth > 1) {\n return {\n content:\n 'Agent is running — use /goal status / pause / clear mid-run, or wait for the current turn to finish before setting a new goal.',\n success: false,\n };\n }\n\n const goal = goals.create({\n title: t,\n sessionKey: ctx.sessionKey,\n agentId: getDefaultAgentId(ctx.config),\n config: ctx.config,\n source: ctx.source === 'cli' ? 'cli' : ctx.source === 'api' ? 'api' : 'channel',\n projectId: getSessionMetadata(ctx.sessionKey)?.projectId,\n });\n\n ctx.persistentGoalApis?.scheduleContinuation(ctx.sessionKey, goal.title);\n\n return {\n content:\n `⊙ Goal set (${goal.maxTurns}-turn budget): ${goal.title}\\n` +\n \"I'll keep working until the goal is done, you pause/archive it, or the budget is exhausted.\\n\" +\n 'Controls: /goal status · /goal pause · /goal resume · /goal clear · /subgoal',\n success: true,\n };\n },\n};\n\nexport function registerGoalCommand(): void {\n commandRegistry.register(goalCommand);\n}\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function registerReviewCommand(): void;
@@ -0,0 +1,167 @@
1
+ import { effectiveWorkspacePathForSession } from "../../session/session-workspace.js";
2
+ import { getProjectForSession } from "../../projects/workspace.js";
3
+ import { commandRegistry } from "../registry.js";
4
+ import { buildReviewDiffBundle, parseReviewTargetArgs, resolveGitRoot } from "../../review/review-git.js";
5
+ import { formatReviewMarkdown } from "../../review/review-types.js";
6
+ //#region src/chat-commands/builtins/review.ts
7
+ const MAX_DIFF_CHARS = 6e4;
8
+ function truncateForPrompt(text) {
9
+ if (text.length <= MAX_DIFF_CHARS) return {
10
+ text,
11
+ truncated: false
12
+ };
13
+ return {
14
+ text: text.slice(0, MAX_DIFF_CHARS) + "\n\n[diff truncated]",
15
+ truncated: true
16
+ };
17
+ }
18
+ function extractJsonObject(raw) {
19
+ const text = (raw.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1] ?? raw).trim();
20
+ const start = text.indexOf("{");
21
+ const end = text.lastIndexOf("}");
22
+ if (start < 0 || end <= start) throw new Error("review response did not contain JSON");
23
+ return JSON.parse(text.slice(start, end + 1));
24
+ }
25
+ function priorityFrom(raw) {
26
+ const n = typeof raw === "number" ? raw : Number.parseInt(String(raw ?? ""), 10);
27
+ if (n === 0 || n === 1 || n === 2 || n === 3) return n;
28
+ return 2;
29
+ }
30
+ function numberFrom(raw) {
31
+ return typeof raw === "number" && Number.isFinite(raw) ? raw : void 0;
32
+ }
33
+ function stringFrom(raw) {
34
+ return typeof raw === "string" ? raw.trim() : "";
35
+ }
36
+ function parseReviewJson(raw, target) {
37
+ const parsed = extractJsonObject(raw);
38
+ const rec = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
39
+ const findings = (Array.isArray(rec.findings) ? rec.findings : []).map((item) => {
40
+ const f = item && typeof item === "object" && !Array.isArray(item) ? item : {};
41
+ const loc = f.code_location && typeof f.code_location === "object" ? f.code_location : {};
42
+ const range = loc.line_range && typeof loc.line_range === "object" ? loc.line_range : {};
43
+ const title = stringFrom(f.title);
44
+ const body = stringFrom(f.body);
45
+ if (!title && !body) return void 0;
46
+ const finding = {
47
+ title: title || body.slice(0, 80),
48
+ body,
49
+ priority: priorityFrom(f.priority)
50
+ };
51
+ const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);
52
+ const filePath = stringFrom(loc.file_path ?? f.filePath);
53
+ const lineStart = numberFrom(range.start ?? f.lineStart);
54
+ const lineEnd = numberFrom(range.end ?? f.lineEnd);
55
+ if (confidenceScore !== void 0) finding.confidenceScore = confidenceScore;
56
+ if (filePath) finding.filePath = filePath;
57
+ if (lineStart !== void 0) finding.lineStart = lineStart;
58
+ if (lineEnd !== void 0) finding.lineEnd = lineEnd;
59
+ return finding;
60
+ }).filter((item) => Boolean(item));
61
+ const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);
62
+ const overallCorrectness = correctness === "patch is correct" || correctness === "patch is incorrect" ? correctness : "unknown";
63
+ return {
64
+ type: "review",
65
+ target,
66
+ summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? "" : "s"}`,
67
+ findings,
68
+ overallCorrectness,
69
+ overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),
70
+ overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),
71
+ generatedAt: Date.now(),
72
+ source: "model"
73
+ };
74
+ }
75
+ function buildReviewPrompt(params) {
76
+ return [
77
+ "You are a senior code reviewer. Review the provided git diff for correctness bugs only.",
78
+ "Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.",
79
+ "Do not mention style, broad refactors, praise, or speculative improvements.",
80
+ "Return strict JSON only with this shape:",
81
+ "{\"findings\":[{\"title\":\"...\",\"body\":\"...\",\"priority\":1,\"confidence_score\":0.9,\"code_location\":{\"file_path\":\"path\",\"line_range\":{\"start\":12,\"end\":12}}}],\"overall_correctness\":\"patch is correct\",\"overall_explanation\":\"...\",\"overall_confidence_score\":0.8,\"summary\":\"...\"}",
82
+ "Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.",
83
+ params.instructions ? `Extra reviewer instructions: ${params.instructions}` : "",
84
+ `Target: ${params.target}`,
85
+ params.truncated ? "The diff was truncated; only report findings supported by visible lines." : "",
86
+ "Git status:",
87
+ params.status || "(clean)",
88
+ "Diff stat:",
89
+ params.stat || "(none)",
90
+ "Diff:",
91
+ params.diff || "(none)"
92
+ ].filter(Boolean).join("\n\n");
93
+ }
94
+ async function resolveWorkspace(ctx) {
95
+ const sessionConfigStore = ctx.getSessionConfigStore?.();
96
+ const sessionConfig = sessionConfigStore ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null) : null;
97
+ return effectiveWorkspacePathForSession(ctx.config, ctx.sessionKey, sessionConfig, getProjectForSession(ctx.sessionKey));
98
+ }
99
+ async function buildReview(ctx, args) {
100
+ const cwd = await resolveGitRoot(await resolveWorkspace(ctx));
101
+ const reviewTarget = parseReviewTargetArgs(args);
102
+ const bundle = await buildReviewDiffBundle(cwd, reviewTarget);
103
+ const { text: diff, truncated } = truncateForPrompt(bundle.diff);
104
+ const target = bundle.targetLabel;
105
+ const instructions = reviewTarget.instructions ?? "";
106
+ if (!bundle.status.trim() && !bundle.diff.trim()) return {
107
+ type: "review",
108
+ target,
109
+ summary: "Working tree is clean.",
110
+ findings: [],
111
+ overallCorrectness: "patch is correct",
112
+ overallExplanation: "No uncommitted changes were found to review.",
113
+ generatedAt: Date.now(),
114
+ source: "local"
115
+ };
116
+ const prompt = buildReviewPrompt({
117
+ target,
118
+ status: bundle.status,
119
+ stat: bundle.stat,
120
+ diff,
121
+ truncated,
122
+ instructions
123
+ });
124
+ const answer = await ctx.btwQuery?.(prompt);
125
+ if (answer?.text && !answer.error) try {
126
+ return parseReviewJson(answer.text, target);
127
+ } catch {}
128
+ return {
129
+ type: "review",
130
+ target,
131
+ summary: "Review model was unavailable; returned a local diff summary.",
132
+ findings: [],
133
+ overallCorrectness: "unknown",
134
+ overallExplanation: [answer?.error ? `Reviewer model error: ${answer.error}` : "Reviewer model output could not be parsed.", bundle.stat.trim() ? `Changed files:\n${bundle.stat.trim()}` : "No textual diff stat was available."].join("\n\n"),
135
+ generatedAt: Date.now(),
136
+ source: "local"
137
+ };
138
+ }
139
+ const reviewCommand = {
140
+ id: "coding.review",
141
+ name: "review",
142
+ description: "Review current workspace changes for correctness issues",
143
+ category: "tool",
144
+ scope: [
145
+ "global",
146
+ "private",
147
+ "group"
148
+ ],
149
+ acceptsArgs: true,
150
+ examples: ["/review", "/review focus on auth and persistence"],
151
+ handler: async (ctx, args) => {
152
+ await ctx.setTyping(true);
153
+ const review = await buildReview(ctx, args);
154
+ return {
155
+ content: formatReviewMarkdown(review),
156
+ success: true,
157
+ metadata: { review }
158
+ };
159
+ }
160
+ };
161
+ function registerReviewCommand() {
162
+ commandRegistry.register(reviewCommand);
163
+ }
164
+ //#endregion
165
+ export { registerReviewCommand };
166
+
167
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","names":[],"sources":["../../../../src/chat-commands/builtins/review.ts"],"sourcesContent":["import type { CommandDefinition, CommandContext } from '../types.js';\nimport { commandRegistry } from '../registry.js';\nimport { effectiveWorkspacePathForSession } from '../../session/session-workspace.js';\nimport { getProjectForSession } from '../../projects/workspace.js';\nimport {\n buildReviewDiffBundle,\n parseReviewTargetArgs,\n resolveGitRoot,\n} from '../../review/review-git.js';\nimport {\n formatReviewMarkdown,\n type ReviewFinding,\n type ReviewOutput,\n type ReviewPriority,\n} from '../../review/review-types.js';\n\nconst MAX_DIFF_CHARS = 60_000;\n\nfunction truncateForPrompt(text: string): { text: string; truncated: boolean } {\n if (text.length <= MAX_DIFF_CHARS) return { text, truncated: false };\n return {\n text: text.slice(0, MAX_DIFF_CHARS) + '\\n\\n[diff truncated]',\n truncated: true,\n };\n}\n\nfunction extractJsonObject(raw: string): unknown {\n const fenced = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n const text = (fenced?.[1] ?? raw).trim();\n const start = text.indexOf('{');\n const end = text.lastIndexOf('}');\n if (start < 0 || end <= start) throw new Error('review response did not contain JSON');\n return JSON.parse(text.slice(start, end + 1));\n}\n\nfunction priorityFrom(raw: unknown): ReviewPriority {\n const n = typeof raw === 'number' ? raw : Number.parseInt(String(raw ?? ''), 10);\n if (n === 0 || n === 1 || n === 2 || n === 3) return n;\n return 2;\n}\n\nfunction numberFrom(raw: unknown): number | undefined {\n return typeof raw === 'number' && Number.isFinite(raw) ? raw : undefined;\n}\n\nfunction stringFrom(raw: unknown): string {\n return typeof raw === 'string' ? raw.trim() : '';\n}\n\nfunction parseReviewJson(raw: string, target: string): ReviewOutput {\n const parsed = extractJsonObject(raw);\n const rec = parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? parsed as Record<string, unknown>\n : {};\n const rawFindings = Array.isArray(rec.findings) ? rec.findings : [];\n const findings: ReviewFinding[] = rawFindings\n .map((item) => {\n const f = item && typeof item === 'object' && !Array.isArray(item)\n ? item as Record<string, unknown>\n : {};\n const loc = f.code_location && typeof f.code_location === 'object'\n ? f.code_location as Record<string, unknown>\n : {};\n const range = loc.line_range && typeof loc.line_range === 'object'\n ? loc.line_range as Record<string, unknown>\n : {};\n const title = stringFrom(f.title);\n const body = stringFrom(f.body);\n if (!title && !body) return undefined;\n const finding: ReviewFinding = {\n title: title || body.slice(0, 80),\n body,\n priority: priorityFrom(f.priority),\n };\n const confidenceScore = numberFrom(f.confidence_score ?? f.confidenceScore);\n const filePath = stringFrom(loc.file_path ?? f.filePath);\n const lineStart = numberFrom(range.start ?? f.lineStart);\n const lineEnd = numberFrom(range.end ?? f.lineEnd);\n if (confidenceScore !== undefined) finding.confidenceScore = confidenceScore;\n if (filePath) finding.filePath = filePath;\n if (lineStart !== undefined) finding.lineStart = lineStart;\n if (lineEnd !== undefined) finding.lineEnd = lineEnd;\n return finding;\n })\n .filter((item): item is ReviewFinding => Boolean(item));\n\n const correctness = stringFrom(rec.overall_correctness ?? rec.overallCorrectness);\n const overallCorrectness =\n correctness === 'patch is correct' || correctness === 'patch is incorrect'\n ? correctness\n : 'unknown';\n return {\n type: 'review',\n target,\n summary: stringFrom(rec.summary) || `${findings.length} finding${findings.length === 1 ? '' : 's'}`,\n findings,\n overallCorrectness,\n overallExplanation: stringFrom(rec.overall_explanation ?? rec.overallExplanation),\n overallConfidenceScore: numberFrom(rec.overall_confidence_score ?? rec.overallConfidenceScore),\n generatedAt: Date.now(),\n source: 'model',\n };\n}\n\nfunction buildReviewPrompt(params: {\n target: string;\n status: string;\n stat: string;\n diff: string;\n truncated: boolean;\n instructions: string;\n}): string {\n return [\n 'You are a senior code reviewer. Review the provided git diff for correctness bugs only.',\n 'Prioritize concrete regressions, broken behavior, missing required tests for changed behavior, data loss, security issues, and runtime/type errors.',\n 'Do not mention style, broad refactors, praise, or speculative improvements.',\n 'Return strict JSON only with this shape:',\n '{\"findings\":[{\"title\":\"...\",\"body\":\"...\",\"priority\":1,\"confidence_score\":0.9,\"code_location\":{\"file_path\":\"path\",\"line_range\":{\"start\":12,\"end\":12}}}],\"overall_correctness\":\"patch is correct\",\"overall_explanation\":\"...\",\"overall_confidence_score\":0.8,\"summary\":\"...\"}',\n 'Use priority 0 for release-blocking, 1 for high, 2 for medium, 3 for low.',\n params.instructions ? `Extra reviewer instructions: ${params.instructions}` : '',\n `Target: ${params.target}`,\n params.truncated ? 'The diff was truncated; only report findings supported by visible lines.' : '',\n 'Git status:',\n params.status || '(clean)',\n 'Diff stat:',\n params.stat || '(none)',\n 'Diff:',\n params.diff || '(none)',\n ].filter(Boolean).join('\\n\\n');\n}\n\nasync function resolveWorkspace(ctx: CommandContext): Promise<string> {\n const sessionConfigStore = ctx.getSessionConfigStore?.();\n const sessionConfig = sessionConfigStore\n ? await sessionConfigStore.get(ctx.sessionKey).catch(() => null)\n : null;\n return effectiveWorkspacePathForSession(\n ctx.config,\n ctx.sessionKey,\n sessionConfig,\n getProjectForSession(ctx.sessionKey),\n );\n}\n\nasync function buildReview(ctx: CommandContext, args: string): Promise<ReviewOutput> {\n const workspace = await resolveWorkspace(ctx);\n const cwd = await resolveGitRoot(workspace);\n const reviewTarget = parseReviewTargetArgs(args);\n const bundle = await buildReviewDiffBundle(cwd, reviewTarget);\n const { text: diff, truncated } = truncateForPrompt(bundle.diff);\n const target = bundle.targetLabel;\n const instructions = reviewTarget.instructions ?? '';\n\n if (!bundle.status.trim() && !bundle.diff.trim()) {\n return {\n type: 'review',\n target,\n summary: 'Working tree is clean.',\n findings: [],\n overallCorrectness: 'patch is correct',\n overallExplanation: 'No uncommitted changes were found to review.',\n generatedAt: Date.now(),\n source: 'local',\n };\n }\n\n const prompt = buildReviewPrompt({\n target,\n status: bundle.status,\n stat: bundle.stat,\n diff,\n truncated,\n instructions,\n });\n const answer = await ctx.btwQuery?.(prompt);\n if (answer?.text && !answer.error) {\n try {\n return parseReviewJson(answer.text, target);\n } catch {\n // Fall through to a deterministic local summary when model output is not parseable.\n }\n }\n\n return {\n type: 'review',\n target,\n summary: 'Review model was unavailable; returned a local diff summary.',\n findings: [],\n overallCorrectness: 'unknown',\n overallExplanation: [\n answer?.error ? `Reviewer model error: ${answer.error}` : 'Reviewer model output could not be parsed.',\n bundle.stat.trim() ? `Changed files:\\n${bundle.stat.trim()}` : 'No textual diff stat was available.',\n ].join('\\n\\n'),\n generatedAt: Date.now(),\n source: 'local',\n };\n}\n\nconst reviewCommand: CommandDefinition = {\n id: 'coding.review',\n name: 'review',\n description: 'Review current workspace changes for correctness issues',\n category: 'tool',\n scope: ['global', 'private', 'group'],\n acceptsArgs: true,\n examples: ['/review', '/review focus on auth and persistence'],\n handler: async (ctx: CommandContext, args: string) => {\n await ctx.setTyping(true);\n const review = await buildReview(ctx, args);\n return {\n content: formatReviewMarkdown(review),\n success: true,\n metadata: { review },\n };\n },\n};\n\nexport function registerReviewCommand(): void {\n commandRegistry.register(reviewCommand);\n}\n"],"mappings":"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"}
@@ -20,6 +20,7 @@ export { registerContextCommands } from './builtins/context.js';
20
20
  export { registerGoalCommand } from './builtins/goal.js';
21
21
  export { registerSubgoalCommand } from './builtins/subgoal.js';
22
22
  export { registerWorkflowCommands } from './builtins/workflow.js';
23
+ export { registerReviewCommand } from './builtins/review.js';
23
24
  export { registerAgentEditCommand } from './agent-edit.js';
24
25
  /**
25
26
  * Initialize the command system with all built-in commands
@@ -11,6 +11,7 @@ import { registerContextCommands } from "./builtins/context.js";
11
11
  import { registerGoalCommand } from "./builtins/goal.js";
12
12
  import { registerSubgoalCommand } from "./builtins/subgoal.js";
13
13
  import { registerWorkflowCommands } from "./builtins/workflow.js";
14
+ import { registerReviewCommand } from "./builtins/review.js";
14
15
  import { registerAgentEditCommand } from "./agent-edit.js";
15
16
  import { CommandContextImpl, createCommandContext } from "./context.js";
16
17
  //#region src/chat-commands/index.ts
@@ -34,9 +35,10 @@ function initializeCommands() {
34
35
  registerGoalCommand();
35
36
  registerSubgoalCommand();
36
37
  registerWorkflowCommands();
38
+ registerReviewCommand();
37
39
  registerAgentEditCommand();
38
40
  }
39
41
  //#endregion
40
- export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getSessionDisplayName, initializeCommands, normalizeTelegramCommandName, parseSlashCommand, registerAgentEditCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands, registerWorkflowCommands };
42
+ export { CommandContextImpl, CommandRegistry, commandRegistry, createCommandContext, generateSessionKey, getSessionDisplayName, initializeCommands, normalizeTelegramCommandName, parseSlashCommand, registerAgentEditCommand, registerConfigCommand, registerContextCommands, registerGoalCommand, registerModelCommands, registerReviewCommand, registerSessionCommands, registerSubgoalCommand, registerSystemCommands, registerTTSCommands, registerThinkingCommands, registerWorkflowCommands };
41
43
 
42
44
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\nimport { registerWorkflowCommands } from './builtins/workflow.js';\nimport { registerAgentEditCommand } from './agent-edit.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session display helpers\nexport { generateSessionKey, getSessionDisplayName, type SessionKeyContext } from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\nexport { registerWorkflowCommands } from './builtins/workflow.js';\nexport { registerAgentEditCommand } from './agent-edit.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n registerWorkflowCommands();\n registerAgentEditCommand();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8EA,SAAgB,qBAA2B;AACzC,0BAAyB;AACzB,wBAAuB;AACvB,yBAAwB;AACxB,wBAAuB;AACvB,0BAAyB;AACzB,sBAAqB;AACrB,2BAA0B;AAC1B,sBAAqB;AACrB,yBAAwB;AACxB,2BAA0B;AAC1B,2BAA0B"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/chat-commands/index.ts"],"sourcesContent":["/**\n * Unified Command System\n *\n * Provides a platform-agnostic command system that works across\n * Telegram, Feishu, Web UI, CLI, and other channel surfaces.\n */\n\n// Built-in Commands (import first to avoid circular deps)\nimport { registerSessionCommands } from './builtins/session.js';\nimport { registerModelCommands } from './builtins/model.js';\nimport { registerSystemCommands } from './builtins/system.js';\nimport { registerTTSCommands } from './builtins/tts.js';\nimport { registerThinkingCommands } from './builtins/thinking.js';\nimport { registerConfigCommand } from './builtins/config.js';\nimport { registerContextCommands } from './builtins/context.js';\nimport { registerGoalCommand } from './builtins/goal.js';\nimport { registerSubgoalCommand } from './builtins/subgoal.js';\nimport { registerWorkflowCommands } from './builtins/workflow.js';\nimport { registerReviewCommand } from './builtins/review.js';\nimport { registerAgentEditCommand } from './agent-edit.js';\n\n// Types\nexport type {\n MessageSource,\n UnifiedMessage,\n PlatformMetadata,\n MessageAttachment,\n CommandDefinition,\n CommandCategory,\n CommandScope,\n CommandHandler,\n CommandResult,\n CommandContext,\n ReplyOptions,\n UIComponent,\n ButtonGroup,\n SelectMenu,\n ModelPicker,\n UsageDisplay,\n SessionList,\n TextInput,\n ProviderInfo,\n ModelInfo,\n UsageStats,\n SessionInfo,\n PlatformFeature,\n ChannelAdapter,\n ReplyPayload,\n} from './types.js';\n\n// Session display helpers\nexport { generateSessionKey, getSessionDisplayName, type SessionKeyContext } from './session-key.js';\n\n// Command parsing helpers\nexport { normalizeTelegramCommandName, parseSlashCommand } from './command-parse.js';\n\n// Registry\nexport { CommandRegistry, commandRegistry } from './registry.js';\nexport type { CommandRegistry as CommandRegistryType } from './types.js';\n\n// Context\nexport { CommandContextImpl, createCommandContext } from './context.js';\n\n// Built-in Commands\nexport { registerSessionCommands } from './builtins/session.js';\nexport { registerModelCommands } from './builtins/model.js';\nexport { registerSystemCommands } from './builtins/system.js';\nexport { registerTTSCommands } from './builtins/tts.js';\nexport { registerThinkingCommands } from './builtins/thinking.js';\nexport { registerConfigCommand } from './builtins/config.js';\nexport { registerContextCommands } from './builtins/context.js';\nexport { registerGoalCommand } from './builtins/goal.js';\nexport { registerSubgoalCommand } from './builtins/subgoal.js';\nexport { registerWorkflowCommands } from './builtins/workflow.js';\nexport { registerReviewCommand } from './builtins/review.js';\nexport { registerAgentEditCommand } from './agent-edit.js';\n\n/**\n * Initialize the command system with all built-in commands\n */\nexport function initializeCommands(): void {\n registerSessionCommands();\n registerModelCommands();\n registerSystemCommands();\n registerConfigCommand();\n registerContextCommands();\n registerTTSCommands();\n registerThinkingCommands();\n registerGoalCommand();\n registerSubgoalCommand();\n registerWorkflowCommands();\n registerReviewCommand();\n registerAgentEditCommand();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgFA,SAAgB,qBAA2B;AACzC,0BAAyB;AACzB,wBAAuB;AACvB,yBAAwB;AACxB,wBAAuB;AACvB,0BAAyB;AACzB,sBAAqB;AACrB,2BAA0B;AAC1B,sBAAqB;AACrB,yBAAwB;AACxB,2BAA0B;AAC1B,wBAAuB;AACvB,2BAA0B"}
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v20).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v21).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveConfigPath } from "../../../config/paths.js";
2
2
  import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
- import { isRestartEnabled } from "../../../config/commands.flags.js";
5
4
  import { resolveGatewayService } from "../../../daemon/service.js";
5
+ import { isRestartEnabled } from "../../../config/commands.flags.js";
6
6
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
7
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
@@ -1,6 +1,6 @@
1
+ import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
1
2
  import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
2
3
  import "../agent-manifest/index.js";
3
- import { init_agent_scope, normalizeAgentId, resolveAgentWorkspaceDir } from "../agent/agent-scope.js";
4
4
  import { init_session_key, parseSessionKey } from "../routing/session-key.js";
5
5
  import { agentExists, getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
6
6
  //#region src/config/agent-profile.ts
@@ -2,5 +2,5 @@
2
2
  * Built-in agent tool `name` values for gateway admin UI (disable toggles).
3
3
  * Extension tools are not listed; users can still add arbitrary strings in config.
4
4
  */
5
- export declare const GATEWAY_BUILTIN_TOOL_IDS: readonly ["read_file", "write_file", "edit_file", "list_dir", "grep", "find", "shell", "session_status", "dreaming", "tool_manual", "clarify", "todo", "skills_list", "skill_view", "skill_manage", "web_search", "web_fetch", "web_extract", "send_message", "send_media", "read_media", "create_share", "text_to_speech", "memory_search", "memory_get", "curated_memory", "session_search", "automation", "workflow", "delegate_task", "execute_code", "image", "image_generate", "browser_use", "extensions", "bundle-mcp"];
5
+ export declare const GATEWAY_BUILTIN_TOOL_IDS: readonly ["read_file", "write_file", "apply_patch", "list_dir", "grep", "find", "exec_command", "update_plan", "session_status", "dreaming", "tool_manual", "clarify", "todo", "skills_list", "skill_view", "skill_manage", "web_search", "web_fetch", "web_extract", "send_message", "send_media", "read_media", "create_share", "text_to_speech", "memory_search", "memory_get", "curated_memory", "session_search", "automation", "workflow", "delegate_task", "execute_code", "image", "image_generate", "browser_use", "extensions", "bundle-mcp"];
6
6
  export type GatewayBuiltinToolId = (typeof GATEWAY_BUILTIN_TOOL_IDS)[number];
@@ -6,11 +6,12 @@
6
6
  const GATEWAY_BUILTIN_TOOL_IDS = [
7
7
  "read_file",
8
8
  "write_file",
9
- "edit_file",
9
+ "apply_patch",
10
10
  "list_dir",
11
11
  "grep",
12
12
  "find",
13
- "shell",
13
+ "exec_command",
14
+ "update_plan",
14
15
  "session_status",
15
16
  "dreaming",
16
17
  "tool_manual",
@@ -1 +1 @@
1
- {"version":3,"file":"agent-builtin-tools.js","names":[],"sources":["../../../src/gateway/agent-builtin-tools.ts"],"sourcesContent":["/**\n * Built-in agent tool `name` values for gateway admin UI (disable toggles).\n * Extension tools are not listed; users can still add arbitrary strings in config.\n */\nexport const GATEWAY_BUILTIN_TOOL_IDS = [\n 'read_file',\n 'write_file',\n 'edit_file',\n 'list_dir',\n 'grep',\n 'find',\n 'shell',\n 'session_status',\n 'dreaming',\n 'tool_manual',\n 'clarify',\n 'todo',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'send_message',\n 'send_media',\n 'read_media',\n 'create_share',\n 'text_to_speech',\n 'memory_search',\n 'memory_get',\n 'curated_memory',\n 'session_search',\n 'automation',\n 'workflow',\n 'delegate_task',\n 'execute_code',\n 'image',\n 'image_generate',\n 'browser_use',\n 'extensions',\n 'bundle-mcp',\n] as const;\n\nexport type GatewayBuiltinToolId = (typeof GATEWAY_BUILTIN_TOOL_IDS)[number];\n"],"mappings":";;;;;AAIA,MAAa,2BAA2B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
1
+ {"version":3,"file":"agent-builtin-tools.js","names":[],"sources":["../../../src/gateway/agent-builtin-tools.ts"],"sourcesContent":["/**\n * Built-in agent tool `name` values for gateway admin UI (disable toggles).\n * Extension tools are not listed; users can still add arbitrary strings in config.\n */\nexport const GATEWAY_BUILTIN_TOOL_IDS = [\n 'read_file',\n 'write_file',\n 'apply_patch',\n 'list_dir',\n 'grep',\n 'find',\n 'exec_command',\n 'update_plan',\n 'session_status',\n 'dreaming',\n 'tool_manual',\n 'clarify',\n 'todo',\n 'skills_list',\n 'skill_view',\n 'skill_manage',\n 'web_search',\n 'web_fetch',\n 'web_extract',\n 'send_message',\n 'send_media',\n 'read_media',\n 'create_share',\n 'text_to_speech',\n 'memory_search',\n 'memory_get',\n 'curated_memory',\n 'session_search',\n 'automation',\n 'workflow',\n 'delegate_task',\n 'execute_code',\n 'image',\n 'image_generate',\n 'browser_use',\n 'extensions',\n 'bundle-mcp',\n] as const;\n\nexport type GatewayBuiltinToolId = (typeof GATEWAY_BUILTIN_TOOL_IDS)[number];\n"],"mappings":";;;;;AAIA,MAAa,2BAA2B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD"}
@@ -1,5 +1,5 @@
1
- import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
2
1
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentDir, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId, resolveUserPath, validateAgentIdForNewAgent } from "../agent/agent-scope.js";
2
+ import { resolveEffectiveAgentManifest } from "../agent-manifest/resolver.js";
3
3
  import { resolveEffectiveAgentProfile } from "../config/agent-profile.js";
4
4
  import { WORKSPACE_FILES, init_paths, resolveUserProfilePath } from "../config/paths.js";
5
5
  import { AGENT_PROFILE_MARKDOWN_SYSTEM_FILES, REQUIRED_AGENT_PROFILE_MARKDOWN_FILE_SET } from "../agent/context/workspace.js";
@@ -15,7 +15,12 @@ export declare class ChatStreamMapper {
15
15
  private currentAssistantMessageId;
16
16
  private lastAssistantMessageId;
17
17
  private currentAssistantText;
18
+ private currentAssistantReviewEmitted;
18
19
  private toolCallToMessageId;
20
+ private turnDiffs;
21
+ private turnDiffFiles;
22
+ private turnDiffAdded;
23
+ private turnDiffRemoved;
19
24
  private started;
20
25
  private ended;
21
26
  constructor(opts: ChatStreamMapperOptions);
@@ -32,4 +37,5 @@ export declare class ChatStreamMapper {
32
37
  private ensureAssistantMessageId;
33
38
  private nextAssistantMessageId;
34
39
  private make;
40
+ private recordPatchDiff;
35
41
  }