@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
@@ -1,4 +1,7 @@
1
- import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
1
+ import { SSEClientTransport as SDKSSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
2
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
+ import { StdioClientTransport, getDefaultEnvironment } from "@modelcontextprotocol/sdk/client/stdio.js";
4
+ import { createOAuthProvider } from "./mcp-oauth-provider.js";
2
5
  import { EventEmitter } from "events";
3
6
  import axios from "axios";
4
7
  import { logger } from '../utils/logger.js';
@@ -14,7 +17,7 @@ export class StdioTransport {
14
17
  async connect() {
15
18
  // Create transport with environment variables to suppress verbose output
16
19
  const env = {
17
- ...process.env,
20
+ ...(this.config.inheritEnv === false ? getDefaultEnvironment() : process.env),
18
21
  ...this.config.env,
19
22
  // Try to suppress verbose output from mcp-remote
20
23
  MCP_REMOTE_QUIET: '1',
@@ -25,6 +28,7 @@ export class StdioTransport {
25
28
  const transportConfig = {
26
29
  command: this.config.command,
27
30
  args: this.config.args || [],
31
+ cwd: this.config.cwd,
28
32
  env,
29
33
  // The SDK default is stderr:'inherit', which lets a noisy MCP server
30
34
  // (startup banners, progress logs) write raw bytes into the CLI's own
@@ -46,10 +50,14 @@ export class StdioTransport {
46
50
  }
47
51
  async disconnect() {
48
52
  if (this.transport) {
49
- await this.transport.close();
50
- this.transport = undefined;
53
+ try {
54
+ await this.transport.close();
55
+ }
56
+ finally {
57
+ this.transport = undefined;
58
+ }
51
59
  }
52
- // The StdioClientTransport from the SDK is expected to terminate the child process.
60
+ // SDK close() ends stdin, then SIGTERM/SIGKILL the child it spawned.
53
61
  }
54
62
  getType() {
55
63
  return 'stdio';
@@ -69,6 +77,7 @@ export class HttpTransport extends EventEmitter {
69
77
  async connect() {
70
78
  this.client = axios.create({
71
79
  baseURL: this.config.url,
80
+ maxRedirects: 0,
72
81
  headers: {
73
82
  'Content-Type': 'application/json',
74
83
  ...this.config.headers
@@ -93,35 +102,28 @@ export class HttpTransport extends EventEmitter {
93
102
  return 'http';
94
103
  }
95
104
  }
96
- export class SSETransport extends EventEmitter {
105
+ export class SSETransport {
97
106
  config;
98
- connected = false;
107
+ transport;
99
108
  constructor(config) {
100
- super();
101
109
  this.config = config;
102
- if (!config.url) {
103
- throw new Error('URL is required for SSE MCP transport. Specify the server URL in your MCP configuration.');
104
- }
110
+ if (!config.url)
111
+ throw new Error('URL is required for SSE MCP transport');
105
112
  }
106
113
  async connect() {
107
- return new Promise((resolve, reject) => {
108
- try {
109
- // For Node.js environment, we'll use a simple HTTP-based approach
110
- // In a real implementation, you'd use a proper SSE library like 'eventsource'
111
- this.connected = true;
112
- resolve(new SSEClientTransport(this.config.url));
113
- }
114
- catch (error) {
115
- reject(error);
116
- }
114
+ this.transport = new SDKSSEClientTransport(new URL(this.config.url), {
115
+ requestInit: { headers: this.config.headers, redirect: 'error' },
116
+ eventSourceInit: { fetch: (url, init) => {
117
+ const headers = new Headers(init?.headers);
118
+ for (const [key, value] of Object.entries(this.config.headers ?? {}))
119
+ headers.set(key, value);
120
+ return fetch(url, { ...init, headers, redirect: 'error' });
121
+ } },
117
122
  });
123
+ return this.transport;
118
124
  }
119
- async disconnect() {
120
- this.connected = false;
121
- }
122
- getType() {
123
- return 'sse';
124
- }
125
+ async disconnect() { await this.transport?.close(); this.transport = undefined; }
126
+ getType() { return 'sse'; }
125
127
  }
126
128
  // Custom HTTP Transport implementation
127
129
  class HttpClientTransport extends EventEmitter {
@@ -156,105 +158,114 @@ class HttpClientTransport extends EventEmitter {
156
158
  }
157
159
  }
158
160
  }
159
- // Custom SSE Transport implementation
160
- class SSEClientTransport extends EventEmitter {
161
- url;
162
- onclose;
163
- onerror;
164
- onmessage;
165
- sessionId;
166
- constructor(url) {
167
- super();
168
- this.url = url;
169
- }
170
- async start() {
171
- // SSE transport is event-driven, so we're always "started"
172
- }
173
- async close() {
174
- // Nothing to close for basic SSE transport
175
- }
176
- async send(message, _options) {
177
- // For bidirectional communication over SSE, we typically use HTTP POST
178
- // for sending messages and SSE for receiving
179
- try {
180
- const response = await axios.post(this.url.replace('/sse', '/rpc'), message, {
181
- headers: { 'Content-Type': 'application/json' }
182
- });
183
- if (this.onmessage && response.data) {
184
- this.onmessage(response.data);
185
- }
186
- }
187
- catch (error) {
188
- const err = new Error(`SSE transport error: ${error}`);
189
- if (this.onerror) {
190
- this.onerror(err);
191
- }
192
- throw err;
193
- }
194
- }
195
- }
196
161
  export class StreamableHttpTransport extends EventEmitter {
197
162
  config;
198
- connected = false;
163
+ transport;
164
+ oauthProvider;
199
165
  constructor(config) {
200
166
  super();
201
167
  this.config = config;
202
- if (!config.url) {
168
+ if (!config.url)
203
169
  throw new Error('URL is required for streamable_http transport');
204
- }
205
170
  }
206
171
  async connect() {
207
- return new Promise((resolve, reject) => {
208
- try {
209
- this.connected = true;
210
- resolve(new StreamableHttpClientTransport(this.config.url, this.config.headers));
211
- }
212
- catch (error) {
213
- reject(error);
214
- }
172
+ const url = new URL(this.config.url);
173
+ if (!['http:', 'https:'].includes(url.protocol)) {
174
+ throw new Error('Streamable HTTP MCP requires an HTTP(S) URL');
175
+ }
176
+ const provider = this.config.auth?.type === 'oauth' ? createOAuthProvider(this.config.url, this.config.auth) : undefined;
177
+ this.oauthProvider = provider;
178
+ this.transport = new StreamableHTTPClientTransport(url, {
179
+ requestInit: { headers: this.config.headers, redirect: 'error' },
180
+ ...(provider ? { authProvider: provider } : {}),
215
181
  });
182
+ provider?.attachTransport(this.transport);
183
+ return this.transport;
216
184
  }
217
185
  async disconnect() {
218
- this.connected = false;
186
+ this.oauthProvider?.abortAuthorization();
187
+ this.oauthProvider = undefined;
188
+ const transport = this.transport;
189
+ this.transport = undefined;
190
+ await transport?.close();
219
191
  }
220
192
  getType() {
221
193
  return 'streamable_http';
222
194
  }
223
195
  }
224
- // Custom Streamable HTTP Transport implementation for GitHub Copilot MCP
225
- class StreamableHttpClientTransport extends EventEmitter {
226
- url;
227
- headers;
228
- onclose;
229
- onerror;
230
- onmessage;
231
- sessionId;
232
- constructor(url, headers) {
233
- super();
234
- this.url = url;
235
- this.headers = headers;
236
- }
237
- async start() {
238
- // Streamable HTTP transport is connection-less, so we're always "started"
239
- }
240
- async close() {
241
- // Nothing to close for streamable HTTP transport
196
+ /** Resolve references only at connection time; missing credentials fail closed. */
197
+ export function resolveMCPTransport(config) {
198
+ const resolve = (value) => value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, key) => {
199
+ const result = process.env[key];
200
+ if (!result)
201
+ throw new Error(`Missing MCP environment reference: ${key}`);
202
+ return result;
203
+ });
204
+ const map = (values) => values && Object.fromEntries(Object.entries(values).map(([k, v]) => [k, resolve(v)]));
205
+ const resolved = { ...config, command: config.command && resolve(config.command), cwd: config.cwd && resolve(config.cwd),
206
+ args: config.args?.map(resolve), env: map(config.env), headers: map(config.headers), url: config.url && resolve(config.url) };
207
+ if (resolved.url) {
208
+ let url;
209
+ try {
210
+ url = new URL(resolved.url);
211
+ }
212
+ catch {
213
+ throw new Error('Invalid MCP endpoint configuration');
214
+ }
215
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash)
216
+ throw new Error('MCP requires HTTP(S) without embedded credentials, query or fragment');
242
217
  }
243
- async send(_message, _options) {
244
- logger.warn('StreamableHttpTransport: SSE endpoints require persistent connections, not suitable for MCP request-response pattern');
245
- logger.debug('StreamableHttpTransport: Message that would be sent', { message: _message });
246
- // For now, throw an error to indicate the transport type is not compatible
247
- // with the MCP protocol's request-response pattern
248
- throw new Error('StreamableHttpTransport: SSE endpoints are not compatible with MCP request-response pattern. GitHub Copilot MCP may require a different integration approach.');
218
+ if (config.auth) {
219
+ const auth = { ...config.auth,
220
+ serverId: config.auth.serverId && resolve(config.auth.serverId),
221
+ clientId: config.auth.clientId && resolve(config.auth.clientId),
222
+ clientMetadataUrl: config.auth.clientMetadataUrl && resolve(config.auth.clientMetadataUrl),
223
+ redirectUri: config.auth.redirectUri && resolve(config.auth.redirectUri) };
224
+ if (auth.redirectUri) {
225
+ // The authorization code must only ever come back to the local callback server.
226
+ let redirect;
227
+ try {
228
+ redirect = new URL(auth.redirectUri);
229
+ }
230
+ catch {
231
+ throw new Error('MCP OAuth redirectUri must be a loopback http URL');
232
+ }
233
+ // Hostname localhost is allowed so a CIMD document's redirect_uris can match.
234
+ // The callback server still binds 127.0.0.1 only — a browser that resolves
235
+ // localhost to ::1 will not hit it. Use 127.0.0.1 when the metadata says so.
236
+ if (redirect.protocol !== 'http:' || !['127.0.0.1', 'localhost'].includes(redirect.hostname))
237
+ throw new Error('MCP OAuth redirectUri must be a loopback http URL');
238
+ }
239
+ if (auth.clientMetadataUrl) {
240
+ let meta;
241
+ try {
242
+ meta = new URL(auth.clientMetadataUrl);
243
+ }
244
+ catch {
245
+ throw new Error('MCP OAuth clientMetadataUrl must be an https URL with a document path');
246
+ }
247
+ if (meta.protocol !== 'https:' || meta.pathname === '/')
248
+ throw new Error('MCP OAuth clientMetadataUrl must be an https URL with a document path');
249
+ }
250
+ return { ...resolved, auth };
249
251
  }
252
+ return resolved;
250
253
  }
251
- export function createTransport(config) {
254
+ export function createTransport(input) {
255
+ const config = resolveMCPTransport(input);
256
+ if (config.auth?.type === 'oauth' && config.type !== 'streamable_http') {
257
+ throw new Error(`MCP OAuth is only supported on streamable_http (got ${config.type}); refusing to connect without the authProvider.`);
258
+ }
252
259
  switch (config.type) {
253
260
  case 'stdio':
254
261
  return new StdioTransport(config);
255
262
  case 'http':
263
+ logger.warn('MCP http /rpc transport is deprecated; use legacy_rpc explicitly or streamable_http for MCP HTTP');
264
+ return new HttpTransport(config);
265
+ case 'legacy_rpc':
256
266
  return new HttpTransport(config);
257
267
  case 'sse':
268
+ case 'sse_sdk':
258
269
  return new SSETransport(config);
259
270
  case 'streamable_http':
260
271
  return new StreamableHttpTransport(config);
@@ -15,6 +15,11 @@ export interface MCPServerConfig {
15
15
  maxRetries?: number;
16
16
  /** Optional: Enable/disable this server (default: true) */
17
17
  enabled?: boolean;
18
+ /** Exact names and star globs; exclusions win. Empty include denies every tool. */
19
+ toolFilter?: {
20
+ include?: string[];
21
+ exclude?: string[];
22
+ };
18
23
  }
19
24
  export type ServerStatus = 'connecting' | 'connected' | 'disconnected' | 'error';
20
25
  export interface MCPTool {
@@ -473,12 +473,6 @@ export declare const comfyUIRecipeSchema: z.ZodObject<{
473
473
  name?: string | undefined;
474
474
  url?: string | undefined;
475
475
  };
476
- schemaVersion: 1;
477
- fallback: {
478
- id: string;
479
- reason?: string | undefined;
480
- version?: string | undefined;
481
- }[];
482
476
  resources: {
483
477
  tier: "high" | "low" | "balanced" | "extreme";
484
478
  maxConcurrency: number;
@@ -486,6 +480,12 @@ export declare const comfyUIRecipeSchema: z.ZodObject<{
486
480
  minRamMiB: number;
487
481
  estimatedSeconds?: number | undefined;
488
482
  };
483
+ schemaVersion: 1;
484
+ fallback: {
485
+ id: string;
486
+ reason?: string | undefined;
487
+ version?: string | undefined;
488
+ }[];
489
489
  bindings: {
490
490
  prompt: {
491
491
  input: string;
@@ -573,7 +573,6 @@ export declare const comfyUIRecipeSchema: z.ZodObject<{
573
573
  name?: string | undefined;
574
574
  url?: string | undefined;
575
575
  };
576
- schemaVersion: 1;
577
576
  resources: {
578
577
  tier: "high" | "low" | "balanced" | "extreme";
579
578
  minVramMiB: number;
@@ -581,6 +580,7 @@ export declare const comfyUIRecipeSchema: z.ZodObject<{
581
580
  maxConcurrency?: number | undefined;
582
581
  estimatedSeconds?: number | undefined;
583
582
  };
583
+ schemaVersion: 1;
584
584
  bindings: {
585
585
  prompt: {
586
586
  input: string;
@@ -63,8 +63,18 @@ export declare const ReconciliationActionSchema: z.ZodObject<{
63
63
  } | undefined;
64
64
  }>;
65
65
  export type ReconciliationAction = z.infer<typeof ReconciliationActionSchema>;
66
+ /** Keep concurrent command sessions on their own provider, including an explicit offline scope. */
67
+ export declare function withFactsMemorySessionClient<T>(client: CodeBuddyClient | null, action: () => T): T;
68
+ /**
69
+ * Async generators execute on next/return/throw, not when they are created.
70
+ * Scope every resumption so model/tool/cleanup work belongs to this agent,
71
+ * while consumers outside a yielded event keep their own async context.
72
+ */
73
+ export declare function bindFactsMemorySession<T>(client: CodeBuddyClient, iterator: AsyncGenerator<T, void, unknown>): AsyncGenerator<T, void, unknown>;
74
+ export declare function setFactsMemorySessionClient(client: CodeBuddyClient | null): void;
66
75
  export declare class FactsMemoryService {
67
- private client;
76
+ private readonly explicitClient;
77
+ private fallbackClient;
68
78
  constructor(client?: CodeBuddyClient);
69
79
  isAvailable(): Promise<boolean>;
70
80
  private getClient;
@@ -1,3 +1,4 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
1
2
  import { z } from 'zod';
2
3
  import { logger } from '../utils/logger.js';
3
4
  import { CodeBuddyClient } from '../codebuddy/client.js';
@@ -30,20 +31,58 @@ export const ReconciliationActionSchema = z.object({
30
31
  targetIndex: z.number().optional(),
31
32
  fact: FactSchema.optional()
32
33
  });
34
+ /**
35
+ * Client of the live session (the provider and endpoint the user actually
36
+ * started with). Without it, reconciliation fell back to environment
37
+ * auto-detection and could send project memories to a different, cloud
38
+ * provider than the local session (e.g. xAI because GROK_API_KEY was set while
39
+ * the CLI ran on --base-url http://127.0.0.1:11434/v1).
40
+ */
41
+ let sessionClient = null;
42
+ const sessionScope = new AsyncLocalStorage();
43
+ /** Keep concurrent command sessions on their own provider, including an explicit offline scope. */
44
+ export function withFactsMemorySessionClient(client, action) {
45
+ return sessionScope.run({ client }, action);
46
+ }
47
+ /**
48
+ * Async generators execute on next/return/throw, not when they are created.
49
+ * Scope every resumption so model/tool/cleanup work belongs to this agent,
50
+ * while consumers outside a yielded event keep their own async context.
51
+ */
52
+ export function bindFactsMemorySession(client, iterator) {
53
+ return {
54
+ next(...args) { return withFactsMemorySessionClient(client, () => iterator.next(...args)); },
55
+ return(value) { return withFactsMemorySessionClient(client, () => iterator.return(value)); },
56
+ throw(error) { return withFactsMemorySessionClient(client, () => iterator.throw(error)); },
57
+ [Symbol.asyncIterator]() { return this; },
58
+ async [Symbol.asyncDispose]() {
59
+ await withFactsMemorySessionClient(client, () => iterator.return());
60
+ },
61
+ };
62
+ }
63
+ export function setFactsMemorySessionClient(client) {
64
+ sessionClient = client;
65
+ }
33
66
  export class FactsMemoryService {
34
- client = null;
67
+ explicitClient;
68
+ fallbackClient = null;
35
69
  constructor(client) {
36
- if (client) {
37
- this.client = client;
38
- }
70
+ this.explicitClient = client ?? null;
39
71
  }
40
72
  async isAvailable() {
41
73
  const client = await this.getClient();
42
74
  return client !== null;
43
75
  }
44
76
  async getClient() {
45
- if (this.client)
46
- return this.client;
77
+ if (this.explicitClient)
78
+ return this.explicitClient;
79
+ const scoped = sessionScope.getStore();
80
+ if (scoped)
81
+ return scoped.client;
82
+ if (sessionClient)
83
+ return sessionClient;
84
+ if (this.fallbackClient)
85
+ return this.fallbackClient;
47
86
  // Skip auto-detecting client in unit tests to prevent timeouts/real API calls
48
87
  if (process.env.NODE_ENV === 'test' || process.env.VITEST) {
49
88
  return null;
@@ -53,8 +92,8 @@ export class FactsMemoryService {
53
92
  logger.warn('[FactsMemory] No LLM provider configuration found.');
54
93
  return null;
55
94
  }
56
- this.client = new CodeBuddyClient(detected.apiKey, detected.defaultModel, detected.baseURL);
57
- return this.client;
95
+ this.fallbackClient = new CodeBuddyClient(detected.apiKey, detected.defaultModel, detected.baseURL);
96
+ return this.fallbackClient;
58
97
  }
59
98
  /**
60
99
  * Extract atom facts from a conversation or context block.
@@ -72,7 +72,7 @@ export interface MemoryCandidateStats {
72
72
  total: number;
73
73
  byStatus: Record<MemoryCandidateStatus, number>;
74
74
  }
75
- export declare function getMemoryCandidateQueue(workDir?: string): MemoryCandidateQueue;
75
+ export declare function getMemoryCandidateQueue(workDir?: string, botId?: string): MemoryCandidateQueue;
76
76
  export declare function resetMemoryCandidateQueues(): void;
77
77
  export declare class MemoryCandidateQueue {
78
78
  private workDir;
@@ -80,7 +80,7 @@ export declare class MemoryCandidateQueue {
80
80
  private filePath;
81
81
  private candidates;
82
82
  private loaded;
83
- constructor(workDir?: string, memoryManager?: PersistentMemoryManager | undefined);
83
+ constructor(workDir?: string, memoryManager?: PersistentMemoryManager | undefined, botId?: string);
84
84
  propose(input: ProposeMemoryCandidateInput): ProposeMemoryCandidateResult;
85
85
  list(status?: MemoryCandidateStatus): MemoryCandidate[];
86
86
  get(id: string): MemoryCandidate | null;
@@ -22,10 +22,10 @@ const VALID_CATEGORIES = [
22
22
  'custom',
23
23
  ];
24
24
  const registry = new Map();
25
- export function getMemoryCandidateQueue(workDir = process.cwd()) {
26
- const key = path.resolve(workDir);
25
+ export function getMemoryCandidateQueue(workDir = process.cwd(), botId) {
26
+ const key = JSON.stringify([path.resolve(workDir), botId ?? '']);
27
27
  if (!registry.has(key)) {
28
- registry.set(key, new MemoryCandidateQueue(key));
28
+ registry.set(key, new MemoryCandidateQueue(path.resolve(workDir), botId ? getMemoryManager(undefined, botId, workDir) : undefined, botId));
29
29
  if (registry.size > 20) {
30
30
  const firstKey = registry.keys().next().value;
31
31
  if (firstKey)
@@ -43,10 +43,10 @@ export class MemoryCandidateQueue {
43
43
  filePath;
44
44
  candidates = [];
45
45
  loaded = false;
46
- constructor(workDir = process.cwd(), memoryManager) {
46
+ constructor(workDir = process.cwd(), memoryManager, botId) {
47
47
  this.workDir = workDir;
48
48
  this.memoryManager = memoryManager;
49
- this.filePath = path.join(workDir, '.codebuddy', 'memory-candidates.json');
49
+ this.filePath = path.join(workDir, '.codebuddy', botId ? `memory-candidates-${encodeURIComponent(botId)}.json` : 'memory-candidates.json');
50
50
  }
51
51
  propose(input) {
52
52
  this.load();
@@ -122,7 +122,7 @@ export class MemoryCandidateQueue {
122
122
  throw new Error('Accepted memory key cannot be empty.');
123
123
  if (!value)
124
124
  throw new Error('Accepted memory value cannot be empty.');
125
- const manager = this.memoryManager ?? getMemoryManager();
125
+ const manager = this.memoryManager ?? getMemoryManager(undefined, undefined, this.workDir);
126
126
  await manager.initialize();
127
127
  const write = await manager.remember(key, value, {
128
128
  scope,
@@ -53,6 +53,15 @@ export interface MemoryWriteResult {
53
53
  category?: MemoryCategory;
54
54
  usage: MemoryUsage;
55
55
  message: string;
56
+ /**
57
+ * Outcome of the optional LLM fact reconciliation, separate from the primary
58
+ * write: `failed` means the memory was still written directly and existing
59
+ * memories were restored unchanged.
60
+ */
61
+ reconciliation?: {
62
+ status: 'applied' | 'skipped' | 'failed';
63
+ reason?: string;
64
+ };
56
65
  }
57
66
  export declare class MemoryWriteRejectedError extends Error {
58
67
  readonly code: 'memory_limit_exceeded' | 'memory_security_rejected';
@@ -164,6 +173,8 @@ export declare class PersistentMemoryManager extends EventEmitter {
164
173
  * poking the private maps. Does NOT reinforce (unlike getRelevantMemories).
165
174
  */
166
175
  listMemories(scope: MemoryScope): Memory[];
176
+ /** Guard the result, including model renames/omissions, rather than trusting DELETE alone. */
177
+ private guardReconciliation;
167
178
  /**
168
179
  * Ebbinghaus forgetting pass (recoverable): memories whose retention decayed
169
180
  * below the threshold are appended to a sibling `*.archive.md`, then removed.
@@ -250,12 +261,6 @@ export declare class PersistentMemoryManager extends EventEmitter {
250
261
  };
251
262
  private assertScopeReadable;
252
263
  }
253
- /**
254
- * Get the memory manager. With no `botId`, returns the global singleton (default
255
- * — CLI / desktop / server behavior unchanged). With a `botId` (multi-bot
256
- * channels), returns a per-bot instance whose memory files live under
257
- * `~/.codebuddy/bots/<botId>/`, so bots never share each other's `remember` facts.
258
- */
259
- export declare function getMemoryManager(config?: Partial<MemoryConfig>, botId?: string): PersistentMemoryManager;
264
+ export declare function getMemoryManager(config?: Partial<MemoryConfig>, botId?: string, cwd?: string): PersistentMemoryManager;
260
265
  export declare function resetMemoryManagerForTests(): void;
261
- export declare function initializeMemory(config?: Partial<MemoryConfig>): Promise<PersistentMemoryManager>;
266
+ export declare function initializeMemory(config?: Partial<MemoryConfig>, cwd?: string): Promise<PersistentMemoryManager>;