@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
@@ -1,6 +1,7 @@
1
1
  import * as readline from 'readline';
2
2
  import { spawn } from 'child_process';
3
- import { mkdirSync, writeFileSync } from 'fs';
3
+ import { existsSync, readFileSync, mkdirSync } from 'fs';
4
+ import { writeJsonAtomicSync } from '../utils/atomic-write.js';
4
5
  import { isAbsolute, join, resolve } from 'path';
5
6
  import { getValidationConfigForGuide, validateProviderKey, } from './provider-onboarding.js';
6
7
  import { detectEnvironment, renderDetectionSummary, } from './environment-detection.js';
@@ -165,31 +166,39 @@ export const ONBOARDING_PHASES = [
165
166
  successCheck: 'the selected layer has a doctor/status command or a focused smoke prompt.',
166
167
  },
167
168
  ];
168
- const TTS_PROVIDERS = ['pocket', 'elevenlabs', 'piper'];
169
+ const TTS_PROVIDERS = ['piper', 'espeak', 'say', 'audioreader'];
170
+ class OnboardingCancelled extends Error {
171
+ }
169
172
  function ask(rl, question, defaultValue) {
170
- return new Promise((resolve) => {
173
+ return new Promise((resolve, reject) => {
174
+ const onClose = () => reject(new OnboardingCancelled('Setup cancelled.'));
175
+ rl.once('close', onClose);
171
176
  const suffix = defaultValue ? ` [${defaultValue}]` : '';
172
177
  rl.question(` ${question}${suffix}: `, (answer) => {
178
+ rl.removeListener('close', onClose);
173
179
  resolve(answer.trim() || defaultValue || '');
174
180
  });
175
181
  });
176
182
  }
177
- function askChoice(rl, question, choices, defaultIdx) {
178
- return new Promise((resolve) => {
179
- console.log(`\n ${question}`);
180
- choices.forEach((c, i) => console.log(` ${i + 1}. ${c}${i === defaultIdx ? ' (default)' : ''}`));
181
- rl.question(` Choice [${defaultIdx + 1}]: `, (answer) => {
182
- const idx = parseInt(answer) - 1;
183
- const selectedIdx = idx >= 0 && idx < choices.length ? idx : defaultIdx;
184
- resolve(choices[selectedIdx] ?? choices[0] ?? '');
185
- });
186
- });
183
+ async function askChoice(rl, question, choices, defaultIdx) {
184
+ console.log(`\n ${question}`);
185
+ choices.forEach((c, i) => console.log(` ${i + 1}. ${c}${i === defaultIdx ? ' (default)' : ''}`));
186
+ while (true) {
187
+ const answer = await ask(rl, 'Choice', String(defaultIdx + 1));
188
+ const idx = Number(answer) - 1;
189
+ if (/^\d+$/.test(answer) && Number.isInteger(idx) && idx >= 0 && idx < choices.length) {
190
+ return choices[idx];
191
+ }
192
+ console.log(` Please enter a number from 1 to ${choices.length}.`);
193
+ }
187
194
  }
188
195
  /** Read a secret without echoing it (masks keystrokes with '*'). The captured
189
196
  * value is always correct regardless of echo; masking is cosmetic, and falls
190
197
  * back to a visible prompt if the terminal doesn't support muting. */
191
198
  function askSecret(rl, question) {
192
- return new Promise((resolve) => {
199
+ return new Promise((resolve, reject) => {
200
+ const onClose = () => reject(new OnboardingCancelled('Setup cancelled.'));
201
+ rl.once('close', onClose);
193
202
  const rlAny = rl;
194
203
  const original = rlAny._writeToOutput?.bind(rl);
195
204
  let muted = false;
@@ -202,6 +211,7 @@ function askSecret(rl, question) {
202
211
  };
203
212
  }
204
213
  rl.question(` ${question}: `, (answer) => {
214
+ rl.removeListener('close', onClose);
205
215
  if (typeof original === 'function')
206
216
  rlAny._writeToOutput = original;
207
217
  resolve(answer.trim());
@@ -216,10 +226,10 @@ function askSecret(rl, question) {
216
226
  * - an entered API key → encrypted credential store (never plaintext in settings),
217
227
  * plus `process.env[envVar]` so the current process resolves immediately.
218
228
  * - ollama → default `OLLAMA_HOST` so auto-detection picks it up.
219
- * All writes are best-effort; the wizard summary still prints on failure.
229
+ * Persistence errors propagate so the wizard cannot report a false success.
220
230
  */
221
231
  export async function persistProviderSelection(guide, model, apiKey) {
222
- try {
232
+ {
223
233
  const { getSettingsManager } = await import('../utils/settings-manager.js');
224
234
  getSettingsManager().saveUserSettings({
225
235
  provider: guide.id,
@@ -229,13 +239,11 @@ export async function persistProviderSelection(guide, model, apiKey) {
229
239
  ...(guide.baseURL ? { baseURL: guide.baseURL } : {}),
230
240
  });
231
241
  }
232
- catch { /* non-fatal */ }
233
242
  if (guide.authMode === 'api-key' && apiKey) {
234
- try {
243
+ {
235
244
  const { getCredentialManager } = await import('../security/credential-manager.js');
236
245
  getCredentialManager().setApiKey(apiKey);
237
246
  }
238
- catch { /* non-fatal */ }
239
247
  if (guide.envVar)
240
248
  process.env[guide.envVar] = apiKey;
241
249
  }
@@ -255,7 +263,13 @@ export function writeConfig(configDir, result) {
255
263
  mkdirSync(configDir, { recursive: true });
256
264
  const authMode = result.authMode ?? getProviderGuide(result.provider).authMode;
257
265
  const recommendedNextCommands = result.recommendedNextCommands ?? buildRecommendedNextCommands(result);
266
+ const configPath = join(configDir, 'config.json');
267
+ const previous = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf8')) : {};
268
+ if (!previous || typeof previous !== 'object' || Array.isArray(previous)) {
269
+ throw new Error('Existing project config must be a JSON object; it was not overwritten.');
270
+ }
258
271
  const config = {
272
+ ...previous,
259
273
  provider: result.provider,
260
274
  model: result.model,
261
275
  authMode,
@@ -269,7 +283,9 @@ export function writeConfig(configDir, result) {
269
283
  if (result.ttsProvider) {
270
284
  config.ttsProvider = result.ttsProvider;
271
285
  }
272
- writeFileSync(join(configDir, 'config.json'), JSON.stringify(config, null, 2) + '\n');
286
+ if (!result.ttsEnabled)
287
+ delete config.ttsProvider;
288
+ writeJsonAtomicSync(configPath, config);
273
289
  }
274
290
  export function getProviderGuide(provider) {
275
291
  return (PROVIDER_GUIDES.find((guide) => guide.id === provider)
@@ -460,7 +476,7 @@ async function runQuickStart(rl, snapshot, projectDir) {
460
476
  const free = snapshot.recommendedFree;
461
477
  const ollama = snapshot.capabilities.find((c) => c.id === 'ollama');
462
478
  // Case A: a ready free path exists — offer it directly.
463
- if (free) {
479
+ if (free && PROVIDER_GUIDES.some((guide) => guide.id === free.id)) {
464
480
  const answer = (await ask(rl, `Start now on ${free.label} — free, no API key needed? (Y/n)`, 'y')).toLowerCase();
465
481
  if (answer === 'y' || answer === 'yes' || answer === '') {
466
482
  const guide = getProviderGuide(free.id);
@@ -514,17 +530,40 @@ function finishQuickStart(provider, model, baseURL, projectDir) {
514
530
  }
515
531
  /** Offer to run the isolated 60-second demo right after setup — ending the
516
532
  * wizard on proof (a green test), not prose. */
517
- async function offerTry(rl) {
533
+ export async function offerOnboardingDemo(rl, result) {
534
+ if (!['chatgpt', 'ollama', 'lmstudio'].includes(result.provider)) {
535
+ console.log(' Verify this provider with the first-chat command below.');
536
+ return;
537
+ }
518
538
  const answer = (await ask(rl, 'Run the 60-second demo now to confirm it works? (Y/n)', 'y')).toLowerCase();
519
539
  if (answer === 'y' || answer === 'yes' || answer === '') {
520
540
  try {
521
541
  const { runTryDemo } = await import('../commands/try.js');
522
542
  rl.pause();
523
- await runTryDemo();
524
- rl.resume();
543
+ const { getSettingsManager } = await import('../utils/settings-manager.js');
544
+ const code = await runTryDemo({
545
+ verbose: false,
546
+ resolveProvider: async () => ({
547
+ kind: result.provider === 'chatgpt' ? 'chatgpt' : 'ollama',
548
+ label: `${result.provider} (${result.model})`,
549
+ apiKey: result.provider === 'chatgpt' ? 'oauth-chatgpt' : 'local',
550
+ baseURL: result.provider === 'chatgpt'
551
+ ? 'https://chatgpt.com/backend-api/codex'
552
+ : getSettingsManager().getBaseURL(),
553
+ model: result.model,
554
+ }),
555
+ });
556
+ if (code !== 0) {
557
+ process.exitCode = code;
558
+ console.log(' Setup saved, but the demo failed. First chat is not verified.');
559
+ }
525
560
  }
526
561
  catch {
527
- console.log('\n Run it yourself anytime with: buddy try\n');
562
+ process.exitCode = 1;
563
+ console.log('\n The demo failed. First chat is not verified.\n');
564
+ }
565
+ finally {
566
+ rl.resume();
528
567
  }
529
568
  }
530
569
  else {
@@ -562,7 +601,7 @@ export async function runOnboarding() {
562
601
  if (quick) {
563
602
  console.log(renderCapabilitiesFooter());
564
603
  console.log('');
565
- await offerTry(rl);
604
+ await offerOnboardingDemo(rl, quick);
566
605
  return quick;
567
606
  }
568
607
  console.log(renderOnboardingRoadmap());
@@ -571,8 +610,15 @@ export async function runOnboarding() {
571
610
  // default lands on the recommended free path when there is one.
572
611
  const orderedGuides = orderGuidesByDetection(snapshot);
573
612
  const provider = await askChoice(rl, 'Which AI provider do you want to use?', orderedGuides.map((guide) => `${guide.id} — ${guide.label}`), 0).then((choice) => choice.split(/\s+—\s+/)[0] ?? choice);
574
- const guide = getProviderGuide(provider);
575
- const validationConfig = getValidationConfigForGuide(provider);
613
+ const selectedGuide = getProviderGuide(provider);
614
+ const detected = snapshot.capabilities.find((capability) => capability.id === provider);
615
+ const guide = selectedGuide.authMode === 'local' && detected?.baseURL
616
+ ? { ...selectedGuide, baseURL: detected.baseURL }
617
+ : selectedGuide;
618
+ const defaultValidation = getValidationConfigForGuide(provider);
619
+ const validationConfig = guide.authMode === 'local' && guide.baseURL && defaultValidation
620
+ ? { ...defaultValidation, baseUrl: guide.baseURL.replace(/\/v1\/?$/, '') }
621
+ : defaultValidation;
576
622
  // 2. Authentication — captured AND verified inline so you leave the wizard
577
623
  // ready to chat. A rejected key never gets persisted; a successful probe
578
624
  // also hands us the provider's real model list for step 3.
@@ -651,10 +697,18 @@ export async function runOnboarding() {
651
697
  recommendedNextCommands: buildRecommendedNextCommands({ provider, apiKey, model }),
652
698
  ...(ttsProvider ? { ttsProvider } : {}),
653
699
  };
700
+ {
701
+ const { getTTSManager } = await import('../input/text-to-speech.js');
702
+ getTTSManager().updateConfig({
703
+ enabled: ttsEnabled,
704
+ autoSpeak: ttsEnabled,
705
+ ...(ttsProvider ? { provider: ttsProvider } : {}),
706
+ });
707
+ }
654
708
  // 6. Write project config into the folder the user chose
655
709
  applyOnboardingProjectConfig(projectDir, result);
656
710
  // 7. Summary
657
- const ready = verified || (guide.authMode === 'api-key' && Boolean(apiKey));
711
+ const ready = verified;
658
712
  console.log('');
659
713
  console.log(` ${ready ? 'Setup complete — you\'re ready to go!' : 'Setup saved.'}`);
660
714
  console.log('');
@@ -688,10 +742,16 @@ export async function runOnboarding() {
688
742
  console.log('');
689
743
  // Close with a real, runnable test so the wizard ends on proof, not prose.
690
744
  if (ready) {
691
- await offerTry(rl);
745
+ await offerOnboardingDemo(rl, result);
692
746
  }
693
747
  return result;
694
748
  }
749
+ catch (error) {
750
+ if (!(error instanceof OnboardingCancelled))
751
+ throw error;
752
+ console.log('\n Setup cancelled.');
753
+ return null;
754
+ }
695
755
  finally {
696
756
  rl.close();
697
757
  }
@@ -19,6 +19,8 @@ export interface ProviderOnboardingConfig {
19
19
  baseUrl: string;
20
20
  /** GET endpoint to validate the key (relative to baseUrl) */
21
21
  validateEndpoint: string;
22
+ /** Optional public catalog, fetched only after authentication succeeds. */
23
+ modelsEndpoint?: string;
22
24
  /** User-facing instructions for obtaining an API key */
23
25
  instructions: string;
24
26
  }
@@ -57,7 +57,10 @@ export const PROVIDER_CONFIGS = [
57
57
  name: 'OpenRouter',
58
58
  envKey: 'OPENROUTER_API_KEY',
59
59
  baseUrl: 'https://openrouter.ai/api',
60
- validateEndpoint: '/v1/models',
60
+ // /models is public and cannot establish whether a key is valid.
61
+ // https://openrouter.ai/docs/api/api-reference/api-keys/get-current-api-key
62
+ validateEndpoint: '/v1/key',
63
+ modelsEndpoint: '/v1/models',
61
64
  instructions: 'Get your API key from https://openrouter.ai/keys',
62
65
  },
63
66
  {
@@ -153,33 +156,68 @@ export async function validateProviderKey(config, apiKey) {
153
156
  error: `API error (${response.status}): ${errorText.slice(0, 200)}`,
154
157
  };
155
158
  }
156
- // Extract model list from response
159
+ if (config.id === 'openrouter') {
160
+ let body;
161
+ try {
162
+ body = await response.json();
163
+ }
164
+ catch { /* invalid response below */ }
165
+ if (!isRecord(body) || !isRecord(body.data) || typeof body.data.label !== 'string') {
166
+ return { valid: false, error: `Invalid authentication response from ${config.name}` };
167
+ }
168
+ // The key is authenticated even if the optional model catalog is unavailable.
169
+ if (!config.modelsEndpoint)
170
+ return { valid: true };
171
+ try {
172
+ const catalog = await fetch(`${config.baseUrl}${config.modelsEndpoint}`, {
173
+ method: 'GET',
174
+ headers,
175
+ signal: AbortSignal.timeout(15000),
176
+ });
177
+ if (!catalog.ok)
178
+ return { valid: true };
179
+ const models = await extractModels(config, catalog);
180
+ return models === null ? { valid: true } : { valid: true, models };
181
+ }
182
+ catch {
183
+ return { valid: true };
184
+ }
185
+ }
157
186
  const models = await extractModels(config, response);
187
+ if (models === null) {
188
+ return { valid: false, error: `Invalid model-list response from ${config.name}` };
189
+ }
158
190
  return { valid: true, models };
159
191
  }
160
192
  /**
161
193
  * Parse the model list from a provider's validation response.
162
194
  */
195
+ function isRecord(value) {
196
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
197
+ }
163
198
  async function extractModels(config, response) {
164
199
  try {
165
- const data = await response.json();
166
- const body = data;
167
- if (config.id === 'ollama') {
168
- // Ollama: { models: [{ name: "llama3" }] }
169
- const models = body.models;
170
- return models?.map((m) => m.name) ?? [];
171
- }
172
- if (config.id === 'google') {
173
- // Gemini: { models: [{ name: "models/gemini-pro" }] }
174
- const models = body.models;
175
- return models?.map((m) => m.name.replace('models/', '')) ?? [];
200
+ const body = await response.json();
201
+ if (!isRecord(body))
202
+ return null;
203
+ const usesNames = config.id === 'ollama' || config.id === 'google';
204
+ const rows = usesNames ? body.models : body.data;
205
+ const field = usesNames ? 'name' : 'id';
206
+ if (!Array.isArray(rows))
207
+ return null;
208
+ const models = [];
209
+ for (const row of rows) {
210
+ if (!isRecord(row))
211
+ return null;
212
+ const value = row[field];
213
+ if (typeof value !== 'string' || !value.trim())
214
+ return null;
215
+ models.push(config.id === 'google' ? value.replace(/^models\//, '') : value);
176
216
  }
177
- // OpenAI-compatible: { data: [{ id: "gpt-4o" }] }
178
- const modelData = body.data;
179
- return modelData?.map((m) => m.id) ?? [];
217
+ return models;
180
218
  }
181
219
  catch {
182
- return [];
220
+ return null;
183
221
  }
184
222
  }
185
223
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@phuetz/code-buddy",
3
- "version": "2.0.0",
4
- "description": "Open-source AI coding agent for the terminal, desktop, and HTTP. 64 LLM providers (Claude, GPT, Grok, Gemini, Ollama, LM Studio, NVIDIA NIM, …), 30 of them free-tier or local $0, with automatic failover. 220+ tools selected per query, a peer-to-peer fleet, opt-in self-improvement, multi-channel messaging, and a skills system.",
3
+ "version": "2.1.0",
4
+ "description": "AI coding agent with terminal and HTTP interfaces, optional Cowork desktop integration, multi-provider routing, tools, fleet collaboration and inspectable memory. See release notes for supported integrations and limits.",
5
5
  "author": "Patrice Huetz <patrice.huetz@gmail.com>",
6
6
  "repository": {
7
7
  "type": "git",
@@ -17,6 +17,10 @@
17
17
  ],
18
18
  "main": "dist/index.js",
19
19
  "exports": {
20
+ "./harness": {
21
+ "types": "./dist/harness/index.d.ts",
22
+ "import": "./dist/harness/index.js"
23
+ },
20
24
  ".": {
21
25
  "import": "./dist/index.js",
22
26
  "types": "./dist/index.d.ts"
@@ -215,6 +219,7 @@
215
219
  "terminal-image": "^4.1.0",
216
220
  "tesseract.js": "^7.0.0",
217
221
  "tiktoken": "^1.0.22",
222
+ "typescript": "^5.9.3",
218
223
  "undici": "^6.28.0",
219
224
  "yaml": "^2.9.0",
220
225
  "youtube-caption-extractor": "^1.10.2",
@@ -275,7 +280,6 @@
275
280
  "semantic-release": "^25.0.3",
276
281
  "tsx": "^4.21.0",
277
282
  "typedoc": "^0.28.15",
278
- "typescript": "^5.9.3",
279
283
  "vitest": "^4.0.18",
280
284
  "vscode-languageserver": "^9.0.1",
281
285
  "vscode-languageserver-textdocument": "^1.0.12"