@phuetz/code-buddy 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/README.fr.md +56 -0
  2. package/README.md +74 -16
  3. package/codebuddy-runtime.json +5 -5
  4. package/dist/agent/codebuddy-agent.d.ts +18 -0
  5. package/dist/agent/codebuddy-agent.js +45 -8
  6. package/dist/agent/execution/agent-executor.d.ts +0 -9
  7. package/dist/agent/execution/agent-executor.js +176 -12
  8. package/dist/agent/execution/context-pipeline.d.ts +9 -0
  9. package/dist/agent/execution/context-pipeline.js +64 -2
  10. package/dist/agent/execution/tool-loop-guard.d.ts +76 -0
  11. package/dist/agent/execution/tool-loop-guard.js +165 -0
  12. package/dist/agent/execution/tool-selection-strategy.d.ts +7 -0
  13. package/dist/agent/execution/tool-selection-strategy.js +32 -2
  14. package/dist/agent/facades/session-facade.d.ts +0 -6
  15. package/dist/agent/facades/session-facade.js +0 -45
  16. package/dist/agent/hermes-claw-migrate.d.ts +0 -21
  17. package/dist/agent/hermes-claw-migrate.js +9 -4
  18. package/dist/agent/hermes-protocol-gateways.js +8 -1
  19. package/dist/agent/repo-profiler.js +17 -4
  20. package/dist/agent/self-improvement/authored-tool-runtime.js +10 -2
  21. package/dist/agent/self-improvement/evolution/ast-novelty.d.ts +5 -0
  22. package/dist/agent/self-improvement/evolution/ast-novelty.js +58 -23
  23. package/dist/agent/self-improvement/evolution/code-variant-store.d.ts +3 -0
  24. package/dist/agent/self-improvement/evolution/evolution-engine.js +2 -0
  25. package/dist/agent/self-improvement/evolution/protected-paths.js +6 -0
  26. package/dist/agent/self-improvement/evolution/variant-fitness.d.ts +13 -2
  27. package/dist/agent/self-improvement/evolution/variant-fitness.js +184 -58
  28. package/dist/agent/self-improvement/evolution/worktree-scorer.d.ts +2 -0
  29. package/dist/agent/self-improvement/evolution/worktree-scorer.js +15 -0
  30. package/dist/agent/self-improvement/evolutionary-archive.d.ts +2 -1
  31. package/dist/agent/self-improvement/evolutionary-archive.js +34 -5
  32. package/dist/agent/self-improvement/proposal-store.d.ts +1 -0
  33. package/dist/agent/self-improvement/proposal-store.js +79 -17
  34. package/dist/agent/self-improvement/skill-apply-journal.d.ts +44 -0
  35. package/dist/agent/self-improvement/skill-apply-journal.js +178 -0
  36. package/dist/agent/self-improvement/skill-behavior-benchmark.d.ts +3 -0
  37. package/dist/agent/self-improvement/skill-behavior-benchmark.js +19 -0
  38. package/dist/agent/self-improvement/skill-behavior-gate.d.ts +34 -0
  39. package/dist/agent/self-improvement/skill-behavior-gate.js +96 -0
  40. package/dist/agent/self-improvement/skill-engine.d.ts +22 -0
  41. package/dist/agent/self-improvement/skill-engine.js +385 -13
  42. package/dist/agent/self-improvement/skill-gate.d.ts +2 -0
  43. package/dist/agent/self-improvement/skill-gate.js +17 -2
  44. package/dist/agent/self-improvement/skill-mutator.d.ts +6 -1
  45. package/dist/agent/self-improvement/skill-mutator.js +51 -15
  46. package/dist/agent/self-improvement/skill-types.d.ts +2 -1
  47. package/dist/agent/self-improvement/types.d.ts +11 -0
  48. package/dist/agent/tool-handler.d.ts +1 -1
  49. package/dist/agent/tool-handler.js +28 -9
  50. package/dist/auth/profile-manager.js +1 -1
  51. package/dist/channels/companion-channel-turn.d.ts +53 -4
  52. package/dist/channels/companion-channel-turn.js +218 -16
  53. package/dist/channels/slash-parity.d.ts +4 -6
  54. package/dist/channels/slash-parity.js +9 -44
  55. package/dist/cli/session-commands.d.ts +9 -0
  56. package/dist/cli/session-commands.js +45 -5
  57. package/dist/cli/session-picker.d.ts +43 -0
  58. package/dist/cli/session-picker.js +128 -0
  59. package/dist/codebuddy/a2a-call-tool-defs.d.ts +26 -0
  60. package/dist/codebuddy/a2a-call-tool-defs.js +12 -0
  61. package/dist/codebuddy/fleet-tool-defs.d.ts +2 -0
  62. package/dist/codebuddy/fleet-tool-defs.js +55 -0
  63. package/dist/codebuddy/providers/chatgpt-headers.d.ts +18 -0
  64. package/dist/codebuddy/providers/chatgpt-headers.js +37 -0
  65. package/dist/codebuddy/providers/provider-chatgpt-responses.d.ts +2 -1
  66. package/dist/codebuddy/providers/provider-chatgpt-responses.js +10 -23
  67. package/dist/codebuddy/providers/provider-openai-compat.d.ts +7 -0
  68. package/dist/codebuddy/providers/provider-openai-compat.js +29 -1
  69. package/dist/codebuddy/ragchat-tool-defs.d.ts +31 -0
  70. package/dist/codebuddy/ragchat-tool-defs.js +19 -0
  71. package/dist/codebuddy/resource-catalog-tool-defs.d.ts +28 -0
  72. package/dist/codebuddy/resource-catalog-tool-defs.js +18 -0
  73. package/dist/codebuddy/tool-definitions/agent-tools.js +2 -2
  74. package/dist/codebuddy/tool-definitions/code-exec-tools.js +5 -1
  75. package/dist/codebuddy/tool-definitions/cron-tools.js +6 -0
  76. package/dist/codebuddy/tool-definitions/self-describe-tools.js +6 -1
  77. package/dist/codebuddy/tools.d.ts +0 -6
  78. package/dist/codebuddy/tools.js +25 -3
  79. package/dist/commands/cli/daemon-commands.js +3 -1
  80. package/dist/commands/cli/evolve-command.js +21 -5
  81. package/dist/commands/cli/fleet-collaboration-commands.d.ts +2 -0
  82. package/dist/commands/cli/fleet-collaboration-commands.js +57 -0
  83. package/dist/commands/cli/fleet-commands.js +29 -0
  84. package/dist/commands/cli/fleet-mission-commands.d.ts +3 -0
  85. package/dist/commands/cli/fleet-mission-commands.js +72 -0
  86. package/dist/commands/cli/fleet-rooms-commands.d.ts +10 -0
  87. package/dist/commands/cli/fleet-rooms-commands.js +289 -0
  88. package/dist/commands/cli/tools-commands.js +2 -1
  89. package/dist/commands/cli/triage-command.d.ts +8 -0
  90. package/dist/commands/cli/triage-command.js +72 -0
  91. package/dist/commands/cli/utility-commands.js +25 -1
  92. package/dist/commands/client-dispatcher.d.ts +7 -0
  93. package/dist/commands/client-dispatcher.js +73 -21
  94. package/dist/commands/cron-cli/index.d.ts +3 -1
  95. package/dist/commands/cron-cli/index.js +25 -0
  96. package/dist/commands/device-auth.d.ts +10 -0
  97. package/dist/commands/device-auth.js +91 -0
  98. package/dist/commands/enhanced-command-handler.d.ts +9 -0
  99. package/dist/commands/enhanced-command-handler.js +28 -6
  100. package/dist/commands/handlers/agent-handlers.d.ts +1 -1
  101. package/dist/commands/handlers/agent-handlers.js +4 -4
  102. package/dist/commands/handlers/channel-handlers.js +53 -2
  103. package/dist/commands/handlers/export-handlers.d.ts +3 -2
  104. package/dist/commands/handlers/export-handlers.js +55 -28
  105. package/dist/commands/handlers/extra-handlers.js +5 -1
  106. package/dist/commands/handlers/grill-me-handler.js +26 -18
  107. package/dist/commands/handlers/memory-handlers.d.ts +6 -2
  108. package/dist/commands/handlers/memory-handlers.js +35 -15
  109. package/dist/commands/handlers/missing-handlers.d.ts +2 -2
  110. package/dist/commands/handlers/missing-handlers.js +12 -4
  111. package/dist/commands/handlers/resources-handler.d.ts +12 -0
  112. package/dist/commands/handlers/resources-handler.js +52 -0
  113. package/dist/commands/handlers/starter-handlers.d.ts +1 -1
  114. package/dist/commands/handlers/starter-handlers.js +32 -2
  115. package/dist/commands/handlers/switch-handler.d.ts +1 -1
  116. package/dist/commands/handlers/switch-handler.js +15 -0
  117. package/dist/commands/handlers/test-handlers.js +4 -86
  118. package/dist/commands/handlers/ui-handlers.js +11 -5
  119. package/dist/commands/login-chatgpt.d.ts +8 -0
  120. package/dist/commands/login-chatgpt.js +17 -0
  121. package/dist/commands/mcp-import.d.ts +11 -0
  122. package/dist/commands/mcp-import.js +67 -0
  123. package/dist/commands/mcp-invoke.d.ts +2 -0
  124. package/dist/commands/mcp-invoke.js +68 -0
  125. package/dist/commands/mcp.d.ts +13 -0
  126. package/dist/commands/mcp.js +66 -21
  127. package/dist/commands/pipeline.d.ts +7 -1
  128. package/dist/commands/pipeline.js +104 -7
  129. package/dist/commands/resources.d.ts +2 -0
  130. package/dist/commands/resources.js +64 -0
  131. package/dist/commands/skills-cli/index.js +35 -12
  132. package/dist/commands/slash/builtin-commands.js +16 -3
  133. package/dist/commands/slash/index.d.ts +3 -1
  134. package/dist/commands/slash/index.js +2 -0
  135. package/dist/commands/slash/surfaces.d.ts +53 -0
  136. package/dist/commands/slash/surfaces.js +177 -0
  137. package/dist/commands/slash/types.d.ts +17 -0
  138. package/dist/commands/try.d.ts +1 -1
  139. package/dist/commands/try.js +1 -1
  140. package/dist/companion/companion-identity.d.ts +43 -0
  141. package/dist/companion/companion-identity.js +136 -0
  142. package/dist/companion/companion-toolset.d.ts +66 -0
  143. package/dist/companion/companion-toolset.js +368 -0
  144. package/dist/companion/companion-turn.d.ts +10 -2
  145. package/dist/companion/companion-turn.js +38 -1
  146. package/dist/config/code-exec-policy.d.ts +25 -0
  147. package/dist/config/code-exec-policy.js +39 -0
  148. package/dist/config/model-tools.d.ts +9 -0
  149. package/dist/config/model-tools.js +103 -0
  150. package/dist/context/context-manager-v2.js +2 -2
  151. package/dist/context/lm-resizer-compressor.js +3 -2
  152. package/dist/context/lm-resizer-diagnostics.d.ts +9 -0
  153. package/dist/context/lm-resizer-diagnostics.js +30 -0
  154. package/dist/context/tool-output-masking.js +3 -4
  155. package/dist/curator/curator.d.ts +6 -0
  156. package/dist/curator/curator.js +53 -3
  157. package/dist/daemon/cron-agent-bridge.d.ts +6 -0
  158. package/dist/daemon/cron-agent-bridge.js +31 -4
  159. package/dist/doctor/index.d.ts +11 -2
  160. package/dist/doctor/index.js +84 -21
  161. package/dist/doctor/integrations.d.ts +197 -0
  162. package/dist/doctor/integrations.js +241 -0
  163. package/dist/doctor/triage.d.ts +108 -0
  164. package/dist/doctor/triage.js +304 -0
  165. package/dist/errors/crash-handler.js +2 -0
  166. package/dist/fleet/collaboration.d.ts +44 -0
  167. package/dist/fleet/collaboration.js +170 -0
  168. package/dist/fleet/fleet-listener.d.ts +1 -0
  169. package/dist/fleet/fleet-listener.js +87 -46
  170. package/dist/fleet/fleet-registry.d.ts +2 -0
  171. package/dist/fleet/resource-catalog.d.ts +245 -0
  172. package/dist/fleet/resource-catalog.js +211 -0
  173. package/dist/fleet/rooms/room-access.d.ts +138 -0
  174. package/dist/fleet/rooms/room-access.js +196 -0
  175. package/dist/fleet/rooms/room-client.d.ts +158 -0
  176. package/dist/fleet/rooms/room-client.js +685 -0
  177. package/dist/fleet/rooms/room-event.d.ts +139 -0
  178. package/dist/fleet/rooms/room-event.js +330 -0
  179. package/dist/fleet/rooms/room-filter.d.ts +48 -0
  180. package/dist/fleet/rooms/room-filter.js +152 -0
  181. package/dist/fleet/rooms/room-hub.d.ts +154 -0
  182. package/dist/fleet/rooms/room-hub.js +363 -0
  183. package/dist/fleet/rooms/room-identity.d.ts +26 -0
  184. package/dist/fleet/rooms/room-identity.js +82 -0
  185. package/dist/fleet/rooms/room-lock.d.ts +34 -0
  186. package/dist/fleet/rooms/room-lock.js +180 -0
  187. package/dist/fleet/rooms/room-observations.d.ts +7 -0
  188. package/dist/fleet/rooms/room-observations.js +61 -0
  189. package/dist/fleet/rooms/room-server.d.ts +28 -0
  190. package/dist/fleet/rooms/room-server.js +75 -0
  191. package/dist/fleet/rooms/room-store.d.ts +119 -0
  192. package/dist/fleet/rooms/room-store.js +448 -0
  193. package/dist/fleet/rooms/room-ws-bridge.d.ts +27 -0
  194. package/dist/fleet/rooms/room-ws-bridge.js +137 -0
  195. package/dist/fleet/sensory-mission-bridge.d.ts +42 -0
  196. package/dist/fleet/sensory-mission-bridge.js +136 -0
  197. package/dist/git/worktree-sessions.js +1 -0
  198. package/dist/harness/contract.d.ts +4 -4
  199. package/dist/harness/fleet-supervisor.d.ts +16 -0
  200. package/dist/harness/fleet-supervisor.js +64 -0
  201. package/dist/harness/index.d.ts +4 -0
  202. package/dist/harness/index.js +4 -0
  203. package/dist/harness/mission-runner.d.ts +3 -0
  204. package/dist/harness/mission-runner.js +53 -0
  205. package/dist/harness/mission-store.d.ts +93 -0
  206. package/dist/harness/mission-store.js +297 -0
  207. package/dist/harness/tool-harness.d.ts +56 -0
  208. package/dist/harness/tool-harness.js +153 -0
  209. package/dist/hooks/use-enhanced-input.js +48 -4
  210. package/dist/hooks/use-input-handler.d.ts +1 -0
  211. package/dist/hooks/use-input-handler.js +82 -22
  212. package/dist/hooks/use-input-history.js +1 -0
  213. package/dist/identity/lisa-introspection.js +5 -2
  214. package/dist/identity/operational-self-model.d.ts +2 -0
  215. package/dist/identity/operational-self-model.js +4 -0
  216. package/dist/index.js +52 -6
  217. package/dist/mcp/client.d.ts +11 -0
  218. package/dist/mcp/client.js +68 -3
  219. package/dist/mcp/config.d.ts +20 -0
  220. package/dist/mcp/config.js +121 -8
  221. package/dist/mcp/import-normalize.d.ts +12 -0
  222. package/dist/mcp/import-normalize.js +114 -0
  223. package/dist/mcp/mcp-oauth-constants.d.ts +8 -0
  224. package/dist/mcp/mcp-oauth-constants.js +9 -0
  225. package/dist/mcp/mcp-oauth-provider.d.ts +80 -0
  226. package/dist/mcp/mcp-oauth-provider.js +241 -0
  227. package/dist/mcp/mcp-oauth.d.ts +60 -1
  228. package/dist/mcp/mcp-oauth.js +241 -65
  229. package/dist/mcp/transports.d.ts +14 -5
  230. package/dist/mcp/transports.js +112 -101
  231. package/dist/mcp/types.d.ts +5 -0
  232. package/dist/media/comfyui-recipe-contract.d.ts +7 -7
  233. package/dist/memory/facts-memory.d.ts +11 -1
  234. package/dist/memory/facts-memory.js +47 -8
  235. package/dist/memory/memory-candidate-queue.d.ts +2 -2
  236. package/dist/memory/memory-candidate-queue.js +6 -6
  237. package/dist/memory/persistent-memory.d.ts +13 -8
  238. package/dist/memory/persistent-memory.js +77 -30
  239. package/dist/nodes/device-node.js +5 -9
  240. package/dist/observability/mobile-supervision-gateway-contract.js +20 -7
  241. package/dist/observability/run-event-writer.d.ts +21 -0
  242. package/dist/observability/run-event-writer.js +81 -0
  243. package/dist/observability/run-store.d.ts +5 -0
  244. package/dist/observability/run-store.js +18 -13
  245. package/dist/observability/run-trajectory.js +1 -1
  246. package/dist/optimization/prompt-cache.d.ts +19 -2
  247. package/dist/optimization/prompt-cache.js +41 -6
  248. package/dist/orchestration/orchestrator.d.ts +21 -0
  249. package/dist/orchestration/orchestrator.js +122 -15
  250. package/dist/persistence/session-content.d.ts +8 -0
  251. package/dist/persistence/session-content.js +76 -0
  252. package/dist/persistence/session-handoff.d.ts +64 -0
  253. package/dist/persistence/session-handoff.js +80 -0
  254. package/dist/persistence/session-history.d.ts +4 -0
  255. package/dist/persistence/session-history.js +38 -0
  256. package/dist/persistence/session-store.d.ts +9 -0
  257. package/dist/persistence/session-store.js +48 -20
  258. package/dist/personas/persona-manager.js +17 -1
  259. package/dist/plugins/code-explorer/CodeExplorerManager.d.ts +10 -4
  260. package/dist/plugins/code-explorer/CodeExplorerManager.js +69 -16
  261. package/dist/plugins/plugin-manager.js +10 -1
  262. package/dist/prompts/prompt-manager.js +11 -4
  263. package/dist/prompts/system-base.js +6 -2
  264. package/dist/protocols/a2a/codebuddy-executor.d.ts +11 -2
  265. package/dist/protocols/a2a/codebuddy-executor.js +9 -8
  266. package/dist/protocols/a2a/index.d.ts +1 -1
  267. package/dist/protocols/a2a/jsonrpc-v1.d.ts +41 -0
  268. package/dist/protocols/a2a/jsonrpc-v1.js +145 -0
  269. package/dist/protocols/a2a/peer-config.d.ts +20 -0
  270. package/dist/protocols/a2a/peer-config.js +55 -0
  271. package/dist/providers/codex-oauth.js +30 -6
  272. package/dist/providers/model-provider-compat.js +2 -1
  273. package/dist/sandbox/os-sandbox.d.ts +1 -1
  274. package/dist/scheduler/cron-scheduler.d.ts +15 -2
  275. package/dist/scheduler/cron-scheduler.js +35 -4
  276. package/dist/scheduler/job-notepad.d.ts +69 -0
  277. package/dist/scheduler/job-notepad.js +339 -0
  278. package/dist/security/audit-logger.d.ts +1 -1
  279. package/dist/security/compute-confinement.d.ts +4 -0
  280. package/dist/security/compute-confinement.js +89 -0
  281. package/dist/security/session-encryption.d.ts +4 -0
  282. package/dist/security/session-encryption.js +31 -0
  283. package/dist/sensory/voice-loop.d.ts +17 -0
  284. package/dist/sensory/voice-loop.js +72 -15
  285. package/dist/server/auth/device-session-context.d.ts +9 -0
  286. package/dist/server/auth/device-session-context.js +13 -0
  287. package/dist/server/auth/device-store.d.ts +89 -0
  288. package/dist/server/auth/device-store.js +261 -0
  289. package/dist/server/auth/device-token.d.ts +3 -0
  290. package/dist/server/auth/device-token.js +6 -0
  291. package/dist/server/auth/jwt.js +4 -0
  292. package/dist/server/index.d.ts +0 -10
  293. package/dist/server/index.js +28 -0
  294. package/dist/server/middleware/auth.js +3 -2
  295. package/dist/server/routes/a2a-jsonrpc.d.ts +9 -0
  296. package/dist/server/routes/a2a-jsonrpc.js +66 -0
  297. package/dist/server/routes/a2a-protocol.d.ts +12 -0
  298. package/dist/server/routes/a2a-protocol.js +1 -1
  299. package/dist/server/routes/device-auth.d.ts +4 -0
  300. package/dist/server/routes/device-auth.js +40 -0
  301. package/dist/server/types.d.ts +4 -0
  302. package/dist/server/websocket/handler.d.ts +13 -0
  303. package/dist/server/websocket/handler.js +102 -17
  304. package/dist/services/prompt-builder.d.ts +2 -0
  305. package/dist/services/prompt-builder.js +16 -6
  306. package/dist/services/runtime-settings-context.d.ts +81 -0
  307. package/dist/services/runtime-settings-context.js +79 -0
  308. package/dist/skills/executor.js +2 -0
  309. package/dist/skills/hub.js +16 -14
  310. package/dist/skills/local-inventory.d.ts +21 -0
  311. package/dist/skills/local-inventory.js +72 -0
  312. package/dist/skills/skill-loader.js +2 -2
  313. package/dist/skills/skill-usage-store.d.ts +49 -0
  314. package/dist/skills/skill-usage-store.js +121 -0
  315. package/dist/testing/ai-integration-tests.js +8 -5
  316. package/dist/themes/theme-manager.d.ts +12 -0
  317. package/dist/themes/theme-manager.js +29 -0
  318. package/dist/themes/theme-schema.d.ts +24 -24
  319. package/dist/tools/a2a-call-tool.d.ts +34 -0
  320. package/dist/tools/a2a-call-tool.js +75 -0
  321. package/dist/tools/bash/streaming-executor.d.ts +1 -0
  322. package/dist/tools/bash/streaming-executor.js +78 -90
  323. package/dist/tools/code-exec-preflight-runner.d.ts +41 -0
  324. package/dist/tools/code-exec-preflight-runner.js +254 -0
  325. package/dist/tools/code-exec-preflight.d.ts +44 -0
  326. package/dist/tools/code-exec-preflight.js +501 -0
  327. package/dist/tools/code-exec-tool.d.ts +48 -1
  328. package/dist/tools/code-exec-tool.js +191 -47
  329. package/dist/tools/comment-watcher.js +29 -12
  330. package/dist/tools/core-code-inspection.d.ts +56 -0
  331. package/dist/tools/core-code-inspection.js +86 -0
  332. package/dist/tools/create-skill-tool.d.ts +2 -3
  333. package/dist/tools/create-skill-tool.js +16 -75
  334. package/dist/tools/cronjob-tool.d.ts +1 -0
  335. package/dist/tools/cronjob-tool.js +1 -0
  336. package/dist/tools/env-doctor-tool.d.ts +2 -0
  337. package/dist/tools/env-doctor-tool.js +4 -3
  338. package/dist/tools/execute-code-rpc-invoker.d.ts +1 -1
  339. package/dist/tools/execute-code-rpc-invoker.js +35 -19
  340. package/dist/tools/execute-code-runner.d.ts +2 -0
  341. package/dist/tools/execute-code-runner.js +52 -17
  342. package/dist/tools/fleet-room-tool.d.ts +104 -0
  343. package/dist/tools/fleet-room-tool.js +124 -0
  344. package/dist/tools/integration-tool-hints.d.ts +4 -0
  345. package/dist/tools/integration-tool-hints.js +19 -0
  346. package/dist/tools/list-peers-tool.d.ts +3 -0
  347. package/dist/tools/list-peers-tool.js +11 -4
  348. package/dist/tools/media-generation-tool.d.ts +16 -1
  349. package/dist/tools/media-generation-tool.js +341 -9
  350. package/dist/tools/merge-conflict-tool.js +53 -25
  351. package/dist/tools/metadata.d.ts +1 -5
  352. package/dist/tools/metadata.js +30 -28
  353. package/dist/tools/peer-tool-invoke-tool.d.ts +61 -0
  354. package/dist/tools/peer-tool-invoke-tool.js +396 -0
  355. package/dist/tools/ragchat-tool.d.ts +39 -0
  356. package/dist/tools/ragchat-tool.js +105 -0
  357. package/dist/tools/registry/fleet-tools.d.ts +21 -3
  358. package/dist/tools/registry/fleet-tools.js +137 -4
  359. package/dist/tools/registry/index.d.ts +1 -1
  360. package/dist/tools/registry/index.js +2 -2
  361. package/dist/tools/registry/knowledge-tools.d.ts +2 -2
  362. package/dist/tools/registry/knowledge-tools.js +2 -2
  363. package/dist/tools/registry/lessons-tools.d.ts +7 -0
  364. package/dist/tools/registry/lessons-tools.js +43 -3
  365. package/dist/tools/registry/memory-tools.d.ts +1 -1
  366. package/dist/tools/registry/memory-tools.js +8 -8
  367. package/dist/tools/registry/research-tools.d.ts +1 -0
  368. package/dist/tools/registry/research-tools.js +4 -13
  369. package/dist/tools/registry/self-describe-tools.d.ts +1 -1
  370. package/dist/tools/registry/self-describe-tools.js +43 -30
  371. package/dist/tools/resource-catalog-tool.d.ts +38 -0
  372. package/dist/tools/resource-catalog-tool.js +46 -0
  373. package/dist/tools/skills-inspection-tool.js +30 -1
  374. package/dist/tools/stream-tool-output.d.ts +3 -0
  375. package/dist/tools/stream-tool-output.js +33 -0
  376. package/dist/tools/tool-call-scheduler.d.ts +10 -0
  377. package/dist/tools/tool-call-scheduler.js +58 -0
  378. package/dist/tools/tool-effect.d.ts +5 -0
  379. package/dist/tools/tool-effect.js +26 -0
  380. package/dist/tools/tool-search.d.ts +12 -11
  381. package/dist/tools/tool-search.js +67 -26
  382. package/dist/tools/types.d.ts +6 -0
  383. package/dist/ui/components/ChatHistory.d.ts +1 -1
  384. package/dist/ui/components/ChatHistory.js +2 -2
  385. package/dist/ui/components/ChatInput.d.ts +2 -1
  386. package/dist/ui/components/ChatInput.js +42 -88
  387. package/dist/ui/components/ChatInterface.d.ts +4 -2
  388. package/dist/ui/components/ChatInterface.js +27 -63
  389. package/dist/ui/components/CommandSuggestions.d.ts +0 -1
  390. package/dist/ui/components/CommandSuggestions.js +4 -6
  391. package/dist/ui/components/FileAutocomplete.js +1 -1
  392. package/dist/ui/components/KeyboardHelp.js +8 -6
  393. package/dist/ui/components/ModelSelection.js +6 -5
  394. package/dist/ui/components/StatusBar.d.ts +2 -1
  395. package/dist/ui/components/StatusBar.js +8 -7
  396. package/dist/ui/context/theme-context.js +3 -2
  397. package/dist/ui/index.d.ts +1 -1
  398. package/dist/ui/index.js +1 -1
  399. package/dist/ui/utils/markdown-renderer.js +4 -13
  400. package/dist/utils/atomic-write.d.ts +22 -0
  401. package/dist/utils/atomic-write.js +29 -0
  402. package/dist/utils/bounded-output.d.ts +16 -0
  403. package/dist/utils/bounded-output.js +63 -0
  404. package/dist/utils/config-validation/schema.d.ts +2 -2
  405. package/dist/utils/device-store-file.d.ts +4 -0
  406. package/dist/utils/device-store-file.js +40 -0
  407. package/dist/utils/export-manager.d.ts +9 -0
  408. package/dist/utils/export-manager.js +19 -0
  409. package/dist/utils/first-use-hints.d.ts +25 -0
  410. package/dist/utils/first-use-hints.js +58 -0
  411. package/dist/utils/graceful-shutdown.d.ts +8 -0
  412. package/dist/utils/graceful-shutdown.js +23 -7
  413. package/dist/utils/history-manager.js +1 -1
  414. package/dist/utils/update-notifier.js +16 -18
  415. package/dist/wizard/environment-detection.d.ts +5 -1
  416. package/dist/wizard/environment-detection.js +49 -7
  417. package/dist/wizard/onboarding.d.ts +5 -1
  418. package/dist/wizard/onboarding.js +90 -30
  419. package/dist/wizard/provider-onboarding.d.ts +2 -0
  420. package/dist/wizard/provider-onboarding.js +55 -17
  421. package/package.json +7 -3
@@ -0,0 +1,68 @@
1
+ import { readFile, stat } from 'node:fs/promises';
2
+ import { MCPManager } from '../mcp/client.js';
3
+ import { loadMCPConfig } from '../mcp/config.js';
4
+ import { getErrorMessage } from '../types/index.js';
5
+ const MAX_ARGUMENT_BYTES = 1024 * 1024;
6
+ export function registerMCPInvocationCommands(command) {
7
+ command.command('tools <server>')
8
+ .description('Print one configured MCP server tool catalog as JSON, without an LLM')
9
+ .option('--query <text>', 'Filter tool names and descriptions before printing schemas')
10
+ .action(async (server, options) => run(server, undefined, options));
11
+ command.command('call <server> <tool>')
12
+ .description('Invoke one MCP tool directly and print its result as JSON')
13
+ .option('--args <json>', 'JSON object of tool arguments')
14
+ .option('--args-file <path>', 'Read JSON arguments from a file (maximum 1 MiB)')
15
+ .action(async (server, tool, options) => {
16
+ await run(server, tool, options);
17
+ });
18
+ }
19
+ async function run(server, tool, options = {}) {
20
+ const manager = new MCPManager();
21
+ try {
22
+ if (options.args !== undefined && options.argsFile !== undefined) {
23
+ throw new Error('Use either --args or --args-file');
24
+ }
25
+ let raw = options.args ?? '{}';
26
+ if (options.argsFile !== undefined) {
27
+ const info = await stat(options.argsFile);
28
+ if (!info.isFile() || info.size > MAX_ARGUMENT_BYTES)
29
+ throw new Error('Arguments must be a regular file no larger than 1 MiB');
30
+ raw = await readFile(options.argsFile, 'utf8');
31
+ }
32
+ if (Buffer.byteLength(raw) > MAX_ARGUMENT_BYTES)
33
+ throw new Error('Arguments exceed 1 MiB');
34
+ let args;
35
+ try {
36
+ args = JSON.parse(raw);
37
+ }
38
+ catch {
39
+ throw new Error('Tool arguments must be valid JSON');
40
+ }
41
+ if (!args || typeof args !== 'object' || Array.isArray(args))
42
+ throw new Error('Tool arguments must be a JSON object');
43
+ const config = loadMCPConfig().servers.find(candidate => candidate.name === server);
44
+ if (!config)
45
+ throw new Error(`Enabled MCP server not found: ${server}`);
46
+ await manager.addServer(config);
47
+ if (!tool) {
48
+ const catalog = manager.getTools().filter(item => item.serverName === server);
49
+ const query = options.query?.toLowerCase();
50
+ const tools = query ? catalog.filter(item => `${item.name} ${item.description}`.toLowerCase().includes(query)) : catalog;
51
+ console.log(JSON.stringify({ server, totalTools: catalog.length, tools }));
52
+ return;
53
+ }
54
+ const qualified = `mcp__${server}__${tool}`;
55
+ const result = await manager.callTool(qualified, args);
56
+ console.log(JSON.stringify(result));
57
+ if (result.isError)
58
+ process.exitCode = 1;
59
+ }
60
+ catch (error) {
61
+ console.log(JSON.stringify({ isError: true, error: getErrorMessage(error) }));
62
+ process.exitCode = 1;
63
+ }
64
+ finally {
65
+ await manager.dispose();
66
+ }
67
+ }
68
+ //# sourceMappingURL=mcp-invoke.js.map
@@ -1,5 +1,18 @@
1
1
  import { Command } from 'commander';
2
2
  export declare function confirmPrompt(prompt: string): Promise<boolean>;
3
+ /**
4
+ * How to confirm a stdio MCP add. `--yes` skips the prompt.
5
+ * Without a TTY and without `--yes`, abort instead of hanging on readline.
6
+ */
7
+ export declare function stdioAddConfirmMode(yes: boolean, stdinIsTTY?: boolean | undefined): 'skip' | 'prompt' | 'abort';
8
+ /**
9
+ * `mcp test` / add / add-json only probe the server then persist config.
10
+ * Tear down the live client so a stdio child cannot keep the CLI event loop open.
11
+ * Same path as `buddy mcp test` (removeServer → transport.disconnect → reap PID).
12
+ */
13
+ export declare function releaseMcpProbe(manager: {
14
+ removeServer(name: string): Promise<void>;
15
+ }, name: string): Promise<void>;
3
16
  export interface MCPServeOptions {
4
17
  allowWrite?: boolean;
5
18
  tools?: string;
@@ -1,3 +1,5 @@
1
+ import { registerMCPImportCommand } from './mcp-import.js';
2
+ import { registerMCPInvocationCommands } from './mcp-invoke.js';
1
3
  import { Command } from 'commander';
2
4
  import { addMCPServer, removeMCPServer, loadMCPConfig, PREDEFINED_SERVERS, setMCPServerEnabled, } from '../mcp/config.js';
3
5
  import { getMCPManager } from '../codebuddy/tools.js';
@@ -35,6 +37,30 @@ export function confirmPrompt(prompt) {
35
37
  });
36
38
  });
37
39
  }
40
+ /**
41
+ * How to confirm a stdio MCP add. `--yes` skips the prompt.
42
+ * Without a TTY and without `--yes`, abort instead of hanging on readline.
43
+ */
44
+ export function stdioAddConfirmMode(yes, stdinIsTTY = process.stdin.isTTY) {
45
+ if (yes)
46
+ return 'skip';
47
+ if (stdinIsTTY)
48
+ return 'prompt';
49
+ return 'abort';
50
+ }
51
+ /**
52
+ * `mcp test` / add / add-json only probe the server then persist config.
53
+ * Tear down the live client so a stdio child cannot keep the CLI event loop open.
54
+ * Same path as `buddy mcp test` (removeServer → transport.disconnect → reap PID).
55
+ */
56
+ export async function releaseMcpProbe(manager, name) {
57
+ try {
58
+ await manager.removeServer(name);
59
+ }
60
+ catch {
61
+ // Probe teardown must not mask the add/test result.
62
+ }
63
+ }
38
64
  /** Start the distribution-facing stdio server. Logs stay on stderr via logger. */
39
65
  export async function serveMCP(options = {}) {
40
66
  const { CodeBuddyMCPServer } = await import('../mcp/mcp-server.js');
@@ -52,6 +78,7 @@ export async function serveMCP(options = {}) {
52
78
  export function createMCPCommand() {
53
79
  const mcpCommand = new Command('mcp');
54
80
  mcpCommand.description('Manage MCP servers or expose Code Buddy over MCP');
81
+ registerMCPImportCommand(mcpCommand);
55
82
  mcpCommand
56
83
  .command('serve')
57
84
  .description('Expose Code Buddy tools as an MCP server over stdio')
@@ -213,9 +240,9 @@ export function createMCPCommand() {
213
240
  }
214
241
  addMCPServer(preset);
215
242
  console.log(chalk.green(`✓ Added predefined MCP server: ${name}`));
216
- // Try to connect immediately
243
+ // Try to connect immediately, then drop the probe (same as `mcp test`).
244
+ const manager = getMCPManager();
217
245
  try {
218
- const manager = getMCPManager();
219
246
  await manager.addServer(preset);
220
247
  console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
221
248
  const tools = manager.getTools().filter(t => t.serverName === name);
@@ -225,6 +252,9 @@ export function createMCPCommand() {
225
252
  console.log(chalk.yellow(`⚠ Server saved but connection failed: ${getErrorMessage(connectError)}`));
226
253
  console.log(chalk.yellow(' Check your API key and try: buddy mcp test ' + name));
227
254
  }
255
+ finally {
256
+ await releaseMcpProbe(manager, name);
257
+ }
228
258
  return;
229
259
  }
230
260
  // Custom server
@@ -282,12 +312,16 @@ export function createMCPCommand() {
282
312
  };
283
313
  addMCPServer(config);
284
314
  console.log(chalk.green(`✓ Added MCP server: ${name}`));
285
- // Try to connect immediately
286
315
  const manager = getMCPManager();
287
- await manager.addServer(config);
288
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
289
- const tools = manager.getTools().filter(t => t.serverName === name);
290
- console.log(chalk.blue(` Available tools: ${tools.length}`));
316
+ try {
317
+ await manager.addServer(config);
318
+ console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
319
+ const tools = manager.getTools().filter(t => t.serverName === name);
320
+ console.log(chalk.blue(` Available tools: ${tools.length}`));
321
+ }
322
+ finally {
323
+ await releaseMcpProbe(manager, name);
324
+ }
291
325
  }
292
326
  catch (error) {
293
327
  logger.error(chalk.red(`Error adding MCP server: ${getErrorMessage(error)}`));
@@ -298,7 +332,8 @@ export function createMCPCommand() {
298
332
  mcpCommand
299
333
  .command('add-json <name> <json>')
300
334
  .description('Add an MCP server from JSON configuration')
301
- .action(async (name, jsonConfig) => {
335
+ .option('-y, --yes', 'skip confirmation for stdio MCP servers (required when stdin is not a TTY)')
336
+ .action(async (name, jsonConfig, options) => {
302
337
  try {
303
338
  let config;
304
339
  try {
@@ -333,20 +368,31 @@ export function createMCPCommand() {
333
368
  console.log(chalk.yellow('\nSecurity notice: This MCP server will execute a command on your system.'));
334
369
  console.log(chalk.yellow(` Command: ${serverConfig.transport.command} ${(serverConfig.transport.args || []).join(' ')}`));
335
370
  console.log(chalk.yellow(' Only add MCP servers from trusted sources.\n'));
336
- const confirmed = await confirmPrompt('Do you want to proceed? (y/N): ');
337
- if (!confirmed) {
338
- console.log('MCP server addition cancelled.');
339
- return;
371
+ const mode = stdioAddConfirmMode(options.yes === true);
372
+ if (mode === 'abort') {
373
+ logger.error(chalk.red('Error: stdin is not a TTY. Re-run with --yes to confirm adding this stdio MCP server.'));
374
+ process.exit(1);
375
+ }
376
+ if (mode === 'prompt') {
377
+ const confirmed = await confirmPrompt('Do you want to proceed? (y/N): ');
378
+ if (!confirmed) {
379
+ console.log('MCP server addition cancelled.');
380
+ return;
381
+ }
340
382
  }
341
383
  }
342
384
  addMCPServer(serverConfig);
343
385
  console.log(chalk.green(`✓ Added MCP server: ${name}`));
344
- // Try to connect immediately
345
386
  const manager = getMCPManager();
346
- await manager.addServer(serverConfig);
347
- console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
348
- const tools = manager.getTools().filter(t => t.serverName === name);
349
- console.log(chalk.blue(` Available tools: ${tools.length}`));
387
+ try {
388
+ await manager.addServer(serverConfig);
389
+ console.log(chalk.green(`✓ Connected to MCP server: ${name}`));
390
+ const tools = manager.getTools().filter(t => t.serverName === name);
391
+ console.log(chalk.blue(` Available tools: ${tools.length}`));
392
+ }
393
+ finally {
394
+ await releaseMcpProbe(manager, name);
395
+ }
350
396
  }
351
397
  catch (error) {
352
398
  logger.error(chalk.red(`Error adding MCP server: ${getErrorMessage(error)}`));
@@ -516,14 +562,13 @@ export function createMCPCommand() {
516
562
  process.exit(1);
517
563
  }
518
564
  finally {
519
- // `mcp test` is a probe, not a long-lived session. Always tear down the
520
- // transport so stdio children and their database/network handles do not
521
- // keep the CLI process alive after a successful discovery.
565
+ // Probe only: drop the client/stdio child so the CLI can exit.
522
566
  if (connected) {
523
- await manager.removeServer(name);
567
+ await releaseMcpProbe(manager, name);
524
568
  }
525
569
  }
526
570
  });
571
+ registerMCPInvocationCommands(mcpCommand);
527
572
  return mcpCommand;
528
573
  }
529
574
  //# sourceMappingURL=mcp.js.map
@@ -5,6 +5,11 @@
5
5
  * Supports running from YAML/JSON files, listing, validating, and status checks.
6
6
  */
7
7
  import { Command } from 'commander';
8
+ import type { PipelineConfig, ApprovalGateConfig } from '../workflows/pipeline.js';
9
+ /** Standalone CLI bridge; tool policy, trust and confirmations stay in ToolHandler. */
10
+ export declare function createPipelineRuntime(): Pick<PipelineConfig, 'toolExecutor' | 'approvalHandler'> & {
11
+ dispose(): Promise<void>;
12
+ };
8
13
  /**
9
14
  * Pipeline definition loaded from a file (YAML/JSON)
10
15
  */
@@ -14,10 +19,11 @@ export interface PipelineFileDefinition {
14
19
  version?: string;
15
20
  steps: Array<{
16
21
  name: string;
17
- type?: 'tool' | 'skill' | 'function' | 'transform';
22
+ type?: 'tool' | 'skill' | 'function' | 'transform' | 'approval';
18
23
  args?: Record<string, unknown>;
19
24
  timeout?: number;
20
25
  label?: string;
26
+ approvalGate?: Pick<ApprovalGateConfig, 'message' | 'timeoutMs'>;
21
27
  }>;
22
28
  config?: {
23
29
  maxSteps?: number;
@@ -6,6 +6,90 @@
6
6
  */
7
7
  import { Command } from 'commander';
8
8
  import { logger } from '../utils/logger.js';
9
+ /** Standalone CLI bridge; tool policy, trust and confirmations stay in ToolHandler. */
10
+ export function createPipelineRuntime() {
11
+ const controller = new AbortController();
12
+ let handler;
13
+ let marketplace;
14
+ let repair;
15
+ let service;
16
+ let readline;
17
+ let ownsListener = false;
18
+ const onConfirmation = (options) => {
19
+ void (async () => {
20
+ try {
21
+ const { createInterface } = await import('node:readline/promises');
22
+ readline = createInterface({ input: process.stdin, output: process.stderr });
23
+ process.stderr.write(`${JSON.stringify({ operation: options.operation, target: options.filename,
24
+ preview: options.diffPreview ?? options.content })}\n`);
25
+ const answer = await readline.question('Approve this operation? [y/N] ');
26
+ service?.confirmOperation(/^(y|yes|o|oui)$/i.test(answer.trim()));
27
+ }
28
+ catch {
29
+ service?.rejectOperation('Approval input closed');
30
+ }
31
+ finally {
32
+ readline?.close();
33
+ readline = undefined;
34
+ }
35
+ })();
36
+ };
37
+ const confirmations = async () => {
38
+ if (!service) {
39
+ const { ConfirmationService } = await import('../utils/confirmation-service.js');
40
+ service = ConfirmationService.getInstance();
41
+ if (process.stdin.isTTY && service.listenerCount('confirmation-requested') === 0) {
42
+ service.on('confirmation-requested', onConfirmation);
43
+ ownsListener = true;
44
+ }
45
+ }
46
+ return service;
47
+ };
48
+ return {
49
+ toolExecutor: async (name, args) => {
50
+ await confirmations();
51
+ if (!handler) {
52
+ const [{ ToolHandler }, { CheckpointManager }, { HooksManager }, { PluginMarketplace }, { RepairCoordinator }] = await Promise.all([
53
+ import('../agent/tool-handler.js'), import('../checkpoints/checkpoint-manager.js'),
54
+ import('../hooks/lifecycle-hooks.js'), import('../plugins/marketplace.js'),
55
+ import('../agent/execution/repair-coordinator.js'),
56
+ ]);
57
+ marketplace = new PluginMarketplace({ autoUpdate: false });
58
+ repair = new RepairCoordinator({ enabled: false });
59
+ handler = new ToolHandler({ checkpointManager: new CheckpointManager(),
60
+ hooksManager: new HooksManager(process.cwd()), marketplace, repairCoordinator: repair });
61
+ handler.setWorkingDirectory(process.cwd());
62
+ }
63
+ const { randomUUID } = await import('node:crypto');
64
+ const result = await handler.executeTool({ id: `pipeline_${randomUUID()}`, type: 'function',
65
+ function: { name, arguments: JSON.stringify(args) } }, { surface: 'cli', abortSignal: controller.signal });
66
+ return { success: result.success, output: result.output ?? '', error: result.error };
67
+ },
68
+ approvalHandler: async (gate) => {
69
+ const confirmation = await confirmations();
70
+ const timer = setTimeout(() => {
71
+ confirmation.rejectOperation('Pipeline approval timed out');
72
+ readline?.close();
73
+ }, gate.timeoutMs);
74
+ try {
75
+ const result = await confirmation.requestConfirmation({ operation: 'Approve pipeline step',
76
+ filename: gate.message, toolName: 'pipeline_approval', forcePrompt: true }, 'tool');
77
+ return { approved: result.confirmed, timestamp: new Date(), comment: result.feedback };
78
+ }
79
+ finally {
80
+ clearTimeout(timer);
81
+ }
82
+ },
83
+ dispose: async () => {
84
+ controller.abort();
85
+ if (ownsListener)
86
+ service?.off('confirmation-requested', onConfirmation);
87
+ readline?.close();
88
+ repair?.dispose();
89
+ await marketplace?.dispose();
90
+ },
91
+ };
92
+ }
9
93
  /**
10
94
  * Load a pipeline definition from a YAML or JSON file.
11
95
  * Uses lazy imports for yaml parsing.
@@ -86,8 +170,12 @@ export function validatePipelineDefinition(definition) {
86
170
  warnings.push(`Step ${i + 1}: duplicate step name "${step.name}"`);
87
171
  }
88
172
  stepNames.add(step.name);
89
- if (step.type && !['tool', 'skill', 'function', 'transform'].includes(step.type)) {
90
- errors.push(`Step ${i + 1} ("${step.name}"): invalid type "${step.type}" (must be tool, skill, function, or transform)`);
173
+ if (step.type && !['tool', 'skill', 'function', 'transform', 'approval'].includes(step.type)) {
174
+ errors.push(`Step ${i + 1} ("${step.name}"): invalid type "${step.type}" (must be tool, skill, function, transform, or approval)`);
175
+ }
176
+ if (step.approvalGate && (typeof step.approvalGate.message !== 'string' ||
177
+ !Number.isFinite(step.approvalGate.timeoutMs) || step.approvalGate.timeoutMs <= 0)) {
178
+ errors.push(`Step ${i + 1}: approvalGate requires a message and positive timeoutMs`);
91
179
  }
92
180
  if (step.timeout !== undefined && (typeof step.timeout !== 'number' || step.timeout <= 0)) {
93
181
  warnings.push(`Step ${i + 1} ("${step.name}"): timeout should be a positive number`);
@@ -117,6 +205,8 @@ export function createPipelineCommand() {
117
205
  .option('-t, --timeout <ms>', 'Override default step timeout in milliseconds')
118
206
  .option('--dry-run', 'Validate and show steps without executing')
119
207
  .action(async (file, options) => {
208
+ let runtime;
209
+ let compositor;
120
210
  try {
121
211
  console.log(`Loading pipeline from: ${file}`);
122
212
  const definition = await loadPipelineFile(file);
@@ -164,7 +254,9 @@ export function createPipelineCommand() {
164
254
  if (definition.config?.maxDurationMs) {
165
255
  config.maxDurationMs = definition.config.maxDurationMs;
166
256
  }
167
- const compositor = new PipelineCompositor(config);
257
+ runtime = createPipelineRuntime();
258
+ compositor = new PipelineCompositor({ ...config, toolExecutor: runtime.toolExecutor,
259
+ approvalHandler: runtime.approvalHandler });
168
260
  // Set up event listeners for progress
169
261
  compositor.on('step:start', (step, index) => {
170
262
  console.log(` [${index + 1}/${definition.steps.length}] Running: ${step.name}...`);
@@ -175,11 +267,13 @@ export function createPipelineCommand() {
175
267
  });
176
268
  // Convert file definition steps to PipelineStep format
177
269
  const steps = definition.steps.map(step => ({
178
- type: (step.type || 'tool'),
270
+ type: step.type || 'tool',
179
271
  name: step.name,
180
272
  args: step.args || {},
181
273
  timeout: step.timeout,
182
274
  label: step.label,
275
+ approvalGate: step.type === 'approval' ? { message: step.approvalGate?.message ?? step.name,
276
+ timeoutMs: step.approvalGate?.timeoutMs ?? 300000, requireExplicit: true } : undefined,
183
277
  }));
184
278
  console.log(`\nRunning pipeline: ${definition.name} (${steps.length} steps)`);
185
279
  const result = await compositor.execute(steps);
@@ -191,14 +285,17 @@ export function createPipelineCommand() {
191
285
  }
192
286
  else {
193
287
  console.error(`\nPipeline failed: ${result.error || 'Unknown error'}`);
194
- process.exit(1);
288
+ process.exitCode = 1;
195
289
  }
196
- compositor.dispose();
197
290
  }
198
291
  catch (error) {
199
292
  const msg = error instanceof Error ? error.message : String(error);
200
293
  logger.error(`Pipeline error: ${msg}`);
201
- process.exit(1);
294
+ process.exitCode = 1;
295
+ }
296
+ finally {
297
+ compositor?.dispose();
298
+ await runtime?.dispose();
202
299
  }
203
300
  });
204
301
  // List available pipeline definitions
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createResourcesCommand(): Command;
@@ -0,0 +1,64 @@
1
+ import fs from 'node:fs/promises';
2
+ import { Command } from 'commander';
3
+ import { ResourceCatalog, resourceSchema, selectionWarning } from '../fleet/resource-catalog.js';
4
+ export function createResourcesCommand() {
5
+ const command = new Command('resources').description('Explicit resource inventory and bounded read-only health probes (JSON output)');
6
+ const run = (action) => async () => {
7
+ try {
8
+ process.stdout.write(`${JSON.stringify(await action(), null, 2)}\n`);
9
+ }
10
+ catch (error) {
11
+ command.error(error instanceof Error ? error.message : 'RESOURCE_OPERATION_FAILED');
12
+ }
13
+ };
14
+ command.command('schema').description('Show the resource registration fields').action(() => {
15
+ process.stdout.write(`${JSON.stringify({ kinds: resourceSchema.shape.kind.options,
16
+ fields: ['id', 'kind', 'hostId', 'declaredCapabilities', 'endpointRef', 'healthPath', 'permissions', 'ttlMs', 'timeoutMs'],
17
+ endpointRef: 'Environment variable containing HTTP(S) origin; no embedded credentials, path, query or fragment',
18
+ permissions: { probe: false, use: false }, load: 'unknown (not collected)', usageConfirmed: false }, null, 2)}\n`);
19
+ });
20
+ command.command('add <file>').description('Register one explicit JSON resource; never scans the network').action(async (file) => {
21
+ await run(async () => {
22
+ const stat = await fs.stat(file);
23
+ if (!stat.isFile() || stat.size > 16384)
24
+ throw new Error('RESOURCE_INPUT_TOO_LARGE');
25
+ let input;
26
+ try {
27
+ input = JSON.parse(await fs.readFile(file, 'utf8'));
28
+ }
29
+ catch {
30
+ throw new Error('INVALID_RESOURCE_JSON');
31
+ }
32
+ return new ResourceCatalog().add(input);
33
+ })();
34
+ });
35
+ command.command('remove <id>').description('Remove an explicit registration and its observation').action(async (id) => {
36
+ await run(() => new ResourceCatalog().remove(id))();
37
+ });
38
+ command.command('list').description('List declarations and observation freshness; no network I/O').action(run(() => new ResourceCatalog().list()));
39
+ command.command('status <id>').description('Read one resource state; does not refresh observations').action(async (id) => {
40
+ await run(async () => {
41
+ const result = (await new ResourceCatalog().list()).find(e => e.resource.id === id);
42
+ if (!result)
43
+ throw new Error('RESOURCE_NOT_FOUND');
44
+ return result;
45
+ })();
46
+ });
47
+ command.command('probe <id>').description('Run one explicitly permitted, bounded GET health probe').action(async (id) => {
48
+ await run(() => new ResourceCatalog().probe(id))();
49
+ });
50
+ command.command('select <capability>').option('--kind <kind>', 'Required resource kind').description('Select fresh compatible resource; no task dispatch or automatic replay').action(async (capability, options) => {
51
+ await run(async () => {
52
+ const parsed = options.kind === undefined ? undefined : resourceSchema.shape.kind.safeParse(options.kind);
53
+ if (parsed && !parsed.success)
54
+ throw new Error('INVALID_RESOURCE_KIND');
55
+ const result = await new ResourceCatalog().select(capability, parsed?.data);
56
+ if (!result.selected)
57
+ process.exitCode = 2;
58
+ const warning = selectionWarning(result.selected);
59
+ return warning ? { ...result, warning } : result;
60
+ })();
61
+ });
62
+ return command;
63
+ }
64
+ //# sourceMappingURL=resources.js.map
@@ -134,11 +134,24 @@ export function registerSkillsCommands(program) {
134
134
  const all = hub.listWithIntegrity();
135
135
  const shown = opts.all ? all : all.filter((s) => s.enabled !== false);
136
136
  const health = buildSkillListHealth(all, shown);
137
- const usableCount = all.filter((skill) => skill.enabled !== false && skill.integrityOk).length;
137
+ const { readLocalSkillInventory } = await import('../../skills/local-inventory.js');
138
+ const inventory = await readLocalSkillInventory(all);
139
+ const availableSkills = inventory.entries.filter((skill) => skill.available);
140
+ const usableCount = availableSkills.filter((skill) => skill.source === 'hub').length;
138
141
  if (opts.json) {
139
- console.log(JSON.stringify({ count: shown.length, health, total: all.length, skills: shown }, null, 2));
142
+ console.log(JSON.stringify({ availableSkills, availableCount: availableSkills.length,
143
+ unavailableSkills: inventory.entries.filter((skill) => !skill.available),
144
+ discoveryErrors: inventory.errors,
145
+ count: shown.length, health, total: all.length, skills: shown }, null, 2));
140
146
  return;
141
147
  }
148
+ console.log(`\nAvailable local skills (${availableSkills.length}):`);
149
+ for (const skill of availableSkills) {
150
+ console.log(` + ${skill.name} (${skill.source})${skill.description ? ` — ${skill.description}` : ''}`);
151
+ }
152
+ if (inventory.errors.length > 0) {
153
+ console.log(`\n${inventory.errors.length} skill file(s) could not be loaded; use --json for details.`);
154
+ }
142
155
  if (shown.length === 0) {
143
156
  if (all.length === 0) {
144
157
  const { getBundledSkillsPath } = await import('../../skills/index.js');
@@ -280,26 +293,36 @@ export function registerSkillsCommands(program) {
280
293
  });
281
294
  skills
282
295
  .command('usage')
283
- .description('Show local usage telemetry, most-used first')
296
+ .description('Show local usage telemetry: hub invocations and view/use activity of every skill')
284
297
  .option('--json', 'output JSON')
285
298
  .action(async (opts) => {
286
299
  const { getSkillsHub } = await import('../../skills/hub.js');
300
+ const { listSkillActivity } = await import('../../skills/skill-usage-store.js');
287
301
  const summary = getSkillsHub().usageSummary();
302
+ const activity = listSkillActivity();
288
303
  if (opts.json) {
289
- console.log(JSON.stringify({ count: summary.length, skills: summary }, null, 2));
304
+ console.log(JSON.stringify({ count: summary.length, skills: summary, activityCount: activity.length, activity }, null, 2));
290
305
  return;
291
306
  }
292
- if (summary.length === 0) {
307
+ if (summary.length === 0 && activity.length === 0) {
293
308
  console.log('No skill usage recorded yet.');
294
309
  return;
295
310
  }
296
- console.log('\nSkill usage (most used first):');
297
- for (const skill of summary) {
298
- const u = skill.usage;
299
- const avg = u.averageDurationMs !== undefined ? `, avg ${Math.round(u.averageDurationMs)}ms` : '';
300
- console.log(` ${skill.name}: ${u.invocationCount} run(s), ${u.successCount} ok / ${u.failureCount} fail${avg}`);
301
- if (u.lastError)
302
- console.log(` last error: ${u.lastError}`);
311
+ if (summary.length > 0) {
312
+ console.log('\nSkill usage (most used first):');
313
+ for (const skill of summary) {
314
+ const u = skill.usage;
315
+ const avg = u.averageDurationMs !== undefined ? `, avg ${Math.round(u.averageDurationMs)}ms` : '';
316
+ console.log(` ${skill.name}: ${u.invocationCount} run(s), ${u.successCount} ok / ${u.failureCount} fail${avg}`);
317
+ if (u.lastError)
318
+ console.log(` last error: ${u.lastError}`);
319
+ }
320
+ }
321
+ if (activity.length > 0) {
322
+ console.log('\nSkill activity (most recent first):');
323
+ for (const entry of activity) {
324
+ console.log(` ${entry.skill}: ${entry.viewCount} view(s), ${entry.useCount} use(s), last ${entry.lastActivityAt}`);
325
+ }
303
326
  }
304
327
  console.log('');
305
328
  });
@@ -342,9 +342,12 @@ const devCommands = [
342
342
  {
343
343
  name: 'debug-issue',
344
344
  description: 'Help debug a code issue',
345
- prompt: `Help debug the described issue:
345
+ // A bare /debug-issue used to send "the described issue" with nothing
346
+ // described; the prompt now stands on its own with or without a symptom.
347
+ prompt: `Debug a problem in this project.
348
+ Reported symptom (empty if the user gave none): $ARGUMENTS
346
349
 
347
- 1. Gather information about the problem
350
+ 1. Gather information about the problem. Without a reported symptom, start from the working tree: git status --short, git diff for unstaged changes, git diff --cached for staged changes, then run the project's test script if one exists
348
351
  2. Analyze relevant code and logs
349
352
  3. Identify potential causes
350
353
  4. Suggest debugging steps
@@ -352,7 +355,10 @@ const devCommands = [
352
355
 
353
356
  Be systematic and thorough in your analysis.`,
354
357
  filePath: '',
355
- isBuiltin: true
358
+ isBuiltin: true,
359
+ arguments: [
360
+ { name: 'symptom', description: 'Error message or behaviour to debug (optional)', required: false }
361
+ ]
356
362
  },
357
363
  {
358
364
  name: 'refactor',
@@ -1309,6 +1315,13 @@ const agentControlCommands = [
1309
1315
  filePath: '',
1310
1316
  isBuiltin: true
1311
1317
  },
1318
+ {
1319
+ name: 'resources',
1320
+ description: 'List declared resources (RagChat, GPU, storage…) and observation freshness — read-only, no probe',
1321
+ prompt: '__RESOURCES__',
1322
+ filePath: '',
1323
+ isBuiltin: true
1324
+ },
1312
1325
  {
1313
1326
  name: 'new',
1314
1327
  description: 'Start a new conversation, optionally switching to a different model',
@@ -3,5 +3,7 @@
3
3
  *
4
4
  * Exports types, built-in commands, and utilities for the slash command system.
5
5
  */
6
- export type { SlashCommand, SlashCommandArgument, SlashCommandResult, SlashCommandCategory, CategorizedSlashCommand } from './types.js';
6
+ export type { SlashCommand, SlashCommandArgument, SlashCommandResult, SlashCommandCategory, CategorizedSlashCommand, SlashSurface, SlashAvailability } from './types.js';
7
7
  export { builtinCommands, getCommandsByCategory } from './builtin-commands.js';
8
+ export { CHANNEL_SLASH_SURFACES, channelPlatformsFor, COWORK_TOKEN_SURFACES, COWORK_UNAVAILABLE_REASON, coworkHeadlessAllowlist, coworkUiEffectTokens, isEngineToken, resolveSlashAvailability, withAvailability, } from './surfaces.js';
9
+ export type { ChannelSlashSpec, CoworkTokenMode, SlashCommandWithAvailability } from './surfaces.js';
@@ -5,4 +5,6 @@
5
5
  */
6
6
  // Built-in commands
7
7
  export { builtinCommands, getCommandsByCategory } from './builtin-commands.js';
8
+ // Per-surface availability (single declaration for CLI, Cowork and the wiki)
9
+ export { CHANNEL_SLASH_SURFACES, channelPlatformsFor, COWORK_TOKEN_SURFACES, COWORK_UNAVAILABLE_REASON, coworkHeadlessAllowlist, coworkUiEffectTokens, isEngineToken, resolveSlashAvailability, withAvailability, } from './surfaces.js';
8
10
  //# sourceMappingURL=index.js.map