@phuetz/code-buddy 2.0.0 → 2.1.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 (403) hide show
  1. package/README.fr.md +56 -0
  2. package/README.md +73 -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 +165 -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.js +19 -2
  13. package/dist/agent/facades/session-facade.d.ts +0 -6
  14. package/dist/agent/facades/session-facade.js +0 -45
  15. package/dist/agent/hermes-claw-migrate.d.ts +0 -21
  16. package/dist/agent/hermes-claw-migrate.js +9 -4
  17. package/dist/agent/hermes-protocol-gateways.js +8 -1
  18. package/dist/agent/repo-profiler.js +17 -4
  19. package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
  20. package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
  21. package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
  22. package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
  23. package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
  24. package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
  25. package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
  26. package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
  27. package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
  28. package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
  29. package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
  30. package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
  31. package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
  32. package/dist/agent/self-improvement/proposal-store.js +79 -17
  33. package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
  34. package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
  35. package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
  36. package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
  37. package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
  38. package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
  39. package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
  40. package/dist/agent/self-improvement/skill-engine.js +385 -13
  41. package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
  42. package/dist/agent/self-improvement/skill-gate.js +17 -2
  43. package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
  44. package/dist/agent/self-improvement/skill-mutator.js +51 -15
  45. package/dist/agent/self-improvement/skill-types.d.ts +2 -1
  46. package/dist/agent/self-improvement/types.d.ts +11 -0
  47. package/dist/agent/tool-handler.d.ts +1 -1
  48. package/dist/agent/tool-handler.js +28 -9
  49. package/dist/auth/profile-manager.js +1 -1
  50. package/dist/channels/companion-channel-turn.d.ts +53 -4
  51. package/dist/channels/companion-channel-turn.js +218 -16
  52. package/dist/channels/slash-parity.d.ts +4 -6
  53. package/dist/channels/slash-parity.js +9 -44
  54. package/dist/cli/session-commands.d.ts +9 -0
  55. package/dist/cli/session-commands.js +45 -5
  56. package/dist/cli/session-picker.d.ts +43 -0
  57. package/dist/cli/session-picker.js +128 -0
  58. package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
  59. package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
  60. package/dist/codebuddy/fleet-tool-defs.d.ts +1 -0
  61. package/dist/codebuddy/fleet-tool-defs.js +24 -0
  62. package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
  63. package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
  64. package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
  65. package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
  66. package/dist/codebuddy/providers/provider-openai-compat.js +1 -1
  67. package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
  68. package/dist/codebuddy/ragchat-tool-defs.js +19 -0
  69. package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
  70. package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
  71. package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
  72. package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
  73. package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
  74. package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
  75. package/dist/codebuddy/tools.d.ts +0 -6
  76. package/dist/codebuddy/tools.js +25 -3
  77. package/dist/commands/cli/daemon-commands.js +3 -1
  78. package/dist/commands/cli/evolve-command.js +21 -5
  79. package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
  80. package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
  81. package/dist/commands/cli/fleet-commands.js +29 -0
  82. package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
  83. package/dist/commands/cli/fleet-mission-commands.js +72 -0
  84. package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
  85. package/dist/commands/cli/fleet-rooms-commands.js +289 -0
  86. package/dist/commands/cli/tools-commands.js +2 -1
  87. package/dist/commands/cli/triage-command.d.ts +8 -0
  88. package/dist/commands/cli/triage-command.js +72 -0
  89. package/dist/commands/cli/utility-commands.js +25 -1
  90. package/dist/commands/client-dispatcher.d.ts +7 -0
  91. package/dist/commands/client-dispatcher.js +73 -21
  92. package/dist/commands/cron-cli/index.d.ts +3 -1
  93. package/dist/commands/cron-cli/index.js +25 -0
  94. package/dist/commands/device-auth.d.ts +10 -0
  95. package/dist/commands/device-auth.js +91 -0
  96. package/dist/commands/enhanced-command-handler.d.ts +9 -0
  97. package/dist/commands/enhanced-command-handler.js +28 -6
  98. package/dist/commands/handlers/agent-handlers.d.ts +1 -1
  99. package/dist/commands/handlers/agent-handlers.js +4 -4
  100. package/dist/commands/handlers/channel-handlers.js +53 -2
  101. package/dist/commands/handlers/export-handlers.d.ts +3 -2
  102. package/dist/commands/handlers/export-handlers.js +55 -28
  103. package/dist/commands/handlers/extra-handlers.js +5 -1
  104. package/dist/commands/handlers/grill-me-handler.js +26 -18
  105. package/dist/commands/handlers/memory-handlers.d.ts +6 -2
  106. package/dist/commands/handlers/memory-handlers.js +35 -15
  107. package/dist/commands/handlers/missing-handlers.d.ts +2 -2
  108. package/dist/commands/handlers/missing-handlers.js +4 -4
  109. package/dist/commands/handlers/resources-handler.d.ts +12 -0
  110. package/dist/commands/handlers/resources-handler.js +52 -0
  111. package/dist/commands/handlers/starter-handlers.d.ts +1 -1
  112. package/dist/commands/handlers/starter-handlers.js +32 -2
  113. package/dist/commands/handlers/switch-handler.d.ts +1 -1
  114. package/dist/commands/handlers/switch-handler.js +15 -0
  115. package/dist/commands/handlers/test-handlers.js +4 -86
  116. package/dist/commands/handlers/ui-handlers.js +11 -5
  117. package/dist/commands/login-chatgpt.d.ts +8 -0
  118. package/dist/commands/login-chatgpt.js +17 -0
  119. package/dist/commands/mcp-import.d.ts +11 -0
  120. package/dist/commands/mcp-import.js +67 -0
  121. package/dist/commands/mcp-invoke.d.ts +2 -0
  122. package/dist/commands/mcp-invoke.js +68 -0
  123. package/dist/commands/mcp.js +4 -0
  124. package/dist/commands/pipeline.d.ts +7 -1
  125. package/dist/commands/pipeline.js +104 -7
  126. package/dist/commands/resources.d.ts +2 -0
  127. package/dist/commands/resources.js +64 -0
  128. package/dist/commands/skills-cli/index.js +35 -12
  129. package/dist/commands/slash/builtin-commands.js +16 -3
  130. package/dist/commands/slash/index.d.ts +3 -1
  131. package/dist/commands/slash/index.js +2 -0
  132. package/dist/commands/slash/surfaces.d.ts +53 -0
  133. package/dist/commands/slash/surfaces.js +177 -0
  134. package/dist/commands/slash/types.d.ts +17 -0
  135. package/dist/commands/try.d.ts +1 -1
  136. package/dist/commands/try.js +1 -1
  137. package/dist/companion/companion-identity.d.ts +43 -0
  138. package/dist/companion/companion-identity.js +136 -0
  139. package/dist/companion/companion-toolset.d.ts +66 -0
  140. package/dist/companion/companion-toolset.js +368 -0
  141. package/dist/companion/companion-turn.d.ts +10 -2
  142. package/dist/companion/companion-turn.js +38 -1
  143. package/dist/config/code-exec-policy.d.ts +25 -0
  144. package/dist/config/code-exec-policy.js +39 -0
  145. package/dist/config/model-tools.d.ts +9 -0
  146. package/dist/config/model-tools.js +4 -0
  147. package/dist/context/context-manager-v2.js +2 -2
  148. package/dist/context/lm-resizer-compressor.js +3 -2
  149. package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
  150. package/dist/context/lm-resizer-diagnostics.js +30 -0
  151. package/dist/context/tool-output-masking.js +3 -4
  152. package/dist/curator/curator.d.ts +6 -0
  153. package/dist/curator/curator.js +53 -3
  154. package/dist/daemon/cron-agent-bridge.d.ts +6 -0
  155. package/dist/daemon/cron-agent-bridge.js +31 -4
  156. package/dist/doctor/index.d.ts +11 -2
  157. package/dist/doctor/index.js +84 -21
  158. package/dist/doctor/integrations.d.ts +179 -0
  159. package/dist/doctor/integrations.js +227 -0
  160. package/dist/doctor/triage.d.ts +108 -0
  161. package/dist/doctor/triage.js +304 -0
  162. package/dist/fleet/collaboration.d.ts +44 -0
  163. package/dist/fleet/collaboration.js +170 -0
  164. package/dist/fleet/fleet-listener.d.ts +1 -0
  165. package/dist/fleet/fleet-listener.js +87 -46
  166. package/dist/fleet/fleet-registry.d.ts +2 -0
  167. package/dist/fleet/resource-catalog.d.ts +245 -0
  168. package/dist/fleet/resource-catalog.js +211 -0
  169. package/dist/fleet/rooms/room-access.d.ts +138 -0
  170. package/dist/fleet/rooms/room-access.js +196 -0
  171. package/dist/fleet/rooms/room-client.d.ts +158 -0
  172. package/dist/fleet/rooms/room-client.js +685 -0
  173. package/dist/fleet/rooms/room-event.d.ts +139 -0
  174. package/dist/fleet/rooms/room-event.js +330 -0
  175. package/dist/fleet/rooms/room-filter.d.ts +48 -0
  176. package/dist/fleet/rooms/room-filter.js +152 -0
  177. package/dist/fleet/rooms/room-hub.d.ts +154 -0
  178. package/dist/fleet/rooms/room-hub.js +363 -0
  179. package/dist/fleet/rooms/room-identity.d.ts +26 -0
  180. package/dist/fleet/rooms/room-identity.js +82 -0
  181. package/dist/fleet/rooms/room-lock.d.ts +34 -0
  182. package/dist/fleet/rooms/room-lock.js +180 -0
  183. package/dist/fleet/rooms/room-observations.d.ts +7 -0
  184. package/dist/fleet/rooms/room-observations.js +61 -0
  185. package/dist/fleet/rooms/room-server.d.ts +28 -0
  186. package/dist/fleet/rooms/room-server.js +75 -0
  187. package/dist/fleet/rooms/room-store.d.ts +119 -0
  188. package/dist/fleet/rooms/room-store.js +448 -0
  189. package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
  190. package/dist/fleet/rooms/room-ws-bridge.js +137 -0
  191. package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
  192. package/dist/fleet/sensory-mission-bridge.js +136 -0
  193. package/dist/git/worktree-sessions.js +1 -0
  194. package/dist/harness/contract.d.ts +4 -4
  195. package/dist/harness/fleet-supervisor.d.ts +16 -0
  196. package/dist/harness/fleet-supervisor.js +64 -0
  197. package/dist/harness/index.d.ts +4 -0
  198. package/dist/harness/index.js +4 -0
  199. package/dist/harness/mission-runner.d.ts +3 -0
  200. package/dist/harness/mission-runner.js +53 -0
  201. package/dist/harness/mission-store.d.ts +93 -0
  202. package/dist/harness/mission-store.js +297 -0
  203. package/dist/harness/tool-harness.d.ts +56 -0
  204. package/dist/harness/tool-harness.js +153 -0
  205. package/dist/hooks/use-enhanced-input.js +48 -4
  206. package/dist/hooks/use-input-handler.d.ts +1 -0
  207. package/dist/hooks/use-input-handler.js +82 -22
  208. package/dist/hooks/use-input-history.js +1 -0
  209. package/dist/identity/lisa-introspection.js +5 -2
  210. package/dist/identity/operational-self-model.d.ts +2 -0
  211. package/dist/identity/operational-self-model.js +4 -0
  212. package/dist/index.js +52 -6
  213. package/dist/mcp/client.js +6 -0
  214. package/dist/mcp/config.d.ts +20 -0
  215. package/dist/mcp/config.js +121 -8
  216. package/dist/mcp/import-normalize.d.ts +12 -0
  217. package/dist/mcp/import-normalize.js +114 -0
  218. package/dist/mcp/transports.d.ts +10 -5
  219. package/dist/mcp/transports.js +61 -99
  220. package/dist/mcp/types.d.ts +5 -0
  221. package/dist/media/comfyui-recipe-contract.d.ts +7 -7
  222. package/dist/memory/facts-memory.d.ts +11 -1
  223. package/dist/memory/facts-memory.js +47 -8
  224. package/dist/memory/memory-candidate-queue.d.ts +2 -2
  225. package/dist/memory/memory-candidate-queue.js +6 -6
  226. package/dist/memory/persistent-memory.d.ts +13 -8
  227. package/dist/memory/persistent-memory.js +77 -30
  228. package/dist/nodes/device-node.js +5 -9
  229. package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
  230. package/dist/observability/run-event-writer.d.ts +21 -0
  231. package/dist/observability/run-event-writer.js +81 -0
  232. package/dist/observability/run-store.d.ts +5 -0
  233. package/dist/observability/run-store.js +18 -13
  234. package/dist/observability/run-trajectory.js +1 -1
  235. package/dist/optimization/prompt-cache.d.ts +19 -2
  236. package/dist/optimization/prompt-cache.js +41 -6
  237. package/dist/orchestration/orchestrator.d.ts +21 -0
  238. package/dist/orchestration/orchestrator.js +122 -15
  239. package/dist/persistence/session-content.d.ts +8 -0
  240. package/dist/persistence/session-content.js +76 -0
  241. package/dist/persistence/session-handoff.d.ts +64 -0
  242. package/dist/persistence/session-handoff.js +80 -0
  243. package/dist/persistence/session-history.d.ts +4 -0
  244. package/dist/persistence/session-history.js +38 -0
  245. package/dist/persistence/session-store.d.ts +9 -0
  246. package/dist/persistence/session-store.js +48 -20
  247. package/dist/personas/persona-manager.js +17 -1
  248. package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
  249. package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
  250. package/dist/plugins/plugin-manager.js +10 -1
  251. package/dist/prompts/prompt-manager.js +11 -4
  252. package/dist/prompts/system-base.js +6 -2
  253. package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
  254. package/dist/protocols/a2a/codebuddy-executor.js +9 -8
  255. package/dist/protocols/a2a/index.d.ts +1 -1
  256. package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
  257. package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
  258. package/dist/protocols/a2a/peer-config.d.ts +20 -0
  259. package/dist/protocols/a2a/peer-config.js +55 -0
  260. package/dist/providers/codex-oauth.js +30 -6
  261. package/dist/providers/model-provider-compat.js +2 -1
  262. package/dist/sandbox/os-sandbox.d.ts +1 -1
  263. package/dist/scheduler/cron-scheduler.d.ts +15 -2
  264. package/dist/scheduler/cron-scheduler.js +35 -4
  265. package/dist/scheduler/job-notepad.d.ts +69 -0
  266. package/dist/scheduler/job-notepad.js +339 -0
  267. package/dist/security/audit-logger.d.ts +1 -1
  268. package/dist/security/compute-confinement.d.ts +4 -0
  269. package/dist/security/compute-confinement.js +89 -0
  270. package/dist/security/session-encryption.d.ts +4 -0
  271. package/dist/security/session-encryption.js +31 -0
  272. package/dist/sensory/voice-loop.d.ts +17 -0
  273. package/dist/sensory/voice-loop.js +72 -15
  274. package/dist/server/auth/device-session-context.d.ts +9 -0
  275. package/dist/server/auth/device-session-context.js +13 -0
  276. package/dist/server/auth/device-store.d.ts +89 -0
  277. package/dist/server/auth/device-store.js +261 -0
  278. package/dist/server/auth/device-token.d.ts +3 -0
  279. package/dist/server/auth/device-token.js +6 -0
  280. package/dist/server/auth/jwt.js +4 -0
  281. package/dist/server/index.d.ts +0 -10
  282. package/dist/server/index.js +28 -0
  283. package/dist/server/middleware/auth.js +3 -2
  284. package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
  285. package/dist/server/routes/a2a-jsonrpc.js +66 -0
  286. package/dist/server/routes/a2a-protocol.d.ts +12 -0
  287. package/dist/server/routes/a2a-protocol.js +1 -1
  288. package/dist/server/routes/device-auth.d.ts +4 -0
  289. package/dist/server/routes/device-auth.js +40 -0
  290. package/dist/server/types.d.ts +4 -0
  291. package/dist/server/websocket/handler.d.ts +13 -0
  292. package/dist/server/websocket/handler.js +102 -17
  293. package/dist/services/prompt-builder.d.ts +2 -0
  294. package/dist/services/prompt-builder.js +13 -5
  295. package/dist/services/runtime-settings-context.d.ts +73 -0
  296. package/dist/services/runtime-settings-context.js +69 -0
  297. package/dist/skills/executor.js +2 -0
  298. package/dist/skills/hub.js +16 -14
  299. package/dist/skills/local-inventory.d.ts +21 -0
  300. package/dist/skills/local-inventory.js +72 -0
  301. package/dist/skills/skill-loader.js +2 -2
  302. package/dist/skills/skill-usage-store.d.ts +49 -0
  303. package/dist/skills/skill-usage-store.js +121 -0
  304. package/dist/testing/ai-integration-tests.js +8 -5
  305. package/dist/themes/theme-manager.d.ts +12 -0
  306. package/dist/themes/theme-manager.js +29 -0
  307. package/dist/themes/theme-schema.d.ts +24 -24
  308. package/dist/tools/a2a-call-tool.d.ts +34 -0
  309. package/dist/tools/a2a-call-tool.js +75 -0
  310. package/dist/tools/bash/streaming-executor.d.ts +1 -0
  311. package/dist/tools/bash/streaming-executor.js +78 -90
  312. package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
  313. package/dist/tools/code-exec-preflight-runner.js +254 -0
  314. package/dist/tools/code-exec-preflight.d.ts +44 -0
  315. package/dist/tools/code-exec-preflight.js +501 -0
  316. package/dist/tools/code-exec-tool.d.ts +48 -1
  317. package/dist/tools/code-exec-tool.js +191 -47
  318. package/dist/tools/comment-watcher.js +29 -12
  319. package/dist/tools/core-code-inspection.d.ts +56 -0
  320. package/dist/tools/core-code-inspection.js +86 -0
  321. package/dist/tools/create-skill-tool.d.ts +2 -3
  322. package/dist/tools/create-skill-tool.js +16 -75
  323. package/dist/tools/cronjob-tool.d.ts +1 -0
  324. package/dist/tools/cronjob-tool.js +1 -0
  325. package/dist/tools/env-doctor-tool.d.ts +2 -0
  326. package/dist/tools/env-doctor-tool.js +4 -3
  327. package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
  328. package/dist/tools/execute-code-rpc-invoker.js +35 -19
  329. package/dist/tools/execute-code-runner.d.ts +2 -0
  330. package/dist/tools/execute-code-runner.js +52 -17
  331. package/dist/tools/fleet-room-tool.d.ts +104 -0
  332. package/dist/tools/fleet-room-tool.js +124 -0
  333. package/dist/tools/integration-tool-hints.d.ts +4 -0
  334. package/dist/tools/integration-tool-hints.js +19 -0
  335. package/dist/tools/list-peers-tool.d.ts +3 -0
  336. package/dist/tools/list-peers-tool.js +11 -4
  337. package/dist/tools/media-generation-tool.d.ts +16 -1
  338. package/dist/tools/media-generation-tool.js +341 -9
  339. package/dist/tools/merge-conflict-tool.js +53 -25
  340. package/dist/tools/metadata.d.ts +1 -5
  341. package/dist/tools/metadata.js +21 -28
  342. package/dist/tools/ragchat-tool.d.ts +39 -0
  343. package/dist/tools/ragchat-tool.js +105 -0
  344. package/dist/tools/registry/fleet-tools.d.ts +9 -0
  345. package/dist/tools/registry/fleet-tools.js +22 -1
  346. package/dist/tools/registry/knowledge-tools.d.ts +2 -2
  347. package/dist/tools/registry/knowledge-tools.js +2 -2
  348. package/dist/tools/registry/lessons-tools.d.ts +7 -0
  349. package/dist/tools/registry/lessons-tools.js +43 -3
  350. package/dist/tools/registry/memory-tools.d.ts +1 -1
  351. package/dist/tools/registry/memory-tools.js +8 -8
  352. package/dist/tools/registry/research-tools.d.ts +1 -0
  353. package/dist/tools/registry/research-tools.js +4 -13
  354. package/dist/tools/registry/self-describe-tools.d.ts +1 -1
  355. package/dist/tools/registry/self-describe-tools.js +43 -30
  356. package/dist/tools/resource-catalog-tool.d.ts +38 -0
  357. package/dist/tools/resource-catalog-tool.js +46 -0
  358. package/dist/tools/skills-inspection-tool.js +30 -1
  359. package/dist/tools/stream-tool-output.d.ts +3 -0
  360. package/dist/tools/stream-tool-output.js +33 -0
  361. package/dist/tools/tool-call-scheduler.d.ts +10 -0
  362. package/dist/tools/tool-call-scheduler.js +58 -0
  363. package/dist/tools/tool-effect.d.ts +5 -0
  364. package/dist/tools/tool-effect.js +26 -0
  365. package/dist/tools/tool-search.d.ts +12 -11
  366. package/dist/tools/tool-search.js +67 -26
  367. package/dist/tools/types.d.ts +6 -0
  368. package/dist/ui/components/ChatHistory.d.ts +1 -1
  369. package/dist/ui/components/ChatHistory.js +2 -2
  370. package/dist/ui/components/ChatInput.d.ts +2 -1
  371. package/dist/ui/components/ChatInput.js +42 -88
  372. package/dist/ui/components/ChatInterface.d.ts +4 -2
  373. package/dist/ui/components/ChatInterface.js +27 -63
  374. package/dist/ui/components/CommandSuggestions.d.ts +0 -1
  375. package/dist/ui/components/CommandSuggestions.js +4 -6
  376. package/dist/ui/components/FileAutocomplete.js +1 -1
  377. package/dist/ui/components/KeyboardHelp.js +8 -6
  378. package/dist/ui/components/ModelSelection.js +6 -5
  379. package/dist/ui/components/StatusBar.d.ts +2 -1
  380. package/dist/ui/components/StatusBar.js +8 -7
  381. package/dist/ui/context/theme-context.js +3 -2
  382. package/dist/ui/index.d.ts +1 -1
  383. package/dist/ui/index.js +1 -1
  384. package/dist/ui/utils/markdown-renderer.js +4 -13
  385. package/dist/utils/atomic-write.d.ts +22 -0
  386. package/dist/utils/atomic-write.js +29 -0
  387. package/dist/utils/bounded-output.d.ts +16 -0
  388. package/dist/utils/bounded-output.js +63 -0
  389. package/dist/utils/device-store-file.d.ts +4 -0
  390. package/dist/utils/device-store-file.js +40 -0
  391. package/dist/utils/export-manager.d.ts +9 -0
  392. package/dist/utils/export-manager.js +19 -0
  393. package/dist/utils/first-use-hints.d.ts +25 -0
  394. package/dist/utils/first-use-hints.js +58 -0
  395. package/dist/utils/history-manager.js +1 -1
  396. package/dist/utils/update-notifier.js +16 -18
  397. package/dist/wizard/environment-detection.d.ts +5 -1
  398. package/dist/wizard/environment-detection.js +49 -7
  399. package/dist/wizard/onboarding.d.ts +5 -1
  400. package/dist/wizard/onboarding.js +90 -30
  401. package/dist/wizard/provider-onboarding.d.ts +2 -0
  402. package/dist/wizard/provider-onboarding.js +55 -17
  403. package/package.json +7 -3
@@ -8,7 +8,8 @@ import { buildDispatchToolFilter, getDispatchToolPolicy, normalizeDispatchProfil
8
8
  import { getBuiltinToolNames } from '../../codebuddy/tools.js';
9
9
  import { buildBrowserOperatorSessionDraft, buildInternetScoutPlan, renderBrowserOperatorSessionDraft, renderInternetScoutPlan, } from '../../browser-automation/index.js';
10
10
  import { installResearchScriptSkillCandidate, listMaterializedResearchScriptSkillCandidates, readMaterializedResearchScriptSkillCandidate, } from '../../agent/research-script-skill-candidate.js';
11
- import { getActiveToolMetadata, resolveToolEffect } from '../../tools/metadata.js';
11
+ import { getActiveToolMetadata } from '../../tools/metadata.js';
12
+ import { resolveToolEffect } from '../../tools/tool-effect.js';
12
13
  function formatList(values) {
13
14
  return values.length > 0 ? values.join(', ') : 'none';
14
15
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * buddy triage — write a local, redacted support bundle (src/doctor/triage.ts).
3
+ *
4
+ * Never sends anything and never launches an agent: the command to hand the
5
+ * prompt to a local agent is printed for the user to review and run.
6
+ */
7
+ import type { Command } from 'commander';
8
+ export declare function registerTriageCommand(program: Command): void;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * buddy triage — write a local, redacted support bundle (src/doctor/triage.ts).
3
+ *
4
+ * Never sends anything and never launches an agent: the command to hand the
5
+ * prompt to a local agent is printed for the user to review and run.
6
+ */
7
+ import { readFileSync } from 'node:fs';
8
+ import { dirname, join, resolve } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ function buddyVersion() {
11
+ try {
12
+ const here = dirname(fileURLToPath(import.meta.url));
13
+ for (const candidate of [join(here, '..', '..', '..', 'package.json'), join(here, '..', '..', 'package.json')]) {
14
+ try {
15
+ const pkg = JSON.parse(readFileSync(candidate, 'utf8'));
16
+ if (pkg.version && pkg.name?.includes('buddy'))
17
+ return pkg.version;
18
+ }
19
+ catch { /* try next */ }
20
+ }
21
+ }
22
+ catch { /* fall through */ }
23
+ return 'unknown';
24
+ }
25
+ export function registerTriageCommand(program) {
26
+ program
27
+ .command('triage')
28
+ .description('Write a local redacted support bundle and a ≤ 8 KiB prompt (no network, launches nothing)')
29
+ .option('--json', 'Print a JSON summary on stdout')
30
+ .option('--out <dir>', 'Parent directory for the bundle (default ~/.codebuddy/triage)')
31
+ .option('--log-lines <n>', 'Maximum log lines to include', '200')
32
+ .action(async (options) => {
33
+ const { writeTriageBundle } = await import('../../doctor/triage.js');
34
+ const directory = program.opts().directory;
35
+ const cwd = resolve(process.cwd(), directory || process.cwd());
36
+ const logLines = Math.max(0, Math.min(2000, Number.parseInt(options.logLines ?? '200', 10) || 0));
37
+ try {
38
+ const result = await writeTriageBundle({
39
+ cwd,
40
+ ...(options.out ? { outParent: resolve(process.cwd(), options.out) } : {}),
41
+ logLines,
42
+ buddyVersion: buddyVersion(),
43
+ });
44
+ if (options.json) {
45
+ console.log(JSON.stringify({
46
+ dir: result.dir,
47
+ files: { json: result.jsonPath, prompt: result.promptPath },
48
+ promptBytes: result.promptBytes,
49
+ redactions: result.redactions,
50
+ withheld: result.withheld,
51
+ networkUsed: false,
52
+ agentLaunched: false,
53
+ suggestedCommand: result.suggestedCommand,
54
+ }, null, 2));
55
+ return;
56
+ }
57
+ console.log('\nCode Buddy triage (local only — nothing was sent, no agent was started)\n');
58
+ console.log(` Bundle : ${result.dir}`);
59
+ console.log(` Prompt : ${result.promptPath} (${result.promptBytes} bytes)`);
60
+ console.log(` Redactions : ${result.redactions}`);
61
+ if (result.withheld.length > 0)
62
+ console.log(` Withheld : ${result.withheld.join(', ')} (secret scan still matched)`);
63
+ console.log('\nReview prompt.md, then hand it to a local agent yourself:');
64
+ console.log(` ${result.suggestedCommand}\n`);
65
+ }
66
+ catch (error) {
67
+ console.error(`triage failed: ${error instanceof Error ? error.message : String(error)}`);
68
+ process.exitCode = 1;
69
+ }
70
+ });
71
+ }
72
+ //# sourceMappingURL=triage-command.js.map
@@ -19,9 +19,31 @@ export function registerUtilityCommands(program) {
19
19
  .description('Diagnose Code Buddy environment, dependencies, and configuration')
20
20
  .option('-v, --verbose', 'Show all checks including passing ones')
21
21
  .option('--fix', 'Auto-fix issues that can be resolved automatically')
22
+ .option('--json', 'Print a stable JSON report (includes the Integrations section)')
23
+ .option('--offline', 'Skip every network call (live key checks, OAuth refresh, local runtime probes)')
24
+ .option('--integrations', 'Also check LM Resizer, Code Explorer, MCP config, resource catalog and skills (no network)')
22
25
  .action(async (options) => {
23
26
  const { runDoctorChecks, runFixes, summarizeDoctorChecks } = await import('../../doctor/index.js');
24
- const checks = await runDoctorChecks(resolveCommandDirectory(program));
27
+ const cwd = resolveCommandDirectory(program);
28
+ const offline = options.offline === true;
29
+ const coreChecks = await runDoctorChecks(cwd, { offline });
30
+ const withIntegrations = options.json === true || options.integrations === true;
31
+ const integrationChecks = withIntegrations
32
+ ? await (await import('../../doctor/integrations.js')).runIntegrationChecks(cwd)
33
+ : [];
34
+ const checks = [...coreChecks, ...integrationChecks];
35
+ if (options.json) {
36
+ const { buildDoctorJsonReport } = await import('../../doctor/integrations.js');
37
+ const fixes = options.fix ? await runFixes(checks.filter((c) => c.fixable)) : undefined;
38
+ const summary = summarizeDoctorChecks(checks);
39
+ const report = buildDoctorJsonReport(checks, summary, { offline, ...(fixes ? { fixes } : {}) });
40
+ console.log(JSON.stringify(report, null, 2));
41
+ const readinessJson = checks.find((c) => c.name === 'AI provider ready');
42
+ if (summary.errors > 0 || (readinessJson && readinessJson.status !== 'ok') || fixes?.some((f) => !f.success)) {
43
+ process.exitCode = 1;
44
+ }
45
+ return;
46
+ }
25
47
  console.log('\n🔍 Code Buddy Doctor\n');
26
48
  const icons = { ok: '✅', warn: '⚠️', error: '❌' };
27
49
  // Headline verdict: the first question a newcomer has is "can I chat yet?"
@@ -39,6 +61,8 @@ export function registerUtilityCommands(program) {
39
61
  for (const check of checks) {
40
62
  if (check.name === 'AI provider ready')
41
63
  continue; // already shown as the headline
64
+ if (integrationChecks.length > 0 && check === integrationChecks[0])
65
+ console.log('\n Integrations (no network):');
42
66
  if (options.verbose || check.status !== 'ok') {
43
67
  const fixTag = check.fixable ? ' [fixable]' : '';
44
68
  console.log(` ${icons[check.status]} ${check.name}: ${check.message}${fixTag}`);
@@ -37,6 +37,13 @@ export declare class ClientCommandDispatcher {
37
37
  * result handling (add entry to chat, pass prompt to AI, clear input).
38
38
  */
39
39
  private static delegateToEnhanced;
40
+ /** Session-only /switch overrides, keyed by the live agent. */
41
+ private static readonly switchState;
42
+ /**
43
+ * Back /switch with the running agent so it changes the model used by the
44
+ * next turns (session only, unlike /model which also saves the preference).
45
+ */
46
+ private static createSwitchModelProvider;
40
47
  private static handleEnhancedCommand;
41
48
  private static handleModelSwitch;
42
49
  private static handleShellBypass;
@@ -3,7 +3,9 @@ import { getEnhancedCommandHandler } from "./enhanced-command-handler.js";
3
3
  import { GitWorkflowHandler } from "./workflow/git-workflow.js";
4
4
  import { getErrorMessage } from "../types/index.js";
5
5
  import { ConfirmationService } from "../utils/confirmation-service.js";
6
+ import { isModelCompatibleWithProvider } from "../providers/model-provider-compat.js";
6
7
  import { updateCurrentModel } from "../utils/model-config.js";
8
+ import { setSwitchModelProvider } from "./handlers/switch-handler.js";
7
9
  export class ClientCommandDispatcher {
8
10
  /**
9
11
  * Dispatches a command input to the appropriate handler.
@@ -48,6 +50,8 @@ export class ClientCommandDispatcher {
48
50
  context.clearInput();
49
51
  }
50
52
  static async handleSlashCommand(input, context) {
53
+ // Keep the historical plural spelling on the same live-agent path.
54
+ input = input.replace(/^\/models(?=\s|$)/, '/model');
51
55
  const slashManager = getSlashCommandManager();
52
56
  const result = slashManager.execute(input);
53
57
  if (result.success && result.prompt) {
@@ -108,18 +112,22 @@ export class ClientCommandDispatcher {
108
112
  const args = originalInput.trim().split(/\s+/).slice(1);
109
113
  if (args.length === 0) {
110
114
  context.setShowModelSelection(true);
111
- context.setSelectedModelIndex(0);
115
+ context.setSelectedModelIndex(Math.max(0, context.availableModels.findIndex(option => option.model === context.agent.getCurrentModel())));
112
116
  context.clearInput();
113
117
  return true;
114
118
  }
115
- // With args, delegate to enhanced handler for model switching
116
- return await this.delegateToEnhanced(token, originalInput, context);
119
+ if (args[0] === 'auto' || args[0] === 'list') {
120
+ return await this.delegateToEnhanced(token, originalInput, context);
121
+ }
122
+ await this.handleModelSwitch(originalInput, context);
123
+ return true;
117
124
  }
118
125
  // __CLEAR_CHAT__ needs UI state resets beyond what the handler provides
119
126
  if (token === "__CLEAR_CHAT__") {
120
127
  const handled = await this.delegateToEnhanced(token, originalInput, context);
121
128
  if (handled) {
122
129
  // Apply UI-specific side effects
130
+ context.agent.clearChat();
123
131
  context.setChatHistory([]);
124
132
  context.setIsProcessing(false);
125
133
  context.setIsStreaming(false);
@@ -149,11 +157,13 @@ export class ClientCommandDispatcher {
149
157
  getContextStats: () => context.agent.getContextStats(),
150
158
  formatContextStats: () => context.agent.formatContextStats(),
151
159
  getCurrentModel: () => context.agent.getCurrentModel(),
160
+ getMemoryScope: () => context.agent.getMemoryScope(),
152
161
  getCurrentSessionId: () => context.agent.getCurrentSessionId?.() ?? null,
153
162
  getContextMemoryMetrics: () => context.agent.getContextMemoryMetrics(),
154
163
  getCompressionStats: () => context.agent.getCompressionStats(),
155
164
  getContextBudgetBreakdown: () => context.agent.getContextBudgetBreakdown(),
156
165
  });
166
+ setSwitchModelProvider(this.createSwitchModelProvider(context));
157
167
  const args = overrideArgs ?? originalInput.trim().split(" ").slice(1);
158
168
  const handlerResult = await enhancedHandler.handleCommand(token, args, originalInput);
159
169
  if (handlerResult.handled) {
@@ -173,30 +183,72 @@ export class ClientCommandDispatcher {
173
183
  this.finishCommandWithMessage(context, `Command ${commandName} is registered but has no conversation-loop handler yet. Use /help to see working commands.`);
174
184
  return true;
175
185
  }
186
+ /** Session-only /switch overrides, keyed by the live agent. */
187
+ static switchState = new WeakMap();
188
+ /**
189
+ * Back /switch with the running agent so it changes the model used by the
190
+ * next turns (session only, unlike /model which also saves the preference).
191
+ */
192
+ static createSwitchModelProvider(context) {
193
+ const agent = context.agent;
194
+ const state = () => {
195
+ let current = this.switchState.get(agent);
196
+ if (!current) {
197
+ current = { baseModel: agent.getCurrentModel(), switched: null };
198
+ this.switchState.set(agent, current);
199
+ }
200
+ return current;
201
+ };
202
+ return {
203
+ getAvailableModels: () => context.availableModels.map(option => option.model),
204
+ getCurrentModel: () => agent.getCurrentModel(),
205
+ getSwitchedModel: () => this.switchState.get(agent)?.switched ?? null,
206
+ setSwitchedModel: (model) => {
207
+ const current = state();
208
+ if (model === null) {
209
+ if (current.switched !== null)
210
+ agent.setModel(current.baseModel);
211
+ this.switchState.delete(agent);
212
+ return;
213
+ }
214
+ const provider = agent.getClient().getCurrentProvider?.();
215
+ if (!isModelCompatibleWithProvider(model, provider)) {
216
+ throw new Error(`Model ${model} is incompatible with the active provider ${provider}. Choose a model for this connection.`);
217
+ }
218
+ agent.setModel(model);
219
+ current.switched = model;
220
+ },
221
+ };
222
+ }
176
223
  static async handleEnhancedCommand(token, originalInput, context) {
177
224
  return await this.delegateToEnhanced(token, originalInput, context);
178
225
  }
179
226
  static async handleModelSwitch(input, context) {
180
- const modelArg = input.trim().split(" ")[1];
181
- const modelNames = context.availableModels.map((m) => m.model);
182
- if (modelArg !== undefined && modelNames.includes(modelArg)) {
183
- context.agent.setModel(modelArg);
184
- updateCurrentModel(modelArg);
185
- const confirmEntry = {
186
- type: "assistant",
187
- content: `✓ Switched to model: ${modelArg}`,
188
- timestamp: new Date(),
189
- };
190
- context.setChatHistory((prev) => [...prev, confirmEntry]);
227
+ const args = input.trim().split(/\s+/).slice(1);
228
+ const model = args[0];
229
+ if (!model || args.length !== 1) {
230
+ this.finishCommandWithMessage(context, 'Usage: /model <model-name>');
231
+ return;
191
232
  }
192
- else {
193
- const errorEntry = {
194
- type: "assistant",
195
- content: `Invalid model: ${modelArg}\n\nAvailable models: ${modelNames.join(", ")}`,
196
- timestamp: new Date(),
197
- };
198
- context.setChatHistory((prev) => [...prev, errorEntry]);
233
+ const provider = context.agent.getClient().getCurrentProvider?.();
234
+ if (!isModelCompatibleWithProvider(model, provider)) {
235
+ this.finishCommandWithMessage(context, `Model ${model} is incompatible with the active provider ${provider}. Choose a model for this connection.`);
236
+ return;
237
+ }
238
+ // Change the running client and its context/token limits before announcing success.
239
+ context.agent.setModel(model);
240
+ // An explicit /model choice becomes the new base for later /switch auto.
241
+ this.switchState.delete(context.agent);
242
+ try {
243
+ updateCurrentModel(model);
244
+ }
245
+ catch (error) {
246
+ this.finishCommandWithMessage(context, `Model active for this session: ${model}. Could not save the preference: ${getErrorMessage(error)}`);
247
+ return;
199
248
  }
249
+ context.setChatHistory(prev => [...prev, {
250
+ type: 'assistant', content: `Switched to model: ${model}`, timestamp: new Date(),
251
+ }]);
200
252
  context.clearInput();
201
253
  }
202
254
  static async handleShellBypass(command, context) {
@@ -38,6 +38,7 @@ export interface CronAddOptions {
38
38
  /** Job-level chain target: id (or id prefix) to run on successful completion. */
39
39
  then?: string;
40
40
  preCheck?: string;
41
+ continuity?: string;
41
42
  deliver?: string[];
42
43
  format?: string;
43
44
  }
@@ -56,9 +57,10 @@ export interface CronJobSpec {
56
57
  task: CronJob['task'];
57
58
  delivery?: CronJob['delivery'];
58
59
  preCheck?: CronJob['preCheck'];
60
+ continuity?: CronJob['continuity'];
59
61
  then?: string;
60
62
  }
61
- export type CronJobUpdates = Partial<Pick<CronJob, 'name' | 'type' | 'schedule' | 'task' | 'delivery' | 'preCheck' | 'then'>>;
63
+ export type CronJobUpdates = Partial<Pick<CronJob, 'name' | 'type' | 'schedule' | 'task' | 'delivery' | 'preCheck' | 'then' | 'continuity'>>;
62
64
  export type CronJobSpecResult = {
63
65
  spec: CronJobSpec;
64
66
  } | {
@@ -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));