@phuetz/code-buddy 2.0.0 → 2.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/README.fr.md +56 -0
  2. package/README.md +74 -16
  3. package/codebuddy-runtime.json +5 -5
  4. package/dist/agent/codebuddy-agent.d.ts +18 -0
  5. package/dist/agent/codebuddy-agent.js +45 -8
  6. package/dist/agent/execution/agent-executor.d.ts +0 -9
  7. package/dist/agent/execution/agent-executor.js +176 -12
  8. package/dist/agent/execution/context-pipeline.d.ts +9 -0
  9. package/dist/agent/execution/context-pipeline.js +64 -2
  10. package/dist/agent/execution/tool-loop-guard.d.ts +76 -0
  11. package/dist/agent/execution/tool-loop-guard.js +165 -0
  12. package/dist/agent/execution/tool-selection-strategy.d.ts +7 -0
  13. package/dist/agent/execution/tool-selection-strategy.js +32 -2
  14. package/dist/agent/facades/session-facade.d.ts +0 -6
  15. package/dist/agent/facades/session-facade.js +0 -45
  16. package/dist/agent/hermes-claw-migrate.d.ts +0 -21
  17. package/dist/agent/hermes-claw-migrate.js +9 -4
  18. package/dist/agent/hermes-protocol-gateways.js +8 -1
  19. package/dist/agent/repo-profiler.js +17 -4
  20. package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
  21. package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
  22. package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
  23. package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
  24. package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
  25. package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
  26. package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
  27. package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
  28. package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
  29. package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
  30. package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
  31. package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
  32. package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
  33. package/dist/agent/self-improvement/proposal-store.js +79 -17
  34. package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
  35. package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
  36. package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
  37. package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
  38. package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
  39. package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
  40. package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
  41. package/dist/agent/self-improvement/skill-engine.js +385 -13
  42. package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
  43. package/dist/agent/self-improvement/skill-gate.js +17 -2
  44. package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
  45. package/dist/agent/self-improvement/skill-mutator.js +51 -15
  46. package/dist/agent/self-improvement/skill-types.d.ts +2 -1
  47. package/dist/agent/self-improvement/types.d.ts +11 -0
  48. package/dist/agent/tool-handler.d.ts +1 -1
  49. package/dist/agent/tool-handler.js +28 -9
  50. package/dist/auth/profile-manager.js +1 -1
  51. package/dist/channels/companion-channel-turn.d.ts +53 -4
  52. package/dist/channels/companion-channel-turn.js +218 -16
  53. package/dist/channels/slash-parity.d.ts +4 -6
  54. package/dist/channels/slash-parity.js +9 -44
  55. package/dist/cli/session-commands.d.ts +9 -0
  56. package/dist/cli/session-commands.js +45 -5
  57. package/dist/cli/session-picker.d.ts +43 -0
  58. package/dist/cli/session-picker.js +128 -0
  59. package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
  60. package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
  61. package/dist/codebuddy/fleet-tool-defs.d.ts +2 -0
  62. package/dist/codebuddy/fleet-tool-defs.js +55 -0
  63. package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
  64. package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
  65. package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
  66. package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
  67. package/dist/codebuddy/providers/provider-openai-compat.d.ts +7 -0
  68. package/dist/codebuddy/providers/provider-openai-compat.js +29 -1
  69. package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
  70. package/dist/codebuddy/ragchat-tool-defs.js +19 -0
  71. package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
  72. package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
  73. package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
  74. package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
  75. package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
  76. package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
  77. package/dist/codebuddy/tools.d.ts +0 -6
  78. package/dist/codebuddy/tools.js +25 -3
  79. package/dist/commands/cli/daemon-commands.js +3 -1
  80. package/dist/commands/cli/evolve-command.js +21 -5
  81. package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
  82. package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
  83. package/dist/commands/cli/fleet-commands.js +29 -0
  84. package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
  85. package/dist/commands/cli/fleet-mission-commands.js +72 -0
  86. package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
  87. package/dist/commands/cli/fleet-rooms-commands.js +289 -0
  88. package/dist/commands/cli/tools-commands.js +2 -1
  89. package/dist/commands/cli/triage-command.d.ts +8 -0
  90. package/dist/commands/cli/triage-command.js +72 -0
  91. package/dist/commands/cli/utility-commands.js +25 -1
  92. package/dist/commands/client-dispatcher.d.ts +7 -0
  93. package/dist/commands/client-dispatcher.js +73 -21
  94. package/dist/commands/cron-cli/index.d.ts +3 -1
  95. package/dist/commands/cron-cli/index.js +25 -0
  96. package/dist/commands/device-auth.d.ts +10 -0
  97. package/dist/commands/device-auth.js +91 -0
  98. package/dist/commands/enhanced-command-handler.d.ts +9 -0
  99. package/dist/commands/enhanced-command-handler.js +28 -6
  100. package/dist/commands/handlers/agent-handlers.d.ts +1 -1
  101. package/dist/commands/handlers/agent-handlers.js +4 -4
  102. package/dist/commands/handlers/channel-handlers.js +53 -2
  103. package/dist/commands/handlers/export-handlers.d.ts +3 -2
  104. package/dist/commands/handlers/export-handlers.js +55 -28
  105. package/dist/commands/handlers/extra-handlers.js +5 -1
  106. package/dist/commands/handlers/grill-me-handler.js +26 -18
  107. package/dist/commands/handlers/memory-handlers.d.ts +6 -2
  108. package/dist/commands/handlers/memory-handlers.js +35 -15
  109. package/dist/commands/handlers/missing-handlers.d.ts +2 -2
  110. package/dist/commands/handlers/missing-handlers.js +12 -4
  111. package/dist/commands/handlers/resources-handler.d.ts +12 -0
  112. package/dist/commands/handlers/resources-handler.js +52 -0
  113. package/dist/commands/handlers/starter-handlers.d.ts +1 -1
  114. package/dist/commands/handlers/starter-handlers.js +32 -2
  115. package/dist/commands/handlers/switch-handler.d.ts +1 -1
  116. package/dist/commands/handlers/switch-handler.js +15 -0
  117. package/dist/commands/handlers/test-handlers.js +4 -86
  118. package/dist/commands/handlers/ui-handlers.js +11 -5
  119. package/dist/commands/login-chatgpt.d.ts +8 -0
  120. package/dist/commands/login-chatgpt.js +17 -0
  121. package/dist/commands/mcp-import.d.ts +11 -0
  122. package/dist/commands/mcp-import.js +67 -0
  123. package/dist/commands/mcp-invoke.d.ts +2 -0
  124. package/dist/commands/mcp-invoke.js +68 -0
  125. package/dist/commands/mcp.d.ts +13 -0
  126. package/dist/commands/mcp.js +66 -21
  127. package/dist/commands/pipeline.d.ts +7 -1
  128. package/dist/commands/pipeline.js +104 -7
  129. package/dist/commands/resources.d.ts +2 -0
  130. package/dist/commands/resources.js +64 -0
  131. package/dist/commands/skills-cli/index.js +35 -12
  132. package/dist/commands/slash/builtin-commands.js +16 -3
  133. package/dist/commands/slash/index.d.ts +3 -1
  134. package/dist/commands/slash/index.js +2 -0
  135. package/dist/commands/slash/surfaces.d.ts +53 -0
  136. package/dist/commands/slash/surfaces.js +177 -0
  137. package/dist/commands/slash/types.d.ts +17 -0
  138. package/dist/commands/try.d.ts +1 -1
  139. package/dist/commands/try.js +1 -1
  140. package/dist/companion/companion-identity.d.ts +43 -0
  141. package/dist/companion/companion-identity.js +136 -0
  142. package/dist/companion/companion-toolset.d.ts +66 -0
  143. package/dist/companion/companion-toolset.js +368 -0
  144. package/dist/companion/companion-turn.d.ts +10 -2
  145. package/dist/companion/companion-turn.js +38 -1
  146. package/dist/config/code-exec-policy.d.ts +25 -0
  147. package/dist/config/code-exec-policy.js +39 -0
  148. package/dist/config/model-tools.d.ts +9 -0
  149. package/dist/config/model-tools.js +103 -0
  150. package/dist/context/context-manager-v2.js +2 -2
  151. package/dist/context/lm-resizer-compressor.js +3 -2
  152. package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
  153. package/dist/context/lm-resizer-diagnostics.js +30 -0
  154. package/dist/context/tool-output-masking.js +3 -4
  155. package/dist/curator/curator.d.ts +6 -0
  156. package/dist/curator/curator.js +53 -3
  157. package/dist/daemon/cron-agent-bridge.d.ts +6 -0
  158. package/dist/daemon/cron-agent-bridge.js +31 -4
  159. package/dist/doctor/index.d.ts +11 -2
  160. package/dist/doctor/index.js +84 -21
  161. package/dist/doctor/integrations.d.ts +197 -0
  162. package/dist/doctor/integrations.js +241 -0
  163. package/dist/doctor/triage.d.ts +108 -0
  164. package/dist/doctor/triage.js +304 -0
  165. package/dist/errors/crash-handler.js +2 -0
  166. package/dist/fleet/collaboration.d.ts +44 -0
  167. package/dist/fleet/collaboration.js +170 -0
  168. package/dist/fleet/fleet-listener.d.ts +1 -0
  169. package/dist/fleet/fleet-listener.js +87 -46
  170. package/dist/fleet/fleet-registry.d.ts +2 -0
  171. package/dist/fleet/resource-catalog.d.ts +245 -0
  172. package/dist/fleet/resource-catalog.js +211 -0
  173. package/dist/fleet/rooms/room-access.d.ts +138 -0
  174. package/dist/fleet/rooms/room-access.js +196 -0
  175. package/dist/fleet/rooms/room-client.d.ts +158 -0
  176. package/dist/fleet/rooms/room-client.js +685 -0
  177. package/dist/fleet/rooms/room-event.d.ts +139 -0
  178. package/dist/fleet/rooms/room-event.js +330 -0
  179. package/dist/fleet/rooms/room-filter.d.ts +48 -0
  180. package/dist/fleet/rooms/room-filter.js +152 -0
  181. package/dist/fleet/rooms/room-hub.d.ts +154 -0
  182. package/dist/fleet/rooms/room-hub.js +363 -0
  183. package/dist/fleet/rooms/room-identity.d.ts +26 -0
  184. package/dist/fleet/rooms/room-identity.js +82 -0
  185. package/dist/fleet/rooms/room-lock.d.ts +34 -0
  186. package/dist/fleet/rooms/room-lock.js +180 -0
  187. package/dist/fleet/rooms/room-observations.d.ts +7 -0
  188. package/dist/fleet/rooms/room-observations.js +61 -0
  189. package/dist/fleet/rooms/room-server.d.ts +28 -0
  190. package/dist/fleet/rooms/room-server.js +75 -0
  191. package/dist/fleet/rooms/room-store.d.ts +119 -0
  192. package/dist/fleet/rooms/room-store.js +448 -0
  193. package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
  194. package/dist/fleet/rooms/room-ws-bridge.js +137 -0
  195. package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
  196. package/dist/fleet/sensory-mission-bridge.js +136 -0
  197. package/dist/git/worktree-sessions.js +1 -0
  198. package/dist/harness/contract.d.ts +4 -4
  199. package/dist/harness/fleet-supervisor.d.ts +16 -0
  200. package/dist/harness/fleet-supervisor.js +64 -0
  201. package/dist/harness/index.d.ts +4 -0
  202. package/dist/harness/index.js +4 -0
  203. package/dist/harness/mission-runner.d.ts +3 -0
  204. package/dist/harness/mission-runner.js +53 -0
  205. package/dist/harness/mission-store.d.ts +93 -0
  206. package/dist/harness/mission-store.js +297 -0
  207. package/dist/harness/tool-harness.d.ts +56 -0
  208. package/dist/harness/tool-harness.js +153 -0
  209. package/dist/hooks/use-enhanced-input.js +48 -4
  210. package/dist/hooks/use-input-handler.d.ts +1 -0
  211. package/dist/hooks/use-input-handler.js +82 -22
  212. package/dist/hooks/use-input-history.js +1 -0
  213. package/dist/identity/lisa-introspection.js +5 -2
  214. package/dist/identity/operational-self-model.d.ts +2 -0
  215. package/dist/identity/operational-self-model.js +4 -0
  216. package/dist/index.js +52 -6
  217. package/dist/mcp/client.d.ts +11 -0
  218. package/dist/mcp/client.js +68 -3
  219. package/dist/mcp/config.d.ts +20 -0
  220. package/dist/mcp/config.js +121 -8
  221. package/dist/mcp/import-normalize.d.ts +12 -0
  222. package/dist/mcp/import-normalize.js +114 -0
  223. package/dist/mcp/mcp-oauth-constants.d.ts +8 -0
  224. package/dist/mcp/mcp-oauth-constants.js +9 -0
  225. package/dist/mcp/mcp-oauth-provider.d.ts +80 -0
  226. package/dist/mcp/mcp-oauth-provider.js +241 -0
  227. package/dist/mcp/mcp-oauth.d.ts +60 -1
  228. package/dist/mcp/mcp-oauth.js +241 -65
  229. package/dist/mcp/transports.d.ts +14 -5
  230. package/dist/mcp/transports.js +112 -101
  231. package/dist/mcp/types.d.ts +5 -0
  232. package/dist/media/comfyui-recipe-contract.d.ts +7 -7
  233. package/dist/memory/facts-memory.d.ts +11 -1
  234. package/dist/memory/facts-memory.js +47 -8
  235. package/dist/memory/memory-candidate-queue.d.ts +2 -2
  236. package/dist/memory/memory-candidate-queue.js +6 -6
  237. package/dist/memory/persistent-memory.d.ts +13 -8
  238. package/dist/memory/persistent-memory.js +77 -30
  239. package/dist/nodes/device-node.js +5 -9
  240. package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
  241. package/dist/observability/run-event-writer.d.ts +21 -0
  242. package/dist/observability/run-event-writer.js +81 -0
  243. package/dist/observability/run-store.d.ts +5 -0
  244. package/dist/observability/run-store.js +18 -13
  245. package/dist/observability/run-trajectory.js +1 -1
  246. package/dist/optimization/prompt-cache.d.ts +19 -2
  247. package/dist/optimization/prompt-cache.js +41 -6
  248. package/dist/orchestration/orchestrator.d.ts +21 -0
  249. package/dist/orchestration/orchestrator.js +122 -15
  250. package/dist/persistence/session-content.d.ts +8 -0
  251. package/dist/persistence/session-content.js +76 -0
  252. package/dist/persistence/session-handoff.d.ts +64 -0
  253. package/dist/persistence/session-handoff.js +80 -0
  254. package/dist/persistence/session-history.d.ts +4 -0
  255. package/dist/persistence/session-history.js +38 -0
  256. package/dist/persistence/session-store.d.ts +9 -0
  257. package/dist/persistence/session-store.js +48 -20
  258. package/dist/personas/persona-manager.js +17 -1
  259. package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
  260. package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
  261. package/dist/plugins/plugin-manager.js +10 -1
  262. package/dist/prompts/prompt-manager.js +11 -4
  263. package/dist/prompts/system-base.js +6 -2
  264. package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
  265. package/dist/protocols/a2a/codebuddy-executor.js +9 -8
  266. package/dist/protocols/a2a/index.d.ts +1 -1
  267. package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
  268. package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
  269. package/dist/protocols/a2a/peer-config.d.ts +20 -0
  270. package/dist/protocols/a2a/peer-config.js +55 -0
  271. package/dist/providers/codex-oauth.js +30 -6
  272. package/dist/providers/model-provider-compat.js +2 -1
  273. package/dist/sandbox/os-sandbox.d.ts +1 -1
  274. package/dist/scheduler/cron-scheduler.d.ts +15 -2
  275. package/dist/scheduler/cron-scheduler.js +35 -4
  276. package/dist/scheduler/job-notepad.d.ts +69 -0
  277. package/dist/scheduler/job-notepad.js +339 -0
  278. package/dist/security/audit-logger.d.ts +1 -1
  279. package/dist/security/compute-confinement.d.ts +4 -0
  280. package/dist/security/compute-confinement.js +89 -0
  281. package/dist/security/session-encryption.d.ts +4 -0
  282. package/dist/security/session-encryption.js +31 -0
  283. package/dist/sensory/voice-loop.d.ts +17 -0
  284. package/dist/sensory/voice-loop.js +72 -15
  285. package/dist/server/auth/device-session-context.d.ts +9 -0
  286. package/dist/server/auth/device-session-context.js +13 -0
  287. package/dist/server/auth/device-store.d.ts +89 -0
  288. package/dist/server/auth/device-store.js +261 -0
  289. package/dist/server/auth/device-token.d.ts +3 -0
  290. package/dist/server/auth/device-token.js +6 -0
  291. package/dist/server/auth/jwt.js +4 -0
  292. package/dist/server/index.d.ts +0 -10
  293. package/dist/server/index.js +28 -0
  294. package/dist/server/middleware/auth.js +3 -2
  295. package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
  296. package/dist/server/routes/a2a-jsonrpc.js +66 -0
  297. package/dist/server/routes/a2a-protocol.d.ts +12 -0
  298. package/dist/server/routes/a2a-protocol.js +1 -1
  299. package/dist/server/routes/device-auth.d.ts +4 -0
  300. package/dist/server/routes/device-auth.js +40 -0
  301. package/dist/server/types.d.ts +4 -0
  302. package/dist/server/websocket/handler.d.ts +13 -0
  303. package/dist/server/websocket/handler.js +102 -17
  304. package/dist/services/prompt-builder.d.ts +2 -0
  305. package/dist/services/prompt-builder.js +16 -6
  306. package/dist/services/runtime-settings-context.d.ts +81 -0
  307. package/dist/services/runtime-settings-context.js +79 -0
  308. package/dist/skills/executor.js +2 -0
  309. package/dist/skills/hub.js +16 -14
  310. package/dist/skills/local-inventory.d.ts +21 -0
  311. package/dist/skills/local-inventory.js +72 -0
  312. package/dist/skills/skill-loader.js +2 -2
  313. package/dist/skills/skill-usage-store.d.ts +49 -0
  314. package/dist/skills/skill-usage-store.js +121 -0
  315. package/dist/testing/ai-integration-tests.js +8 -5
  316. package/dist/themes/theme-manager.d.ts +12 -0
  317. package/dist/themes/theme-manager.js +29 -0
  318. package/dist/themes/theme-schema.d.ts +24 -24
  319. package/dist/tools/a2a-call-tool.d.ts +34 -0
  320. package/dist/tools/a2a-call-tool.js +75 -0
  321. package/dist/tools/bash/streaming-executor.d.ts +1 -0
  322. package/dist/tools/bash/streaming-executor.js +78 -90
  323. package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
  324. package/dist/tools/code-exec-preflight-runner.js +254 -0
  325. package/dist/tools/code-exec-preflight.d.ts +44 -0
  326. package/dist/tools/code-exec-preflight.js +501 -0
  327. package/dist/tools/code-exec-tool.d.ts +48 -1
  328. package/dist/tools/code-exec-tool.js +191 -47
  329. package/dist/tools/comment-watcher.js +29 -12
  330. package/dist/tools/core-code-inspection.d.ts +56 -0
  331. package/dist/tools/core-code-inspection.js +86 -0
  332. package/dist/tools/create-skill-tool.d.ts +2 -3
  333. package/dist/tools/create-skill-tool.js +16 -75
  334. package/dist/tools/cronjob-tool.d.ts +1 -0
  335. package/dist/tools/cronjob-tool.js +1 -0
  336. package/dist/tools/env-doctor-tool.d.ts +2 -0
  337. package/dist/tools/env-doctor-tool.js +4 -3
  338. package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
  339. package/dist/tools/execute-code-rpc-invoker.js +35 -19
  340. package/dist/tools/execute-code-runner.d.ts +2 -0
  341. package/dist/tools/execute-code-runner.js +52 -17
  342. package/dist/tools/fleet-room-tool.d.ts +104 -0
  343. package/dist/tools/fleet-room-tool.js +124 -0
  344. package/dist/tools/integration-tool-hints.d.ts +4 -0
  345. package/dist/tools/integration-tool-hints.js +19 -0
  346. package/dist/tools/list-peers-tool.d.ts +3 -0
  347. package/dist/tools/list-peers-tool.js +11 -4
  348. package/dist/tools/media-generation-tool.d.ts +16 -1
  349. package/dist/tools/media-generation-tool.js +341 -9
  350. package/dist/tools/merge-conflict-tool.js +53 -25
  351. package/dist/tools/metadata.d.ts +1 -5
  352. package/dist/tools/metadata.js +30 -28
  353. package/dist/tools/peer-tool-invoke-tool.d.ts +61 -0
  354. package/dist/tools/peer-tool-invoke-tool.js +396 -0
  355. package/dist/tools/ragchat-tool.d.ts +39 -0
  356. package/dist/tools/ragchat-tool.js +105 -0
  357. package/dist/tools/registry/fleet-tools.d.ts +21 -3
  358. package/dist/tools/registry/fleet-tools.js +137 -4
  359. package/dist/tools/registry/index.d.ts +1 -1
  360. package/dist/tools/registry/index.js +2 -2
  361. package/dist/tools/registry/knowledge-tools.d.ts +2 -2
  362. package/dist/tools/registry/knowledge-tools.js +2 -2
  363. package/dist/tools/registry/lessons-tools.d.ts +7 -0
  364. package/dist/tools/registry/lessons-tools.js +43 -3
  365. package/dist/tools/registry/memory-tools.d.ts +1 -1
  366. package/dist/tools/registry/memory-tools.js +8 -8
  367. package/dist/tools/registry/research-tools.d.ts +1 -0
  368. package/dist/tools/registry/research-tools.js +4 -13
  369. package/dist/tools/registry/self-describe-tools.d.ts +1 -1
  370. package/dist/tools/registry/self-describe-tools.js +43 -30
  371. package/dist/tools/resource-catalog-tool.d.ts +38 -0
  372. package/dist/tools/resource-catalog-tool.js +46 -0
  373. package/dist/tools/skills-inspection-tool.js +30 -1
  374. package/dist/tools/stream-tool-output.d.ts +3 -0
  375. package/dist/tools/stream-tool-output.js +33 -0
  376. package/dist/tools/tool-call-scheduler.d.ts +10 -0
  377. package/dist/tools/tool-call-scheduler.js +58 -0
  378. package/dist/tools/tool-effect.d.ts +5 -0
  379. package/dist/tools/tool-effect.js +26 -0
  380. package/dist/tools/tool-search.d.ts +12 -11
  381. package/dist/tools/tool-search.js +67 -26
  382. package/dist/tools/types.d.ts +6 -0
  383. package/dist/ui/components/ChatHistory.d.ts +1 -1
  384. package/dist/ui/components/ChatHistory.js +2 -2
  385. package/dist/ui/components/ChatInput.d.ts +2 -1
  386. package/dist/ui/components/ChatInput.js +42 -88
  387. package/dist/ui/components/ChatInterface.d.ts +4 -2
  388. package/dist/ui/components/ChatInterface.js +27 -63
  389. package/dist/ui/components/CommandSuggestions.d.ts +0 -1
  390. package/dist/ui/components/CommandSuggestions.js +4 -6
  391. package/dist/ui/components/FileAutocomplete.js +1 -1
  392. package/dist/ui/components/KeyboardHelp.js +8 -6
  393. package/dist/ui/components/ModelSelection.js +6 -5
  394. package/dist/ui/components/StatusBar.d.ts +2 -1
  395. package/dist/ui/components/StatusBar.js +8 -7
  396. package/dist/ui/context/theme-context.js +3 -2
  397. package/dist/ui/index.d.ts +1 -1
  398. package/dist/ui/index.js +1 -1
  399. package/dist/ui/utils/markdown-renderer.js +4 -13
  400. package/dist/utils/atomic-write.d.ts +22 -0
  401. package/dist/utils/atomic-write.js +29 -0
  402. package/dist/utils/bounded-output.d.ts +16 -0
  403. package/dist/utils/bounded-output.js +63 -0
  404. package/dist/utils/config-validation/schema.d.ts +2 -2
  405. package/dist/utils/device-store-file.d.ts +4 -0
  406. package/dist/utils/device-store-file.js +40 -0
  407. package/dist/utils/export-manager.d.ts +9 -0
  408. package/dist/utils/export-manager.js +19 -0
  409. package/dist/utils/first-use-hints.d.ts +25 -0
  410. package/dist/utils/first-use-hints.js +58 -0
  411. package/dist/utils/graceful-shutdown.d.ts +8 -0
  412. package/dist/utils/graceful-shutdown.js +23 -7
  413. package/dist/utils/history-manager.js +1 -1
  414. package/dist/utils/update-notifier.js +16 -18
  415. package/dist/wizard/environment-detection.d.ts +5 -1
  416. package/dist/wizard/environment-detection.js +49 -7
  417. package/dist/wizard/onboarding.d.ts +5 -1
  418. package/dist/wizard/onboarding.js +90 -30
  419. package/dist/wizard/provider-onboarding.d.ts +2 -0
  420. package/dist/wizard/provider-onboarding.js +55 -17
  421. package/package.json +7 -3
@@ -22,6 +22,7 @@
22
22
  * Commander actions stay thin wrappers around the scheduler singleton.
23
23
  */
24
24
  import * as fs from 'fs';
25
+ import { validateContinuity } from '../../scheduler/job-notepad.js';
25
26
  /**
26
27
  * Build (and validate) a CronJob spec from CLI options. Pure: no side effects,
27
28
  * fully unit-testable. Returns either a spec or a human-readable error.
@@ -77,6 +78,17 @@ export function buildCronJobSpec(name, opts) {
77
78
  }
78
79
  spec.then = opts.then.trim();
79
80
  }
81
+ if (opts.continuity !== undefined) {
82
+ const parsed = parseJsonOption(opts.continuity, '--continuity');
83
+ if ('error' in parsed)
84
+ return parsed;
85
+ try {
86
+ spec.continuity = validateContinuity(parsed.value);
87
+ }
88
+ catch (error) {
89
+ return { error: `Invalid --continuity: ${String(error)}` };
90
+ }
91
+ }
80
92
  // Optional pre-check gate.
81
93
  if (opts.preCheck !== undefined) {
82
94
  const parsed = parseJsonOption(opts.preCheck, '--pre-check');
@@ -159,6 +171,17 @@ export function buildCronJobUpdates(job, opts) {
159
171
  }
160
172
  updates.then = opts.then.trim();
161
173
  }
174
+ if (opts.continuity !== undefined) {
175
+ const parsed = parseJsonOption(opts.continuity, '--continuity');
176
+ if ('error' in parsed)
177
+ return parsed;
178
+ try {
179
+ updates.continuity = validateContinuity(parsed.value);
180
+ }
181
+ catch (error) {
182
+ return { error: `Invalid --continuity: ${String(error)}` };
183
+ }
184
+ }
162
185
  if (opts.preCheck !== undefined && opts.clearPreCheck) {
163
186
  return { error: 'cron update: --pre-check and --clear-pre-check are mutually exclusive' };
164
187
  }
@@ -394,6 +417,7 @@ export function registerCronCommands(program) {
394
417
  .option('--skill-request <text>', 'request string passed to the skill executor')
395
418
  .option('--then <jobId>', 'chain: run this job id (or prefix) on successful completion')
396
419
  .option('--clear-then', 'remove the chain target')
420
+ .option('--continuity <json>', 'per-job continuity: true, false, or {enabled, notes}; inline JSON or @file')
397
421
  .option('--pre-check <json>', 'replace pre-check gate as inline JSON or @file')
398
422
  .option('--clear-pre-check', 'remove the pre-check gate')
399
423
  .option('--deliver <target>', 'replace delivery targets type:id (repeatable)', collectOption, [])
@@ -433,6 +457,7 @@ export function registerCronCommands(program) {
433
457
  .option('--skill <id>', 'no-agent skill run by registered skill name')
434
458
  .option('--skill-request <text>', 'request string passed to the skill executor')
435
459
  .option('--then <jobId>', 'chain: run this job id (or prefix) on successful completion')
460
+ .option('--continuity <json>', 'per-job continuity: true, false, or {enabled, notes}; inline JSON or @file')
436
461
  .option('--pre-check <json>', 'pre-check gate as inline JSON or @file')
437
462
  .option('--deliver <target>', 'delivery target type:id (repeatable)', collectOption, [])
438
463
  .option('--format <fmt>', 'delivery body format: full|summary')
@@ -0,0 +1,10 @@
1
+ import { Command } from 'commander';
2
+ import { DeviceAuthStore } from '../server/auth/device-store.js';
3
+ import { type SpawnSyncFn } from './token.js';
4
+ export interface DeviceCommandDependencies {
5
+ store?: DeviceAuthStore;
6
+ env?: NodeJS.ProcessEnv;
7
+ spawn?: SpawnSyncFn;
8
+ }
9
+ export declare function createPairCommand(deps?: DeviceCommandDependencies): Command;
10
+ export declare function createDevicesCommand(deps?: DeviceCommandDependencies): Command;
@@ -0,0 +1,91 @@
1
+ import { Command } from 'commander';
2
+ import { getDeviceAuthStore } from '../server/auth/device-store.js';
3
+ import { renderQrAnsi } from './token.js';
4
+ function pairingUrl(raw) {
5
+ try {
6
+ const url = new URL(raw);
7
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash)
8
+ throw new Error();
9
+ return url.toString().replace(/\/+$/, '');
10
+ }
11
+ catch {
12
+ throw new Error('Use a valid HTTP(S) server URL without credentials, query or fragment');
13
+ }
14
+ }
15
+ export function createPairCommand(deps = {}) {
16
+ return new Command('pair')
17
+ .description('Pair an Android authenticator with this server (local one-time code, 10 minutes)')
18
+ .option('--url <url>', 'Server URL reachable from the phone')
19
+ .option('--json', 'Print the QR payload as JSON')
20
+ .action((options) => {
21
+ try {
22
+ const env = deps.env ?? process.env;
23
+ const url = pairingUrl(options.url || env.CODEBUDDY_SERVER_URL || `http://127.0.0.1:${env.CODEBUDDY_SERVER_PORT || env.PORT || '3000'}`);
24
+ const { pairingCode, expiresAt } = (deps.store ?? getDeviceAuthStore()).createPairing();
25
+ const payload = JSON.stringify({ url, pairingCode });
26
+ if (options.json) {
27
+ console.log(payload);
28
+ return;
29
+ }
30
+ console.log(`Pairing code: ${pairingCode}`);
31
+ console.log(`Expires: ${expiresAt} (10 minutes, one use)`);
32
+ console.log(payload);
33
+ const qr = renderQrAnsi(payload, deps.spawn);
34
+ if (qr.ok)
35
+ console.log(qr.output);
36
+ else
37
+ console.error(qr.hint);
38
+ }
39
+ catch (error) {
40
+ console.error(error instanceof Error && error.message.startsWith('Use a valid')
41
+ ? error.message : 'Device pairing unavailable');
42
+ process.exitCode = 1;
43
+ }
44
+ });
45
+ }
46
+ export function createDevicesCommand(deps = {}) {
47
+ const command = new Command('devices').description('Manage Android authentication devices (local only)');
48
+ const getStore = () => deps.store ?? getDeviceAuthStore();
49
+ command.command('list').option('--json', 'Print public device metadata as JSON')
50
+ .action((options) => {
51
+ try {
52
+ const devices = getStore().list().map(({ publicKeyJwk: _key, ...metadata }) => metadata);
53
+ if (options.json)
54
+ console.log(JSON.stringify(devices, null, 2));
55
+ else if (devices.length === 0)
56
+ console.log('No Android devices paired. Run buddy pair.');
57
+ else
58
+ for (const device of devices) {
59
+ console.log(`${device.deviceId} ${device.deviceName} ${device.revokedAt ? 'revoked' : 'active'} ${device.createdAt}`);
60
+ }
61
+ }
62
+ catch {
63
+ console.error('Device store unavailable');
64
+ process.exitCode = 1;
65
+ }
66
+ });
67
+ command.command('revoke <id>').description('Revoke an Android authentication device')
68
+ .action((id) => {
69
+ try {
70
+ getStore().revoke(id);
71
+ console.log('Device revoked');
72
+ }
73
+ catch {
74
+ console.error('Unable to revoke device');
75
+ process.exitCode = 1;
76
+ }
77
+ });
78
+ command.command('rename <id> <name>').description('Rename an Android device')
79
+ .action((id, name) => {
80
+ try {
81
+ getStore().rename(id, name);
82
+ console.log('Device renamed');
83
+ }
84
+ catch {
85
+ console.error('Unable to rename device');
86
+ process.exitCode = 1;
87
+ }
88
+ });
89
+ return command;
90
+ }
91
+ //# sourceMappingURL=device-auth.js.map
@@ -2,10 +2,19 @@ import { ChatEntry } from "../agent/codebuddy-agent.js";
2
2
  import { CodeBuddyClient } from "../codebuddy/client.js";
3
3
  import type { CommandHandlerResult } from "./handlers/index.js";
4
4
  export type { CommandHandlerResult };
5
+ /**
6
+ * Give every handled result a visible `entry` when the handler only produced
7
+ * legacy text fields. Results that already carry an entry are left untouched.
8
+ */
9
+ export declare function normalizeHandlerResult(result: CommandHandlerResult): CommandHandlerResult;
5
10
  /**
6
11
  * Proxy interface for agent context stats used by the /context stats command.
7
12
  */
8
13
  export interface AgentContextProxy {
14
+ getMemoryScope?: () => {
15
+ cwd: string;
16
+ botId?: string;
17
+ };
9
18
  getContextStats: () => unknown;
10
19
  formatContextStats: () => string;
11
20
  getCurrentModel: () => string;
@@ -1,5 +1,6 @@
1
1
  import { handleGrillMe } from './handlers/grill-me-handler.js';
2
2
  import { handleDeepthink } from './handlers/deepthink-handler.js';
3
+ import { withFactsMemorySessionClient } from "../memory/facts-memory.js";
3
4
  // Import all handlers from modular files
4
5
  import {
5
6
  // Branch handlers
@@ -116,6 +117,7 @@ handleInfra,
116
117
  handleRedo, handleTimeline, handleKnowledgeGraph, handleApprovals, } from "./handlers/index.js";
117
118
  import { handleLessonsCommand } from "./handlers/index.js";
118
119
  import { handleContextStats } from "./handlers/extra-handlers.js";
120
+ import { handleResources } from "./handlers/resources-handler.js";
119
121
  import { handleLogin, handleLogout, handleWhoami } from "./handlers/auth-handlers.js";
120
122
  import { handlePromptCommand as handlePromptCommandRaw } from "./slash/prompt-commands.js";
121
123
  import { handleShortcuts, handleDebugMode, handleToolAnalytics, handleSecurityReview, handleIdentity, handlePairing, handleElevated, handlePolicy, } from "./handlers/index.js";
@@ -183,6 +185,25 @@ async function handlePromptCommand(args) {
183
185
  entry: { type: 'assistant', content: output, timestamp: new Date() },
184
186
  };
185
187
  }
188
+ /**
189
+ * Give every handled result a visible `entry` when the handler only produced
190
+ * legacy text fields. Results that already carry an entry are left untouched.
191
+ */
192
+ export function normalizeHandlerResult(result) {
193
+ if (!result.handled || result.entry) {
194
+ return result;
195
+ }
196
+ const legacy = result;
197
+ const text = [legacy.output, legacy.response, legacy.message, legacy.error]
198
+ .find((value) => typeof value === 'string' && value.trim().length > 0);
199
+ if (!text) {
200
+ return result;
201
+ }
202
+ return {
203
+ ...result,
204
+ entry: { type: 'assistant', content: text, timestamp: new Date() },
205
+ };
206
+ }
186
207
  /**
187
208
  * Enhanced Command Handler.
188
209
  *
@@ -225,8 +246,8 @@ export class EnhancedCommandHandler {
225
246
  ['__MERGE__', (args) => handleMerge(args)],
226
247
  ['__BRANCH__', (args) => handleBranch(args)],
227
248
  // Memory & TODOs
228
- ['__MEMORY__', (args) => handleMemory(args)],
229
- ['__REMEMBER__', (args) => handleRemember(args)],
249
+ ['__MEMORY__', (args) => this.agentProxy?.getMemoryScope ? handleMemory(args, this.agentProxy.getMemoryScope()) : handleMemory(args)],
250
+ ['__REMEMBER__', (args) => this.agentProxy?.getMemoryScope ? handleRemember(args, this.agentProxy.getMemoryScope()) : handleRemember(args)],
230
251
  ['__SCAN_TODOS__', () => handleScanTodos()],
231
252
  ['__ADDRESS_TODO__', (args) => handleAddressTodo(args)],
232
253
  // Context & Workspace
@@ -237,7 +258,7 @@ export class EnhancedCommandHandler {
237
258
  : handleContext(args)],
238
259
  // Export (context-dependent: conversationHistory)
239
260
  ['__SAVE_CONVERSATION__', (args) => handleSaveConversation(args, this.conversationHistory)],
240
- ['__EXPORT__', (args) => handleExport(args)],
261
+ ['__EXPORT__', (args) => handleExport(args, this.conversationHistory, this.agentProxy?.getCurrentModel())],
241
262
  ['__EXPORT_LIST__', () => handleExportList()],
242
263
  ['__EXPORT_FORMATS__', () => handleExportFormats()],
243
264
  // Testing (context-dependent: codebuddyClient)
@@ -306,10 +327,11 @@ export class EnhancedCommandHandler {
306
327
  ['__BATCH__', (args) => handleBatchSlashCommand(args, this.createBatchChatFn(), this.createBatchSpawnFn())],
307
328
  // Commands previously handled inline in client-dispatcher
308
329
  ['__CLEAR_CHAT__', () => handleClearChat()],
309
- ['__CHANGE_MODEL__', (args) => handleChangeModel(args)],
330
+ ['__CHANGE_MODEL__', (args) => handleChangeModel(args, this.agentProxy?.getCurrentModel())],
310
331
  ['__CHANGE_MODE__', (args) => handleChangeMode(args)],
311
332
  ['__PLAN_MODE__', () => handleChangeMode(['plan'])],
312
- ['__STATUS__', () => handleStatus()],
333
+ ['__STATUS__', () => handleStatus(this.agentProxy?.getCurrentModel())],
334
+ ['__RESOURCES__', () => handleResources()],
313
335
  ['__NEW__', (args) => handleNew(args)],
314
336
  ['__ULTRAPLAN__', (args) => handleUltraplan(args)],
315
337
  ['__LIST_CHECKPOINTS__', (args) => handleListCheckpoints(args)],
@@ -541,7 +563,7 @@ export class EnhancedCommandHandler {
541
563
  async handleCommand(token, args, _fullInput) {
542
564
  const handler = this.handlerMap.get(token);
543
565
  if (handler) {
544
- return handler(args);
566
+ return withFactsMemorySessionClient(this.codebuddyClient ?? null, async () => normalizeHandlerResult(await handler(args)));
545
567
  }
546
568
  return { handled: false };
547
569
  }
@@ -2,7 +2,7 @@
2
2
  * Agent command handlers
3
3
  *
4
4
  * Handles /agent commands for custom agent management:
5
- * - /agent - List all agents
5
+ * - /agent, /agent list - List all agents
6
6
  * - /agent <id> - Activate an agent
7
7
  * - /agent create <name> - Create a new agent
8
8
  * - /agent info <id> - Show agent details
@@ -2,7 +2,7 @@
2
2
  * Agent command handlers
3
3
  *
4
4
  * Handles /agent commands for custom agent management:
5
- * - /agent - List all agents
5
+ * - /agent, /agent list - List all agents
6
6
  * - /agent <id> - Activate an agent
7
7
  * - /agent create <name> - Create a new agent
8
8
  * - /agent info <id> - Show agent details
@@ -14,14 +14,14 @@ import { setActiveCustomAgentRuntime } from '../../agent/custom/custom-agent-run
14
14
  */
15
15
  export function handleAgent(args) {
16
16
  const loader = getCustomAgentLoader();
17
- // No args - list agents
18
- if (args.length === 0) {
17
+ const subcommand = args[0]?.toLowerCase() ?? '';
18
+ // No args or the documented `list` action - list agents
19
+ if (args.length === 0 || (subcommand === 'list' && args.length === 1)) {
19
20
  return {
20
21
  handled: true,
21
22
  output: loader.formatAgentList(),
22
23
  };
23
24
  }
24
- const subcommand = args[0]?.toLowerCase() ?? '';
25
25
  // Create new agent
26
26
  if (subcommand === 'create') {
27
27
  return handleAgentCreate(args.slice(1));
@@ -1595,6 +1595,8 @@ export async function registerAIMessageHandler(manager) {
1595
1595
  let successfulLisaSelfieToolResult = false;
1596
1596
  let shouldPersistChannelSession = Boolean(agent);
1597
1597
  let telegramWidget;
1598
+ let companionMediaResult;
1599
+ let companionHistorySuffix;
1598
1600
  if (prefetchedDirectResponse) {
1599
1601
  response = prefetchedDirectResponse;
1600
1602
  if (agent && !agent.recordTrustedExternalConversationTurn(agentInput, response)) {
@@ -1632,16 +1634,34 @@ export async function registerAIMessageHandler(manager) {
1632
1634
  sharedPhotos: companionPhotos?.photos.length ?? 0,
1633
1635
  });
1634
1636
  try {
1637
+ let companionIdentity;
1638
+ if (channel.type === 'telegram') {
1639
+ const { resolveCompanionIdentity } = await import('../../companion/companion-identity.js');
1640
+ const telegramChannel = channel;
1641
+ companionIdentity = resolveCompanionIdentity({
1642
+ channel: 'telegram',
1643
+ chatId: message.channel.id,
1644
+ senderId: message.sender?.id,
1645
+ senderUsername: message.sender?.username,
1646
+ allowedUsers: telegramChannel.config?.allowedUsers ?? [],
1647
+ env: process.env,
1648
+ });
1649
+ }
1635
1650
  const generated = await runCompanionChannelTurn({
1636
1651
  apiKey: effectiveRuntime.apiKey,
1637
1652
  baseUrl: effectiveRuntime.baseUrl,
1638
1653
  model: effectiveRuntime.model,
1639
1654
  messages: companionMessages,
1640
1655
  signal: turn.signal,
1656
+ ...(companionIdentity ? { identity: companionIdentity } : {}),
1657
+ surface: channel.type,
1658
+ env: process.env,
1641
1659
  });
1642
1660
  turn.throwIfAborted();
1643
1661
  response = generated.text;
1644
1662
  hasGeneratedResponse = response.trim() !== '';
1663
+ companionMediaResult = generated.media;
1664
+ companionHistorySuffix = generated.historySuffix;
1645
1665
  if (hasSharedPhotos && companionPhotos) {
1646
1666
  // The album write is deliberately after the reply: a full disk must
1647
1667
  // cost the memory, never the reaction.
@@ -1860,7 +1880,35 @@ export async function registerAIMessageHandler(manager) {
1860
1880
  turn.throwIfAborted();
1861
1881
  turn.phase('delivery');
1862
1882
  deliveryState = 'started';
1863
- if (channel.type === 'telegram' && response.trim() && telegramWidget) {
1883
+ if (channel.type === 'telegram' && response.trim() && companionMediaResult && companionMediaResult.length > 0) {
1884
+ const media = companionMediaResult[0];
1885
+ if (media) {
1886
+ const pathMod = await import('path');
1887
+ const ext = pathMod.extname(media.imagePath).slice(1) || 'png';
1888
+ const result = await channel.send({
1889
+ channelId: message.channel.id,
1890
+ content: response,
1891
+ replyTo: message.id,
1892
+ attachments: [
1893
+ {
1894
+ type: 'image',
1895
+ filePath: media.imagePath,
1896
+ fileName: pathMod.basename(media.imagePath),
1897
+ mimeType: ext === 'jpg' || ext === 'jpeg' ? 'image/jpeg' : `image/${ext}`,
1898
+ },
1899
+ ],
1900
+ });
1901
+ delivered = result?.success === true;
1902
+ deliveredChunks = delivered ? 1 : 0;
1903
+ if (delivered)
1904
+ deliveredAssistantContent = response;
1905
+ if (delivered)
1906
+ deliveryMode = 'telegram-photo';
1907
+ else
1908
+ deliveryMode = 'failed';
1909
+ }
1910
+ }
1911
+ else if (channel.type === 'telegram' && response.trim() && telegramWidget) {
1864
1912
  const result = await channel.send({
1865
1913
  channelId: message.channel.id,
1866
1914
  content: response,
@@ -2070,7 +2118,10 @@ export async function registerAIMessageHandler(manager) {
2070
2118
  turn.throwIfAborted();
2071
2119
  turn.phase('persistence');
2072
2120
  if (useCompanionProfile && response.trim()) {
2073
- rememberCompanionChannelTurn(sessionKey, message.content, response);
2121
+ const recordedResponse = companionHistorySuffix
2122
+ ? `${response}${companionHistorySuffix}`
2123
+ : response;
2124
+ rememberCompanionChannelTurn(sessionKey, message.content, recordedResponse);
2074
2125
  }
2075
2126
  if (shouldPersistChannelSession && agent)
2076
2127
  await persistChannelSession(agent, sessionKey);
@@ -3,12 +3,13 @@
3
3
  *
4
4
  * Handlers for exporting sessions, conversations, and tool results
5
5
  */
6
+ import type { ChatEntry } from '../../agent/types.js';
6
7
  import { CommandHandlerResult } from './branch-handlers.js';
7
8
  /**
8
9
  * Handle /export command
9
- * Export current or specified session to file
10
+ * Export the current conversation, or a saved session with session:<id>
10
11
  */
11
- export declare function handleExport(args: string[]): Promise<CommandHandlerResult>;
12
+ export declare function handleExport(args: string[], conversationHistory?: ChatEntry[], currentModel?: string): Promise<CommandHandlerResult>;
12
13
  /**
13
14
  * Handle /export-list command
14
15
  * List all exported files
@@ -3,54 +3,81 @@
3
3
  *
4
4
  * Handlers for exporting sessions, conversations, and tool results
5
5
  */
6
+ import { initializeDatabase } from '../../database/database-manager.js';
6
7
  import { getExportManager } from '../../utils/export-manager.js';
7
- import { getSessionRepository } from '../../database/repositories/session-repository.js';
8
+ function reply(content) {
9
+ return { handled: true, entry: { type: 'assistant', content, timestamp: new Date() } };
10
+ }
11
+ /** Map the visible transcript to export messages; UI-only entries are skipped. */
12
+ function chatEntriesToMessages(history) {
13
+ const messages = [];
14
+ for (const entry of history) {
15
+ if (entry.type === 'user' || entry.type === 'assistant') {
16
+ messages.push({ role: entry.type, content: entry.content, timestamp: entry.timestamp });
17
+ }
18
+ else if (entry.type === 'tool_result') {
19
+ messages.push({
20
+ role: 'tool',
21
+ content: entry.content,
22
+ timestamp: entry.timestamp,
23
+ toolName: entry.toolCall?.function?.name ?? 'tool',
24
+ toolCallId: entry.toolCall?.id,
25
+ });
26
+ }
27
+ }
28
+ return messages;
29
+ }
8
30
  /**
9
31
  * Handle /export command
10
- * Export current or specified session to file
32
+ * Export the current conversation, or a saved session with session:<id>
11
33
  */
12
- export async function handleExport(args) {
34
+ export async function handleExport(args, conversationHistory = [], currentModel) {
13
35
  const exportManager = getExportManager();
14
- const sessionRepo = getSessionRepository();
15
36
  // Parse arguments
16
37
  const format = args.find(a => ['json', 'markdown', 'html', 'text'].includes(a)) || 'markdown';
17
38
  const sessionIdArg = args.find(a => a.startsWith('session:'))?.split(':')[1];
18
39
  const includeSecrets = args.includes('--include-secrets');
19
40
  const noToolCalls = args.includes('--no-tools');
20
41
  const noMetadata = args.includes('--no-metadata');
21
- // Get session to export
22
- let sessionId;
42
+ const options = {
43
+ redactSecrets: !includeSecrets,
44
+ includeToolCalls: !noToolCalls,
45
+ includeMetadata: !noMetadata,
46
+ };
47
+ let result;
23
48
  if (sessionIdArg) {
24
- sessionId = sessionIdArg;
49
+ // Saved sessions live in the SQLite session database, which the
50
+ // interactive CLI does not open at startup.
51
+ try {
52
+ await initializeDatabase();
53
+ }
54
+ catch (error) {
55
+ return reply(`Failed to export session ${sessionIdArg}: session database unavailable (${error instanceof Error ? error.message : String(error)}).`);
56
+ }
57
+ result = await exportManager.exportSession(sessionIdArg, format, options);
25
58
  }
26
59
  else {
27
- // Get most recent session
28
- const sessions = sessionRepo.findSessions({ limit: 1 });
29
- const mostRecent = sessions[0];
30
- if (!mostRecent) {
31
- return {
32
- handled: true,
33
- entry: {
34
- type: 'assistant',
35
- content: 'No sessions found to export.',
36
- timestamp: new Date(),
37
- },
38
- };
60
+ // The current session is the conversation on screen, not the most recent
61
+ // database row (which may belong to another project).
62
+ const messages = chatEntriesToMessages(conversationHistory);
63
+ if (messages.length === 0) {
64
+ return reply('Nothing to export yet: the current conversation is empty.\n\nSend a message first, or export a saved session with /export <format> session:<id>.');
39
65
  }
40
- sessionId = mostRecent.id;
66
+ result = await exportManager.exportConversationData({
67
+ title: 'Code Buddy conversation',
68
+ model: currentModel,
69
+ startTime: messages[0]?.timestamp,
70
+ endTime: messages[messages.length - 1]?.timestamp,
71
+ messages,
72
+ metadata: { projectPath: process.cwd(), messageCount: messages.length },
73
+ }, format, options);
41
74
  }
42
- // Export session
43
- const result = await exportManager.exportSession(sessionId, format, {
44
- redactSecrets: !includeSecrets,
45
- includeToolCalls: !noToolCalls,
46
- includeMetadata: !noMetadata,
47
- });
48
75
  if (result.success && result.filePath) {
49
76
  return {
50
77
  handled: true,
51
78
  entry: {
52
79
  type: 'assistant',
53
- content: `Session exported successfully!
80
+ content: `${sessionIdArg ? `Session ${sessionIdArg}` : 'Current conversation'} exported successfully!
54
81
 
55
82
  **Format:** ${format}
56
83
  **File:** ${result.filePath}
@@ -68,7 +95,7 @@ cat "${result.filePath}"
68
95
  handled: true,
69
96
  entry: {
70
97
  type: 'assistant',
71
- content: `Failed to export session: ${result.error}`,
98
+ content: `Failed to export ${sessionIdArg ? `session ${sessionIdArg}` : 'the current conversation'}: ${result.error}`,
72
99
  timestamp: new Date(),
73
100
  },
74
101
  };
@@ -311,7 +311,10 @@ export async function handleSearch(args) {
311
311
  try {
312
312
  const cwd = process.cwd();
313
313
  let output = '';
314
- const rgResult = runCommand('rg', ['--line-number', '--no-heading', '--color=never', '--max-count=20', '--', query], { cwd, timeoutMs: 10000 });
314
+ // Explicit `.` path: without one, ripgrep searches stdin whenever stdin is
315
+ // not a TTY (every non-interactive spawn), so real matches were reported as
316
+ // "No matches" (status 1).
317
+ const rgResult = runCommand('rg', ['--line-number', '--no-heading', '--color=never', '--max-count=20', '--', query, '.'], { cwd, timeoutMs: 10000 });
315
318
  if (rgResult.success) {
316
319
  output = rgResult.output;
317
320
  }
@@ -586,6 +589,7 @@ function createProgressBar(percent, width) {
586
589
  function runCommand(command, args, { cwd, timeoutMs, env }) {
587
590
  const result = spawnSync(command, args, {
588
591
  cwd,
592
+ stdio: ['ignore', 'pipe', 'pipe'],
589
593
  encoding: 'utf-8',
590
594
  maxBuffer: 5 * 1024 * 1024,
591
595
  timeout: timeoutMs,
@@ -1,32 +1,40 @@
1
+ // Written as the user's own request about their own work. The previous wording
2
+ // (role orders addressed to the assistant: "Mène un interrogatoire", "Exige",
3
+ // "Ne flatte pas l'auteur", "ce qui ment") made qwen3:4b answer the injection
4
+ // refusal sentence in the real CLI (recette 2026-09-14), without any tool call.
1
5
  function buildPrompt(target, yolo) {
2
6
  const scope = target
3
- ? `Sujet ciblé par l'utilisateur : ${target}`
4
- : 'Sujet par défaut : le travail récent du dépôt.';
7
+ ? `Sujet ciblé : ${target}`
8
+ : 'Sujet par défaut : mon travail récent dans ce dépôt.';
9
+ // The recent work includes uncommitted changes, and HEAD~1 does not exist in
10
+ // a single-commit repository: inspect the working tree first.
11
+ const gitInspection = 'git status --short, git diff (modifications non indexées), git diff --cached (modifications indexées) et git log -5 --oneline ; git diff HEAD~1 seulement si le dépôt compte au moins deux commits';
5
12
  const baseInstructions = target
6
- ? `Examine d'abord ce sujet précis avec les outils disponibles : ${target}. Utilise aussi le contexte git pertinent si nécessaire, notamment git log -5, git diff HEAD~1 et les fichiers modifiés.`
7
- : 'Examine d\'abord le travail récent avec les outils disponibles : git log -5, git diff HEAD~1 et la liste des fichiers modifiés.';
13
+ ? `Examine d'abord ce sujet avec les outils disponibles : ${target}. Utilise aussi le contexte git utile et la liste des fichiers modifiés : ${gitInspection}.`
14
+ : `Examine d'abord mon travail récent et la liste des fichiers modifiés avec les outils disponibles : ${gitInspection}.`;
8
15
  if (yolo) {
9
- return `${scope}
16
+ return `J'ai lancé /grill-me --yolo : je veux une revue technique de mon propre travail en mode ROAST intégral.
17
+
18
+ ${scope}
10
19
 
11
20
  ${baseInstructions}
12
21
 
13
- Tu es en mode ROAST intégral pour /grill-me --yolo.
14
- Interroge techniquement l'auteur sans aucune complaisance : brutal, sarcastique, aucune politesse, aucun coussin diplomatique.
15
- Chaque pique DOIT rester techniquement exacte, vérifiable et actionnable : cite les fichiers, diffs, noms, tests ou choix qui justifient l'attaque.
16
- Grille l'auteur sur les choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité, les abstractions inutiles et les noms mensongers.
17
- Exige des réponses concrètes, pas des excuses : pour chaque accusation, demande quelle preuve, quel test ou quel correctif va fermer le sujet.
18
- Si une critique n'est pas étayée par le dépôt ou le diff, ne la formule pas.`;
22
+ Ensuite, sois brutal et sarcastique avec moi, sans politesse ni précautions diplomatiques.
23
+ Chaque critique doit rester techniquement exacte, vérifiable et actionnable : cite les fichiers, diffs, noms, tests ou choix qui la justifient.
24
+ Vise mes choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité, les abstractions inutiles et les noms trompeurs.
25
+ Pour chaque critique, demande-moi quelle preuve, quel test ou quel correctif fermera le sujet.
26
+ N'invente rien : une critique que le dépôt ou le diff ne prouve pas ne doit pas être formulée.`;
19
27
  }
20
- return `${scope}
28
+ return `J'ai lancé /grill-me : je veux une revue technique exigeante de mon propre travail.
29
+
30
+ ${scope}
21
31
 
22
32
  ${baseInstructions}
23
33
 
24
- Mène un interrogatoire technique ferme mais constructif.
25
- Après examen, pose 5 à 7 questions dures et précises sur les choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité et les noms mensongers.
26
- Les questions doivent viser des lignes, fichiers, comportements ou décisions observables, pas des généralités.
27
- Exige des réponses et des preuves concrètes, pas des excuses.
28
- Ajoute ensuite 3 risques classés par sévérité, avec pour chacun l'impact, la probabilité et l'action minimale pour le réduire.
29
- Ne flatte pas l'auteur : aide-le à voir ce qui casse, ce qui ment et ce qui manque.`;
34
+ Ensuite, pose-moi 5 à 7 questions difficiles et précises sur mes choix discutables, la dette introduite, les tests manquants, les cas limites ignorés, la sécurité et les noms trompeurs.
35
+ Chaque question doit viser des lignes, fichiers, comportements ou décisions observables, pas des généralités, et me demander une preuve concrète.
36
+ Termine par 3 risques classés par sévérité, avec pour chacun l'impact, la probabilité et l'action minimale pour le réduire.
37
+ Reste franc et constructif, sans compliments inutiles : aide-moi à voir ce qui casse, ce qui est inexact et ce qui manque.`;
30
38
  }
31
39
  export async function handleGrillMe(args) {
32
40
  const remainingArgs = args.filter(arg => arg !== '--yolo');
@@ -1,4 +1,8 @@
1
1
  import { ChatEntry } from "../../agent/codebuddy-agent.js";
2
+ export interface MemoryCommandContext {
3
+ cwd?: string;
4
+ botId?: string;
5
+ }
2
6
  export interface CommandHandlerResult {
3
7
  handled: boolean;
4
8
  entry?: ChatEntry;
@@ -9,11 +13,11 @@ export interface CommandHandlerResult {
9
13
  /**
10
14
  * Memory - Manage persistent memory using PersistentMemoryManager (Markdown) and EnhancedMemory (SQLite/Vector)
11
15
  */
12
- export declare function handleMemory(args: string[]): Promise<CommandHandlerResult>;
16
+ export declare function handleMemory(args: string[], context?: MemoryCommandContext): Promise<CommandHandlerResult>;
13
17
  /**
14
18
  * Remember - Quick memory store using PersistentMemoryManager and EnhancedMemory
15
19
  */
16
- export declare function handleRemember(args: string[]): Promise<CommandHandlerResult>;
20
+ export declare function handleRemember(args: string[], context?: MemoryCommandContext): Promise<CommandHandlerResult>;
17
21
  /**
18
22
  * Scan Todos - Find AI-directed comments
19
23
  */