@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
@@ -5,6 +5,9 @@ import path from 'path';
5
5
  import { getImageGenerationModel } from '../config/agent-defaults.js';
6
6
  import { resolveToolGatewayRoute } from '../agent/tool-gateway-router.js';
7
7
  import { logger } from '../utils/logger.js';
8
+ import { getChatGptAuth, hasCodexCredentials, refreshChatGptAuth, } from '../providers/codex-oauth.js';
9
+ import { buildChatGptHeaders, CHATGPT_RESPONSES_URL, } from '../codebuddy/providers/chatgpt-headers.js';
10
+ import { CHATGPT_OAUTH_DEFAULT_MODEL } from '../providers/chatgpt-models.js';
8
11
  const IMAGE_SIZES = {
9
12
  landscape: '1536x1024',
10
13
  square: '1024x1024',
@@ -38,7 +41,7 @@ export async function generateImage(input, runtime = {}) {
38
41
  if (!prompt) {
39
42
  throw new Error('prompt is required for image generation');
40
43
  }
41
- const config = resolveImageProvider(runtime.env ?? process.env);
44
+ const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
42
45
  const aspect = resolveImageAspect(input.aspectRatio);
43
46
  const fetchImpl = runtime.fetch ?? fetch;
44
47
  const generatedAt = (runtime.now ?? (() => new Date()))().toISOString();
@@ -48,6 +51,9 @@ export async function generateImage(input, runtime = {}) {
48
51
  await ingestLisaSelfieIfNeeded(comfy, runtime);
49
52
  return comfy;
50
53
  }
54
+ if (config.provider === 'chatgpt') {
55
+ return generateChatGptImage(prompt, aspect, config, runtime, generatedAt);
56
+ }
51
57
  const size = IMAGE_SIZES[aspect];
52
58
  const body = {
53
59
  model: config.model,
@@ -155,7 +161,7 @@ export async function editImage(input, runtime = {}) {
155
161
  const imageUrl = validateImageReference(input.imageUrl, 'source image');
156
162
  const selections = normalizeEditSelections(input.selections);
157
163
  const maskUrl = input.maskUrl ? validateDataImage(input.maskUrl, 'mask') : undefined;
158
- const config = resolveImageProvider(runtime.env ?? process.env);
164
+ const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
159
165
  const fetchImpl = runtime.fetch ?? fetch;
160
166
  const generatedAt = (runtime.now ?? (() => new Date()))().toISOString();
161
167
  const selectionHint = selections.length > 0
@@ -174,6 +180,15 @@ export async function editImage(input, runtime = {}) {
174
180
  sourceRef: input.sourceRef,
175
181
  }, config, runtime, generatedAt);
176
182
  }
183
+ if (config.provider === 'chatgpt') {
184
+ return editChatGptImage({
185
+ prompt,
186
+ effectivePrompt,
187
+ imageUrl,
188
+ selections,
189
+ sourceRef: input.sourceRef,
190
+ }, config, runtime, generatedAt);
191
+ }
177
192
  let response;
178
193
  if (config.provider === 'xai') {
179
194
  response = await postJson(fetchImpl, joinUrl(config.baseUrl, '/images/edits'), {
@@ -264,6 +279,299 @@ export async function editImage(input, runtime = {}) {
264
279
  ...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
265
280
  };
266
281
  }
282
+ // ---------------------------------------------------------------------------
283
+ // ChatGPT Codex image backend ($0 subscription, gpt-image-2 via /responses).
284
+ // ---------------------------------------------------------------------------
285
+ export function parseChatGptImageResponse(text) {
286
+ const trimmed = text.trim();
287
+ if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
288
+ try {
289
+ const parsed = JSON.parse(trimmed);
290
+ if (parsed.error?.message) {
291
+ throw new Error(`ChatGPT error: ${parsed.error.message}`);
292
+ }
293
+ if (Array.isArray(parsed.data) && parsed.data[0]?.b64_json) {
294
+ return {
295
+ b64: parsed.data[0].b64_json,
296
+ revisedPrompt: parsed.data[0].revised_prompt,
297
+ };
298
+ }
299
+ if (parsed.item?.type === 'image_generation_call' && parsed.item.result) {
300
+ return {
301
+ b64: parsed.item.result,
302
+ revisedPrompt: parsed.item.revised_prompt,
303
+ };
304
+ }
305
+ }
306
+ catch (e) {
307
+ if (e instanceof Error && e.message.startsWith('ChatGPT'))
308
+ throw e;
309
+ }
310
+ }
311
+ let b64;
312
+ let revisedPrompt;
313
+ const lines = text.split('\n');
314
+ for (const rawLine of lines) {
315
+ const line = rawLine.trim();
316
+ if (!line.startsWith('data:'))
317
+ continue;
318
+ const dataStr = line.slice(5).trim();
319
+ if (!dataStr || dataStr === '[DONE]')
320
+ continue;
321
+ try {
322
+ const event = JSON.parse(dataStr);
323
+ if (event.error?.message) {
324
+ throw new Error(`ChatGPT image error: ${event.error.message}`);
325
+ }
326
+ if (event.type === 'response.failed' && event.response?.error?.message) {
327
+ throw new Error(`ChatGPT image response failed: ${event.response.error.message}`);
328
+ }
329
+ if (event.item?.type === 'image_generation_call') {
330
+ if (event.item.result)
331
+ b64 = event.item.result;
332
+ if (event.item.revised_prompt)
333
+ revisedPrompt = event.item.revised_prompt;
334
+ }
335
+ else if (Array.isArray(event.data) && event.data[0]?.b64_json) {
336
+ b64 = event.data[0].b64_json;
337
+ if (event.data[0].revised_prompt)
338
+ revisedPrompt = event.data[0].revised_prompt;
339
+ }
340
+ }
341
+ catch (e) {
342
+ if (e instanceof Error && e.message.startsWith('ChatGPT'))
343
+ throw e;
344
+ }
345
+ }
346
+ if (!b64) {
347
+ throw new Error('ChatGPT image generation response did not contain image data');
348
+ }
349
+ return { b64, revisedPrompt };
350
+ }
351
+ async function executeChatGptResponsesImage(options) {
352
+ const { prompt, imageUrl, config, runtime, timeoutMs } = options;
353
+ const fetchImpl = runtime.fetch ?? fetch;
354
+ const envSource = runtime.env ?? process.env;
355
+ let auth = runtime.chatGptAuth;
356
+ if (!auth) {
357
+ try {
358
+ auth = (await getChatGptAuth()) ?? undefined;
359
+ }
360
+ catch {
361
+ // getChatGptAuth may throw or return null
362
+ }
363
+ }
364
+ if (!auth?.access_token) {
365
+ throw new Error('No ChatGPT credentials found for provider chatgpt. Run `buddy login` (or `/login chatgpt`) to connect.');
366
+ }
367
+ const endpoint = config.baseUrl;
368
+ const isDirectImageEndpoint = endpoint.includes('/images/');
369
+ let requestBody;
370
+ if (isDirectImageEndpoint) {
371
+ requestBody = {
372
+ model: config.model,
373
+ prompt,
374
+ ...(imageUrl ? { image: imageUrl } : {}),
375
+ };
376
+ }
377
+ else {
378
+ const conversationalModel = env(envSource, 'CODEBUDDY_CHATGPT_MODEL') ?? CHATGPT_OAUTH_DEFAULT_MODEL;
379
+ const content = [
380
+ { type: 'input_text', text: prompt },
381
+ ];
382
+ if (imageUrl) {
383
+ content.push({ type: 'input_image', image_url: imageUrl });
384
+ }
385
+ requestBody = {
386
+ model: conversationalModel,
387
+ store: false,
388
+ stream: true,
389
+ instructions: 'You are an image generation assistant. When the user asks to generate or edit an image, invoke the image_generation tool immediately with the prompt and any provided input image.',
390
+ input: [
391
+ {
392
+ type: 'message',
393
+ role: 'user',
394
+ content,
395
+ },
396
+ ],
397
+ tools: [
398
+ {
399
+ type: 'image_generation',
400
+ // The Codex backend honours a per-tool model (verified live 2026-09-10):
401
+ // Images 2.5 (`gpt-image-2.5-flare` by default) instead of the backend default.
402
+ model: config.model,
403
+ },
404
+ ],
405
+ };
406
+ }
407
+ let res;
408
+ try {
409
+ res = await fetchWithTimeout(fetchImpl, endpoint, {
410
+ method: 'POST',
411
+ headers: buildChatGptHeaders(auth, {
412
+ accept: isDirectImageEndpoint ? 'application/json' : 'text/event-stream',
413
+ }),
414
+ body: JSON.stringify(requestBody),
415
+ }, timeoutMs, runtime.signal);
416
+ }
417
+ catch (err) {
418
+ if (runtime.signal?.aborted)
419
+ throw err;
420
+ throw new Error(`ChatGPT image generation network error: ${err instanceof Error ? err.message : String(err)}`);
421
+ }
422
+ if (res.status === 401) {
423
+ try {
424
+ const refreshed = await refreshChatGptAuth();
425
+ if (refreshed?.access_token) {
426
+ auth = refreshed;
427
+ res = await fetchWithTimeout(fetchImpl, endpoint, {
428
+ method: 'POST',
429
+ headers: buildChatGptHeaders(auth, {
430
+ accept: isDirectImageEndpoint ? 'application/json' : 'text/event-stream',
431
+ }),
432
+ body: JSON.stringify(requestBody),
433
+ }, timeoutMs, runtime.signal);
434
+ }
435
+ }
436
+ catch {
437
+ // Refresh failed, proceed to status checks
438
+ }
439
+ }
440
+ if (res.status === 401) {
441
+ throw new Error('ChatGPT authentication expired (401). Please run `buddy login` (or `/login chatgpt`) to reconnect.');
442
+ }
443
+ if (res.status === 429) {
444
+ const errText = await res.text().catch(() => '');
445
+ let message = 'ChatGPT image generation rate limit reached (429). Please wait before requesting another image.';
446
+ try {
447
+ const parsed = JSON.parse(errText);
448
+ if (parsed.error?.message) {
449
+ message = `ChatGPT image generation rate limit reached (429): ${parsed.error.message}`;
450
+ }
451
+ }
452
+ catch {
453
+ // ignore JSON parse error
454
+ }
455
+ throw new Error(message);
456
+ }
457
+ if (!res.ok) {
458
+ const errText = await res.text().catch(() => '');
459
+ let message = `ChatGPT image generation failed with status ${res.status}`;
460
+ try {
461
+ const parsed = JSON.parse(errText);
462
+ if (parsed.error?.message) {
463
+ message += `: ${parsed.error.message}`;
464
+ }
465
+ else if (errText) {
466
+ message += `: ${errText}`;
467
+ }
468
+ }
469
+ catch {
470
+ if (errText)
471
+ message += `: ${errText}`;
472
+ }
473
+ throw new Error(message);
474
+ }
475
+ const responseText = await res.text();
476
+ return parseChatGptImageResponse(responseText);
477
+ }
478
+ async function generateChatGptImage(prompt, aspect, config, runtime, generatedAt) {
479
+ const envSource = runtime.env ?? process.env;
480
+ const timeoutMs = Number(envSource.CODEBUDDY_CHATGPT_IMAGE_TIMEOUT_MS) || 180_000;
481
+ const aspectHint = aspect === 'square'
482
+ ? ' (aspect ratio: square 1:1)'
483
+ : aspect === 'portrait'
484
+ ? ' (aspect ratio: portrait 2:3)'
485
+ : ' (aspect ratio: landscape 3:2)';
486
+ const effectivePrompt = `${prompt}${aspectHint}`;
487
+ const { b64, revisedPrompt } = await executeChatGptResponsesImage({
488
+ prompt: effectivePrompt,
489
+ config,
490
+ runtime,
491
+ timeoutMs,
492
+ });
493
+ const bytes = Buffer.from(b64, 'base64');
494
+ const outputPath = await saveGeneratedAsset(bytes, {
495
+ rootDir: runtime.rootDir,
496
+ dirName: 'images',
497
+ prefix: 'image',
498
+ extension: 'png',
499
+ createId: runtime.createId,
500
+ });
501
+ await writeMediaSidecar(outputPath, {
502
+ kind: 'image',
503
+ prompt,
504
+ ...(revisedPrompt ? { revisedPrompt } : {}),
505
+ provider: config.provider,
506
+ model: config.model,
507
+ aspect_ratio: aspect,
508
+ generatedAt,
509
+ });
510
+ const result = {
511
+ kind: 'image_generate_result',
512
+ success: true,
513
+ image: outputPath,
514
+ outputPath,
515
+ mediaPath: `MEDIA:${outputPath}`,
516
+ provider: config.provider,
517
+ model: config.model,
518
+ prompt,
519
+ aspect_ratio: aspect,
520
+ generatedAt,
521
+ ...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
522
+ };
523
+ await ingestLisaSelfieIfNeeded(result, runtime);
524
+ return result;
525
+ }
526
+ async function editChatGptImage(input, config, runtime, generatedAt) {
527
+ const envSource = runtime.env ?? process.env;
528
+ const timeoutMs = Number(envSource.CODEBUDDY_CHATGPT_IMAGE_TIMEOUT_MS) || 180_000;
529
+ const { b64, revisedPrompt } = await executeChatGptResponsesImage({
530
+ prompt: input.effectivePrompt,
531
+ imageUrl: input.imageUrl,
532
+ config,
533
+ runtime,
534
+ timeoutMs,
535
+ });
536
+ const bytes = Buffer.from(b64, 'base64');
537
+ const outputPath = await saveGeneratedAsset(bytes, {
538
+ rootDir: runtime.rootDir,
539
+ dirName: 'images',
540
+ prefix: 'image-edit',
541
+ extension: 'png',
542
+ createId: runtime.createId,
543
+ });
544
+ const maskMode = input.selections.length > 0 ? 'region-prompt' : 'none';
545
+ const sourceReference = sanitizeImageSourceReference(input.sourceRef) ?? redactDataUrl(input.imageUrl);
546
+ await writeMediaSidecar(outputPath, {
547
+ kind: 'image-edit',
548
+ prompt: input.prompt,
549
+ ...(revisedPrompt ? { revisedPrompt } : {}),
550
+ provider: config.provider,
551
+ model: config.model,
552
+ source: sourceReference,
553
+ masked: false,
554
+ maskMode,
555
+ selections: input.selections,
556
+ generatedAt,
557
+ });
558
+ return {
559
+ kind: 'image_edit_result',
560
+ success: true,
561
+ image: outputPath,
562
+ outputPath,
563
+ mediaPath: `MEDIA:${outputPath}`,
564
+ provider: config.provider,
565
+ model: config.model,
566
+ prompt: input.prompt,
567
+ source: sourceReference,
568
+ masked: false,
569
+ maskMode,
570
+ selections: input.selections,
571
+ generatedAt,
572
+ ...(revisedPrompt ? { revised_prompt: revisedPrompt } : {}),
573
+ };
574
+ }
267
575
  const COMFY_DIMS = {
268
576
  landscape: { width: 1024, height: 768 },
269
577
  square: { width: 768, height: 768 },
@@ -525,13 +833,16 @@ function comfyDelay(ms, signal) {
525
833
  });
526
834
  }
527
835
  export async function getImageEditCapabilities(runtime = {}) {
528
- const config = resolveImageProvider(runtime.env ?? process.env);
836
+ const config = resolveImageProvider(runtime.env ?? process.env, { hasAuthOverride: Boolean(runtime.chatGptAuth) });
529
837
  if (config.provider === 'openai') {
530
838
  return { provider: config.provider, available: true, alphaMasking: true };
531
839
  }
532
840
  if (config.provider === 'xai') {
533
841
  return { provider: config.provider, available: true, alphaMasking: false };
534
842
  }
843
+ if (config.provider === 'chatgpt') {
844
+ return { provider: config.provider, available: true, alphaMasking: false };
845
+ }
535
846
  if (config.provider !== 'comfyui') {
536
847
  return { provider: config.provider, available: false, alphaMasking: false, reason: 'Provider does not support image editing' };
537
848
  }
@@ -1483,7 +1794,7 @@ async function materializeVideoResult(videoUrl, options) {
1483
1794
  ...(options.endpoint ? { endpoint: options.endpoint } : {}),
1484
1795
  };
1485
1796
  }
1486
- function resolveImageProvider(envSource) {
1797
+ export function resolveImageProvider(envSource = process.env, options) {
1487
1798
  let requested = (envSource.CODEBUDDY_IMAGE_PROVIDER ?? '').trim().toLowerCase();
1488
1799
  // Prefer ComfyUI when explicitly requested OR when a ComfyUI endpoint is
1489
1800
  // declared and no other provider was chosen (selfie / local-first companion
@@ -1498,6 +1809,13 @@ function resolveImageProvider(envSource) {
1498
1809
  || declaredFallbacks.length > 0)) {
1499
1810
  requested = 'comfyui';
1500
1811
  }
1812
+ const hasOpenAiKey = Boolean(envSource.OPENAI_API_KEY?.trim() || envSource.CODEBUDDY_IMAGE_API_KEY?.trim());
1813
+ const hasXaiKey = Boolean(envSource.XAI_API_KEY?.trim());
1814
+ const hasFalKey = Boolean(envSource.FAL_KEY?.trim() || envSource.FAL_API_KEY?.trim());
1815
+ const hasChatGptAuth = Boolean(options?.hasAuthOverride || hasCodexCredentials());
1816
+ if (!requested && !hasOpenAiKey && !hasXaiKey && !hasFalKey && hasChatGptAuth) {
1817
+ requested = 'chatgpt';
1818
+ }
1501
1819
  // Local ComfyUI backend (offline, GPU) — no API key, workflow-based API.
1502
1820
  if (requested === 'comfyui') {
1503
1821
  const baseUrl = (envSource.COMFYUI_URL
@@ -1515,17 +1833,25 @@ function resolveImageProvider(envSource) {
1515
1833
  }
1516
1834
  return { provider: 'comfyui', model, baseUrl, apiKey: '' };
1517
1835
  }
1518
- const provider = requested === 'xai' ? 'xai' : 'openai';
1836
+ if (requested === 'chatgpt') {
1837
+ const baseUrl = (envSource.CHATGPT_RESPONSES_URL
1838
+ ?? envSource.CODEBUDDY_IMAGE_BASE_URL
1839
+ ?? CHATGPT_RESPONSES_URL).trim().replace(/\/+$/, '');
1840
+ const model = (envSource.CODEBUDDY_IMAGE_MODEL ?? 'gpt-image-2.5-flare').trim();
1841
+ assertProviderReady('chatgpt', '', baseUrl, 'image', { hasCredentials: hasChatGptAuth });
1842
+ return { provider: 'chatgpt', model, baseUrl, apiKey: '' };
1843
+ }
1844
+ const provider = requested === 'xai' ? 'xai' : (requested === 'fal' ? 'fal' : 'openai');
1519
1845
  const baseUrl = (envSource.CODEBUDDY_IMAGE_BASE_URL
1520
- ?? (provider === 'xai' ? envSource.XAI_BASE_URL : envSource.OPENAI_BASE_URL)
1846
+ ?? (provider === 'xai' ? envSource.XAI_BASE_URL : (provider === 'fal' ? 'https://queue.fal.run' : envSource.OPENAI_BASE_URL))
1521
1847
  ?? (provider === 'xai' ? 'https://api.x.ai/v1' : 'https://api.openai.com/v1')).trim().replace(/\/+$/, '');
1522
1848
  const apiKey = (envSource.CODEBUDDY_IMAGE_API_KEY
1523
- ?? (provider === 'xai' ? envSource.XAI_API_KEY : envSource.OPENAI_API_KEY)
1849
+ ?? (provider === 'xai' ? envSource.XAI_API_KEY : (provider === 'fal' ? (envSource.FAL_KEY ?? envSource.FAL_API_KEY) : envSource.OPENAI_API_KEY))
1524
1850
  ?? '').trim();
1525
1851
  const model = (envSource.CODEBUDDY_IMAGE_MODEL
1526
1852
  ?? (provider === 'xai' ? envSource.XAI_IMAGE_MODEL : envSource.OPENAI_IMAGE_MODEL)
1527
1853
  ?? getImageGenerationModel()
1528
- ?? (provider === 'xai' ? 'grok-imagine-image' : 'gpt-image-2')).trim();
1854
+ ?? (provider === 'xai' ? 'grok-imagine-image' : 'gpt-image-2.5-flare')).trim();
1529
1855
  // Route through the Nous Tool Gateway when configured (transparent base-URL +
1530
1856
  // token substitution); otherwise use the direct provider.
1531
1857
  const route = resolveToolGatewayRoute('image_gen', envSource);
@@ -1783,10 +2109,16 @@ function resolveVideoProvider(modelOverride, envSource) {
1783
2109
  assertProviderReady(provider, effectiveApiKey, effectiveBaseUrl, 'video');
1784
2110
  return { provider, model, baseUrl: effectiveBaseUrl, apiKey: effectiveApiKey };
1785
2111
  }
1786
- function assertProviderReady(provider, apiKey, baseUrl, kind) {
2112
+ function assertProviderReady(provider, apiKey, baseUrl, kind, options) {
1787
2113
  if (!baseUrl) {
1788
2114
  throw new Error(`No ${kind} generation base URL configured for provider ${provider}`);
1789
2115
  }
2116
+ if (provider === 'chatgpt') {
2117
+ if (!options?.hasCredentials) {
2118
+ throw new Error('No ChatGPT credentials found for provider chatgpt. Run `buddy login` (or `/login chatgpt`) to connect.');
2119
+ }
2120
+ return;
2121
+ }
1790
2122
  if (!apiKey && !isLocalBaseUrl(baseUrl)) {
1791
2123
  throw new Error(`No ${kind} generation credentials configured for provider ${provider}`);
1792
2124
  }
@@ -4,6 +4,7 @@
4
4
  * Parses Git merge conflict markers, provides strategy-based resolution
5
5
  * (ours, theirs, both, ai), and exposes a tool for the agent to use.
6
6
  */
7
+ import { spawnSync } from 'child_process';
7
8
  import * as fs from 'fs';
8
9
  import * as path from 'path';
9
10
  import { logger } from '../utils/logger.js';
@@ -209,34 +210,61 @@ function indent(text, prefix = ' ') {
209
210
  /**
210
211
  * Scan the project for files containing merge conflict markers.
211
212
  */
213
+ function runGit(args, cwd) {
214
+ const result = spawnSync('git', args, {
215
+ cwd,
216
+ encoding: 'utf-8',
217
+ timeout: 10000,
218
+ stdio: ['ignore', 'pipe', 'pipe'],
219
+ windowsHide: true,
220
+ });
221
+ if (result.error) {
222
+ const code = result.error.code;
223
+ return { ok: false, reason: code === 'ENOENT' ? 'git is not installed or not on PATH' : result.error.message };
224
+ }
225
+ if (result.status !== 0) {
226
+ return { ok: false, reason: (result.stderr || '').trim() || `git ${args.join(' ')} exited with status ${result.status}` };
227
+ }
228
+ return { ok: true, stdout: result.stdout || '' };
229
+ }
212
230
  function scanForConflicts(cwd) {
213
- try {
214
- const { execSync } = require('child_process');
215
- const output = execSync('git diff --name-only --diff-filter=U', { cwd, encoding: 'utf-8', timeout: 10000 }).trim();
216
- if (!output) {
217
- return { success: true, output: 'No files with merge conflicts found.' };
231
+ // Distinguish "not a repository" and "git unavailable" from "no conflicts":
232
+ // the former used to be reported for every scan because the ESM module
233
+ // called an undefined `require` and the catch-all blamed git.
234
+ const inside = runGit(['rev-parse', '--is-inside-work-tree'], cwd);
235
+ if (!inside.ok) {
236
+ return { success: false, error: `Unable to scan for conflicts: ${inside.reason}` };
237
+ }
238
+ if (inside.stdout.trim() !== 'true') {
239
+ return { success: false, error: 'Unable to scan for conflicts: not inside a Git work tree.' };
240
+ }
241
+ const diff = runGit(['diff', '--name-only', '--diff-filter=U'], cwd);
242
+ if (!diff.ok) {
243
+ return { success: false, error: `Unable to scan for conflicts: ${diff.reason}` };
244
+ }
245
+ const output = diff.stdout.trim();
246
+ if (!output) {
247
+ return { success: true, output: 'No files with merge conflicts found.' };
248
+ }
249
+ // `git diff --name-only` paths are relative to the repository root.
250
+ const topLevel = runGit(['rev-parse', '--show-toplevel'], cwd);
251
+ const root = topLevel.ok ? topLevel.stdout.trim() : cwd;
252
+ const files = output.split('\n').filter(Boolean);
253
+ const summaries = [];
254
+ for (const file of files) {
255
+ const fullPath = path.join(root, file);
256
+ try {
257
+ const content = fs.readFileSync(fullPath, 'utf-8');
258
+ const conflicts = parseConflicts(content, fullPath);
259
+ summaries.push(` ${file}: ${conflicts.length} conflict(s)`);
218
260
  }
219
- const files = output.split('\n').filter(Boolean);
220
- const summaries = [];
221
- for (const file of files) {
222
- const fullPath = path.join(cwd, file);
223
- try {
224
- const content = fs.readFileSync(fullPath, 'utf-8');
225
- const conflicts = parseConflicts(content, fullPath);
226
- summaries.push(` ${file}: ${conflicts.length} conflict(s)`);
227
- }
228
- catch {
229
- summaries.push(` ${file}: (unable to read)`);
230
- }
261
+ catch {
262
+ summaries.push(` ${file}: (unable to read)`);
231
263
  }
232
- return {
233
- success: true,
234
- output: `Files with merge conflicts:\n${summaries.join('\n')}`,
235
- };
236
- }
237
- catch {
238
- // Fallback: not in a git repo or git not available
239
- return { success: true, output: 'Unable to scan for conflicts (git not available or not in a repository).' };
240
264
  }
265
+ return {
266
+ success: true,
267
+ output: `Files with merge conflicts:\n${summaries.join('\n')}`,
268
+ };
241
269
  }
242
270
  //# sourceMappingURL=merge-conflict-tool.js.map
@@ -1,12 +1,8 @@
1
- import { ToolMetadata, ToolCategory, ToolEffectClass } from "./types.js";
1
+ import type { ToolMetadata, ToolCategory } from './types.js';
2
2
  /**
3
3
  * Default tool metadata for all built-in tools
4
4
  */
5
5
  export declare const TOOL_METADATA: ToolMetadata[];
6
- /** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
7
- export declare function resolveToolEffect(name: string, metadata?: Pick<ToolMetadata, 'effect'> | null): ToolEffectClass | 'unknown';
8
- /** Test hook: unique-warning latch. */
9
- export declare function resetToolEffectWarningLatch(): void;
10
6
  /** Metadata visible to RAG / BM25. Gated tools stay out of the index when disabled. */
11
7
  export declare function getActiveToolMetadata(): ToolMetadata[];
12
8
  /**
@@ -1,9 +1,12 @@
1
- import { TOOL_EFFECT_CLASSES } from "./types.js";
2
- import { logger } from "../utils/logger.js";
3
1
  /**
4
2
  * Default tool metadata for all built-in tools
5
3
  */
6
4
  export const TOOL_METADATA = [
5
+ { name: 'a2a_call', effect: 'emission', category: 'web', keywords: ['a2a', 'peer', 'hermes', 'openclaw', 'delegate'], priority: 6, fleetSafe: false, description: 'Send a task to a configured remote A2A peer; remote execution can have effects and requires permission.' },
6
+ { name: 'resource_catalog', effect: 'read', category: 'system', keywords: ['resource', 'catalog', 'network', 'fleet', 'ragchat', 'available', 'ressources', 'réseau'], priority: 7, fleetSafe: false, description: 'Read explicit resource declarations and select fresh permitted resources; no probes or dispatch.' },
7
+ { name: 'ragchat_search', effect: 'read', category: 'web',
8
+ keywords: ['ragchat', 'pdf', 'corpus', 'citations', 'pages', 'ocr', 'recherche documentaire'],
9
+ priority: 7, description: 'Search configured authenticated RagChat PDF profiles with exact page citations; read-only.', fleetSafe: false },
7
10
  // File reading
8
11
  {
9
12
  name: 'view_file',
@@ -85,7 +88,7 @@ export const TOOL_METADATA = [
85
88
  name: 'self_describe',
86
89
  effect: 'read',
87
90
  category: 'file_read',
88
- keywords: ['self', 'describe', 'components', 'composants', 'briques', 'bricks', 'architecture', 'de quoi es-tu fait', 'de quoi es-tu compose', 'qui es-tu', 'capabilities', 'capacites', 'capteur', 'capteurs', 'sensors', 'modules', 'buddy-sense', 'buddy-vision', 'buddy-memory', 'introspection', 'auto inspection', 'etudie', 'examine', 'inspecte', 'propre code', 'ton code', 'fonctionne', 'fonctionnes', 'fonctionnement', 'limites', 'version', 'conscient', 'consciente', 'conscience', 'consciousness', 'modele de soi'],
91
+ keywords: ['self', 'describe', 'components', 'composants', 'briques', 'bricks', 'architecture', 'de quoi es-tu fait', 'de quoi es-tu compose', 'qui es-tu', 'capabilities', 'capacites', 'capteur', 'capteurs', 'sensors', 'modules', 'buddy-sense', 'buddy-vision', 'buddy-memory', 'introspection', 'auto inspection', 'etudie', 'examine', 'inspecte', 'propre code', 'ton code', 'fonctionne', 'fonctionnes', 'fonctionnement', 'limites', 'version', 'conscient', 'consciente', 'conscience', 'consciousness', 'modele de soi', 'theme', 'parametres', 'parametrage', 'settings', 'configuration'],
89
92
  priority: 50,
90
93
  description: "Inspect the robot's attested core, bounded code structure, turn metadata, configured faculties, and epistemic limits without live probes",
91
94
  fleetSafe: true,
@@ -215,7 +218,8 @@ export const TOOL_METADATA = [
215
218
  category: 'system',
216
219
  keywords: ['process', 'spawn', 'kill', 'list', 'logs', 'pid', 'monitor'],
217
220
  priority: 6,
218
- description: 'Manage system processes (spawn, inspect, logs, terminate)'
221
+ description: 'Manage system processes (spawn, inspect, logs, terminate)',
222
+ repeatSafe: true,
219
223
  },
220
224
  {
221
225
  name: 'app_server',
@@ -1151,7 +1155,8 @@ export const TOOL_METADATA = [
1151
1155
  category: 'media',
1152
1156
  keywords: ['gpuNode', 'gpu', 'panoworld', 'longcat', 'avatar', '3dgs', 'world model', 'reconstruction', 'render'],
1153
1157
  priority: 8,
1154
- description: 'Submit and monitor isolated PanoWorld or LongCat jobs on a configured GPU worker'
1158
+ description: 'Submit and monitor isolated PanoWorld or LongCat jobs on a configured GPU worker',
1159
+ repeatSafe: true,
1155
1160
  },
1156
1161
  {
1157
1162
  name: 'ocr',
@@ -1377,7 +1382,7 @@ export const TOOL_METADATA = [
1377
1382
  category: 'utility',
1378
1383
  keywords: ['skill', 'skills', 'list', 'installed', 'enabled', 'disabled', 'hub', 'hermes'],
1379
1384
  priority: 5,
1380
- description: 'List installed SKILL.md packages from the local SkillsHub',
1385
+ description: 'List available local skills across bundled, built-in, workspace and hub sources',
1381
1386
  fleetSafe: true,
1382
1387
  },
1383
1388
  {
@@ -1386,7 +1391,7 @@ export const TOOL_METADATA = [
1386
1391
  category: 'utility',
1387
1392
  keywords: ['skill', 'skills', 'view', 'read', 'content', 'inspect', 'show', 'hub', 'hermes'],
1388
1393
  priority: 6,
1389
- description: 'Read one installed SKILL.md package and its integrity metadata from the local SkillsHub',
1394
+ description: 'Read one local skill and its source or hub integrity metadata',
1390
1395
  fleetSafe: true,
1391
1396
  },
1392
1397
  {
@@ -1714,6 +1719,15 @@ export const TOOL_METADATA = [
1714
1719
  description: 'Generate professional documents (PowerPoint/Word/Excel/PDF) from markdown content'
1715
1720
  },
1716
1721
  // Fleet — multi-Claude orchestration via peer-RPC (Phase (d).17)
1722
+ {
1723
+ name: 'fleet_room',
1724
+ effect: 'emission',
1725
+ fleetSafe: false,
1726
+ category: 'utility',
1727
+ keywords: ['fleet', 'room', 'salon', 'message', 'coordination', 'history', 'robot', 'communication', 'flotte'],
1728
+ priority: 7,
1729
+ description: 'Send messages, read history or check access in the configured Fleet room; messages remain external data, not action authorization',
1730
+ },
1717
1731
  {
1718
1732
  name: 'peer_delegate',
1719
1733
  effect: 'emission',
@@ -2030,27 +2044,6 @@ export const TOOL_METADATA = [
2030
2044
  fleetSafe: true,
2031
2045
  },
2032
2046
  ];
2033
- const missingEffectWarned = new Set();
2034
- function isToolEffectClass(value) {
2035
- return TOOL_EFFECT_CLASSES.includes(value);
2036
- }
2037
- /** Resolve a tool's declared effect class. Missing catalog/MCP entries warn once and return `unknown`. */
2038
- export function resolveToolEffect(name, metadata) {
2039
- if (isToolEffectClass(metadata?.effect))
2040
- return metadata.effect;
2041
- const catalog = TOOL_METADATA.find((entry) => entry.name === name)?.effect;
2042
- if (isToolEffectClass(catalog))
2043
- return catalog;
2044
- if (!missingEffectWarned.has(name)) {
2045
- missingEffectWarned.add(name);
2046
- logger.warn('tool metadata missing effect class; treating as unknown', { tool: name });
2047
- }
2048
- return 'unknown';
2049
- }
2050
- /** Test hook: unique-warning latch. */
2051
- export function resetToolEffectWarningLatch() {
2052
- missingEffectWarned.clear();
2053
- }
2054
2047
  /** Metadata visible to RAG / BM25. Gated tools stay out of the index when disabled. */
2055
2048
  export function getActiveToolMetadata() {
2056
2049
  if (process.env.CODEBUDDY_CONTEXT_ZOOM === 'true')