@ouro.bot/cli 0.1.0-alpha.70 → 0.1.0-alpha.701

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 (501) hide show
  1. package/README.md +133 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +4461 -14
  13. package/dist/a2a/card.js +57 -0
  14. package/dist/a2a/client.js +180 -0
  15. package/dist/a2a/config.js +50 -0
  16. package/dist/a2a/delegation-stores.js +56 -0
  17. package/dist/a2a/did-resolution.js +93 -0
  18. package/dist/a2a/identity.js +170 -0
  19. package/dist/a2a/inbound-share.js +107 -0
  20. package/dist/a2a/mission-result-wire.js +196 -0
  21. package/dist/a2a/onboarding.js +115 -0
  22. package/dist/a2a/pin-store.js +132 -0
  23. package/dist/a2a/seen-ledger.js +120 -0
  24. package/dist/a2a/server.js +604 -0
  25. package/dist/a2a/task-store.js +69 -0
  26. package/dist/a2a/transport.js +45 -0
  27. package/dist/a2a/types.js +3 -0
  28. package/dist/arc/attention-types.js +8 -0
  29. package/dist/arc/cares.js +144 -0
  30. package/dist/arc/episodes.js +118 -0
  31. package/dist/arc/evolution.js +490 -0
  32. package/dist/arc/flight-recorder.js +928 -0
  33. package/dist/arc/intentions.js +134 -0
  34. package/dist/arc/json-store.js +117 -0
  35. package/dist/arc/obligations.js +348 -0
  36. package/dist/arc/packets.js +336 -0
  37. package/dist/arc/presence.js +185 -0
  38. package/dist/arc/task-lifecycle.js +57 -0
  39. package/dist/commerce/store.js +755 -0
  40. package/dist/commerce/types.js +3 -0
  41. package/dist/heart/active-work.js +867 -43
  42. package/dist/heart/agent-entry.js +190 -3
  43. package/dist/heart/attachments/image-normalize.js +194 -0
  44. package/dist/heart/attachments/materialize.js +97 -0
  45. package/dist/heart/attachments/originals.js +88 -0
  46. package/dist/heart/attachments/render.js +29 -0
  47. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  48. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  49. package/dist/heart/attachments/sources/index.js +16 -0
  50. package/dist/heart/attachments/store.js +103 -0
  51. package/dist/heart/attachments/types.js +93 -0
  52. package/dist/heart/auth/auth-flow.js +479 -0
  53. package/dist/heart/autonomy-budget.js +434 -0
  54. package/dist/heart/awaiting/await-alert.js +146 -0
  55. package/dist/heart/awaiting/await-expiry.js +108 -0
  56. package/dist/heart/awaiting/await-loader.js +91 -0
  57. package/dist/heart/awaiting/await-parser.js +141 -0
  58. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  59. package/dist/heart/awaiting/await-scheduler.js +378 -0
  60. package/dist/heart/background-operations.js +281 -0
  61. package/dist/heart/bridges/manager.js +137 -17
  62. package/dist/heart/bridges/store.js +14 -2
  63. package/dist/heart/bundle-state.js +168 -0
  64. package/dist/heart/commitments.js +135 -0
  65. package/dist/heart/config-registry.js +331 -0
  66. package/dist/heart/config.js +119 -127
  67. package/dist/heart/context-loss-gauntlet.js +354 -0
  68. package/dist/heart/context-loss-sentinel.js +1155 -0
  69. package/dist/heart/core.js +1306 -278
  70. package/dist/heart/cross-chat-delivery.js +8 -22
  71. package/dist/heart/daemon/agent-config-check.js +451 -0
  72. package/dist/heart/daemon/agent-discovery.js +185 -3
  73. package/dist/heart/daemon/agent-service.js +523 -0
  74. package/dist/heart/daemon/agentic-repair.js +547 -0
  75. package/dist/heart/daemon/await-private-wake.js +59 -0
  76. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  77. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  78. package/dist/heart/daemon/cadence.js +180 -0
  79. package/dist/heart/daemon/cli-defaults.js +825 -0
  80. package/dist/heart/daemon/cli-desk.js +322 -0
  81. package/dist/heart/daemon/cli-exec.js +8142 -0
  82. package/dist/heart/daemon/cli-help.js +675 -0
  83. package/dist/heart/daemon/cli-parse.js +2461 -0
  84. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  85. package/dist/heart/daemon/cli-render.js +770 -0
  86. package/dist/heart/daemon/cli-types.js +8 -0
  87. package/dist/heart/daemon/connect-bay.js +323 -0
  88. package/dist/heart/daemon/daemon-cli.js +29 -1930
  89. package/dist/heart/daemon/daemon-entry.js +822 -10
  90. package/dist/heart/daemon/daemon-health.js +176 -0
  91. package/dist/heart/daemon/daemon-rollup.js +57 -0
  92. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  93. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  94. package/dist/heart/daemon/daemon.js +1264 -84
  95. package/dist/heart/daemon/dns-workflow.js +394 -0
  96. package/dist/heart/daemon/doctor-types.js +8 -0
  97. package/dist/heart/daemon/doctor.js +1126 -0
  98. package/dist/heart/daemon/habit-private-wake.js +56 -0
  99. package/dist/heart/daemon/health-monitor.js +142 -11
  100. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  101. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  102. package/dist/heart/daemon/http-health-probe.js +80 -0
  103. package/dist/heart/daemon/human-command-screens.js +234 -0
  104. package/dist/heart/daemon/human-readiness.js +114 -0
  105. package/dist/heart/daemon/inner-status.js +78 -0
  106. package/dist/heart/daemon/interactive-repair.js +394 -0
  107. package/dist/heart/daemon/launchd.js +37 -8
  108. package/dist/heart/daemon/log-tailer.js +79 -10
  109. package/dist/heart/daemon/logs-prune.js +110 -0
  110. package/dist/heart/daemon/mcp-canary.js +297 -0
  111. package/dist/heart/daemon/message-router.js +45 -5
  112. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  113. package/dist/heart/daemon/os-cron-deps.js +135 -0
  114. package/dist/heart/daemon/os-cron.js +22 -14
  115. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  116. package/dist/heart/daemon/ouro-entry.js +3 -1
  117. package/dist/heart/daemon/plugin-cli.js +432 -0
  118. package/dist/heart/daemon/process-manager.js +519 -40
  119. package/dist/heart/daemon/provider-discovery.js +137 -0
  120. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  121. package/dist/heart/daemon/pulse.js +511 -0
  122. package/dist/heart/daemon/readiness-repair.js +365 -0
  123. package/dist/heart/daemon/run-hooks.js +2 -0
  124. package/dist/heart/daemon/runtime-logging.js +41 -14
  125. package/dist/heart/daemon/runtime-metadata.js +2 -30
  126. package/dist/heart/daemon/safe-mode.js +161 -0
  127. package/dist/heart/daemon/sense-manager.js +670 -48
  128. package/dist/heart/daemon/session-id-resolver.js +131 -0
  129. package/dist/heart/daemon/skill-management-installer.js +1 -1
  130. package/dist/heart/daemon/socket-client.js +171 -12
  131. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  132. package/dist/heart/daemon/startup-tui.js +338 -0
  133. package/dist/heart/daemon/task-scheduler.js +117 -39
  134. package/dist/heart/daemon/terminal-ui.js +499 -0
  135. package/dist/heart/daemon/thoughts.js +255 -43
  136. package/dist/heart/daemon/up-progress.js +366 -0
  137. package/dist/heart/daemon/vault-items.js +56 -0
  138. package/dist/heart/delegation.js +1 -4
  139. package/dist/heart/external-events/router.js +121 -0
  140. package/dist/heart/habits/habit-migration.js +189 -0
  141. package/dist/heart/habits/habit-parser.js +214 -0
  142. package/dist/heart/habits/habit-runtime-state.js +114 -0
  143. package/dist/heart/habits/habit-scheduler.js +431 -0
  144. package/dist/heart/habits/habit-session-summary.js +318 -0
  145. package/dist/heart/habits/habit-session.js +617 -0
  146. package/dist/heart/{daemon → hatch}/hatch-flow.js +51 -60
  147. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  148. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  149. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  150. package/dist/heart/identity.js +174 -59
  151. package/dist/heart/kept-notes.js +289 -0
  152. package/dist/heart/kicks.js +1 -1
  153. package/dist/heart/machine-identity.js +161 -0
  154. package/dist/heart/mail-import-discovery.js +353 -0
  155. package/dist/heart/mailbox/mailbox-http-hooks.js +96 -0
  156. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  157. package/dist/heart/mailbox/mailbox-http-routes.js +375 -0
  158. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  159. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  160. package/dist/heart/mailbox/mailbox-http.js +99 -0
  161. package/dist/heart/mailbox/mailbox-read.js +37 -0
  162. package/dist/heart/mailbox/mailbox-types.js +27 -0
  163. package/dist/heart/mailbox/mailbox-view.js +197 -0
  164. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  165. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  166. package/dist/heart/mailbox/readers/mail.js +375 -0
  167. package/dist/heart/mailbox/readers/runtime-readers.js +815 -0
  168. package/dist/heart/mailbox/readers/sessions.js +232 -0
  169. package/dist/heart/mailbox/readers/shared.js +111 -0
  170. package/dist/heart/mcp/mcp-server.js +696 -0
  171. package/dist/heart/migrate-config.js +100 -0
  172. package/dist/heart/model-capabilities.js +11 -0
  173. package/dist/heart/orientation-frame.js +217 -0
  174. package/dist/heart/platform.js +81 -0
  175. package/dist/heart/primitives.js +1 -1
  176. package/dist/heart/private-runtime/decision-renderer.js +156 -0
  177. package/dist/heart/private-runtime/index.js +18 -0
  178. package/dist/heart/private-runtime/ledger.js +218 -0
  179. package/dist/heart/private-runtime/policy.js +214 -0
  180. package/dist/heart/private-runtime/types.js +2 -0
  181. package/dist/heart/progress-story.js +1 -1
  182. package/dist/heart/provider-attempt.js +134 -0
  183. package/dist/heart/provider-binding-resolver.js +273 -0
  184. package/dist/heart/provider-credentials.js +441 -0
  185. package/dist/heart/provider-failover.js +311 -0
  186. package/dist/heart/provider-models.js +81 -0
  187. package/dist/heart/provider-ping.js +262 -0
  188. package/dist/heart/provider-readiness-cache.js +119 -0
  189. package/dist/heart/provider-visibility.js +188 -0
  190. package/dist/heart/providers/anthropic-token.js +131 -0
  191. package/dist/heart/providers/anthropic.js +139 -52
  192. package/dist/heart/providers/azure.js +23 -11
  193. package/dist/heart/providers/error-classification.js +127 -0
  194. package/dist/heart/providers/github-copilot.js +34 -38
  195. package/dist/heart/providers/minimax-vlm.js +189 -0
  196. package/dist/heart/providers/minimax.js +26 -8
  197. package/dist/heart/providers/openai-codex-token.js +349 -0
  198. package/dist/heart/providers/openai-codex.js +55 -40
  199. package/dist/heart/run-ledger.js +247 -0
  200. package/dist/heart/runtime-capability-check.js +170 -0
  201. package/dist/heart/runtime-credentials.js +398 -0
  202. package/dist/heart/runtime-cwd.js +87 -0
  203. package/dist/heart/sense-truth.js +20 -4
  204. package/dist/heart/session-activity.js +90 -24
  205. package/dist/heart/session-events.js +1133 -0
  206. package/dist/heart/session-playback-cli-main.js +5 -0
  207. package/dist/heart/session-playback-cli.js +36 -0
  208. package/dist/heart/session-playback.js +231 -0
  209. package/dist/heart/session-stats-cli-main.js +5 -0
  210. package/dist/heart/session-stats.js +182 -0
  211. package/dist/heart/session-transcript.js +133 -0
  212. package/dist/heart/start-of-turn-packet.js +365 -0
  213. package/dist/heart/streaming.js +44 -27
  214. package/dist/heart/structured-output.js +196 -0
  215. package/dist/heart/sync-classification.js +176 -0
  216. package/dist/heart/sync.js +449 -0
  217. package/dist/heart/target-resolution.js +11 -7
  218. package/dist/heart/tempo.js +93 -0
  219. package/dist/heart/temporal-view.js +41 -0
  220. package/dist/heart/timeouts.js +101 -0
  221. package/dist/heart/tool-activity-callbacks.js +59 -0
  222. package/dist/heart/tool-description.js +155 -0
  223. package/dist/heart/tool-friction.js +55 -0
  224. package/dist/heart/tool-loop.js +200 -0
  225. package/dist/heart/turn-context.js +472 -0
  226. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  227. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  228. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  229. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  230. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  231. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  232. package/dist/heart/versioning/update-hooks.js +154 -0
  233. package/dist/heart/work-card.js +380 -0
  234. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  235. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  236. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  237. package/dist/mailbox-ui/index.html +16 -0
  238. package/dist/mailroom/attention.js +167 -0
  239. package/dist/mailroom/autonomy.js +209 -0
  240. package/dist/mailroom/blob-store.js +715 -0
  241. package/dist/mailroom/body-cache.js +61 -0
  242. package/dist/mailroom/core.js +788 -0
  243. package/dist/mailroom/entry.js +160 -0
  244. package/dist/mailroom/file-store.js +568 -0
  245. package/dist/mailroom/mbox-import.js +393 -0
  246. package/dist/mailroom/migration.js +164 -0
  247. package/dist/mailroom/outbound.js +380 -0
  248. package/dist/mailroom/policy.js +263 -0
  249. package/dist/mailroom/reader.js +233 -0
  250. package/dist/mailroom/search-cache.js +334 -0
  251. package/dist/mailroom/search-relevance.js +319 -0
  252. package/dist/mailroom/smtp-ingress.js +176 -0
  253. package/dist/mailroom/source-state.js +176 -0
  254. package/dist/mailroom/thread.js +109 -0
  255. package/dist/mailroom/travel-extract.js +89 -0
  256. package/dist/mind/bundle-manifest.js +24 -2
  257. package/dist/mind/context.js +250 -101
  258. package/dist/mind/desk-section.js +362 -0
  259. package/dist/mind/diary-integrity.js +60 -0
  260. package/dist/mind/{memory.js → diary.js} +68 -77
  261. package/dist/mind/embedding-provider.js +60 -0
  262. package/dist/mind/file-state.js +179 -0
  263. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  264. package/dist/mind/obligation-steering.js +221 -0
  265. package/dist/mind/pending.js +13 -8
  266. package/dist/mind/prompt-budget.js +380 -0
  267. package/dist/mind/prompt-refresh.js +3 -2
  268. package/dist/mind/prompt.js +1028 -169
  269. package/dist/mind/provenance-trust.js +26 -0
  270. package/dist/mind/record-paths.js +312 -0
  271. package/dist/mind/scrutiny.js +173 -0
  272. package/dist/nerves/cli-logging.js +7 -1
  273. package/dist/nerves/coverage/audit-rules.js +15 -6
  274. package/dist/nerves/coverage/audit.js +28 -2
  275. package/dist/nerves/coverage/cli.js +1 -1
  276. package/dist/nerves/coverage/contract.js +5 -5
  277. package/dist/nerves/coverage/file-completeness.js +139 -5
  278. package/dist/nerves/event-buffer.js +111 -0
  279. package/dist/nerves/index.js +234 -4
  280. package/dist/nerves/observation.js +20 -0
  281. package/dist/nerves/redact.js +79 -0
  282. package/dist/nerves/review/cli-main.js +5 -0
  283. package/dist/nerves/review/cli.js +156 -0
  284. package/dist/nerves/review/core.js +152 -0
  285. package/dist/nerves/runtime.js +5 -1
  286. package/dist/repertoire/ado-client.js +15 -56
  287. package/dist/repertoire/ado-semantic.js +16 -10
  288. package/dist/repertoire/api-client.js +97 -0
  289. package/dist/repertoire/bitwarden-store.js +1042 -0
  290. package/dist/repertoire/bundle-templates.js +71 -0
  291. package/dist/repertoire/bw-installer.js +180 -0
  292. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  293. package/dist/repertoire/coding/context-pack.js +331 -0
  294. package/dist/repertoire/coding/feedback.js +218 -30
  295. package/dist/repertoire/coding/index.js +15 -3
  296. package/dist/repertoire/coding/manager.js +166 -10
  297. package/dist/repertoire/coding/spawner.js +58 -11
  298. package/dist/repertoire/coding/tools.js +242 -14
  299. package/dist/repertoire/coding/workbench-client.js +272 -0
  300. package/dist/repertoire/coding/workbench-manager.js +346 -0
  301. package/dist/repertoire/commerce-errors.js +109 -0
  302. package/dist/repertoire/commerce-self-test.js +156 -0
  303. package/dist/repertoire/credential-access.js +178 -0
  304. package/dist/repertoire/desk/classifier.js +362 -0
  305. package/dist/repertoire/duffel-client.js +185 -0
  306. package/dist/repertoire/github-client.js +14 -55
  307. package/dist/repertoire/graph-client.js +11 -52
  308. package/dist/repertoire/guardrails.js +156 -27
  309. package/dist/repertoire/mcp-client.js +44 -3
  310. package/dist/repertoire/mcp-manager.js +259 -20
  311. package/dist/repertoire/mcp-tools.js +83 -0
  312. package/dist/repertoire/plugin-mcp.js +175 -0
  313. package/dist/repertoire/plugins.js +253 -0
  314. package/dist/repertoire/shell-sessions.js +133 -0
  315. package/dist/repertoire/skills.js +48 -4
  316. package/dist/repertoire/stripe-client.js +131 -0
  317. package/dist/repertoire/tool-results.js +29 -0
  318. package/dist/repertoire/tools-a2a.js +699 -0
  319. package/dist/repertoire/tools-attachments.js +317 -0
  320. package/dist/repertoire/tools-awaiting.js +372 -0
  321. package/dist/repertoire/tools-base.js +65 -1095
  322. package/dist/repertoire/tools-bluebubbles.js +2 -0
  323. package/dist/repertoire/tools-bridge.js +144 -0
  324. package/dist/repertoire/tools-bundle.js +993 -0
  325. package/dist/repertoire/tools-commerce.js +253 -0
  326. package/dist/repertoire/tools-config.js +186 -0
  327. package/dist/repertoire/tools-continuity.js +252 -0
  328. package/dist/repertoire/tools-credential.js +383 -0
  329. package/dist/repertoire/tools-evolution.js +527 -0
  330. package/dist/repertoire/tools-files.js +344 -0
  331. package/dist/repertoire/tools-flight.js +290 -0
  332. package/dist/repertoire/tools-flow.js +119 -0
  333. package/dist/repertoire/tools-github.js +3 -8
  334. package/dist/repertoire/tools-mail.js +1975 -0
  335. package/dist/repertoire/tools-notes.js +459 -0
  336. package/dist/repertoire/tools-obligations.js +182 -0
  337. package/dist/repertoire/tools-orientation.js +31 -0
  338. package/dist/repertoire/tools-record.js +482 -0
  339. package/dist/repertoire/tools-rsvp.js +139 -0
  340. package/dist/repertoire/tools-runtime.js +150 -0
  341. package/dist/repertoire/tools-session.js +881 -0
  342. package/dist/repertoire/tools-shell.js +120 -0
  343. package/dist/repertoire/tools-stripe.js +224 -0
  344. package/dist/repertoire/tools-surface.js +355 -0
  345. package/dist/repertoire/tools-teams.js +12 -39
  346. package/dist/repertoire/tools-travel.js +125 -0
  347. package/dist/repertoire/tools-trip.js +982 -0
  348. package/dist/repertoire/tools-user-profile.js +146 -0
  349. package/dist/repertoire/tools-vault.js +40 -0
  350. package/dist/repertoire/tools-voice.js +145 -0
  351. package/dist/repertoire/tools.js +250 -80
  352. package/dist/repertoire/travel-api-client.js +360 -0
  353. package/dist/repertoire/user-profile.js +131 -0
  354. package/dist/repertoire/vault-setup.js +246 -0
  355. package/dist/repertoire/vault-unlock.js +594 -0
  356. package/dist/rsvp/aisleplanner-client.js +354 -0
  357. package/dist/rsvp/cli.js +704 -0
  358. package/dist/rsvp/config.js +327 -0
  359. package/dist/rsvp/cutover.js +431 -0
  360. package/dist/rsvp/diagnostics.js +222 -0
  361. package/dist/rsvp/diff-renderer.js +161 -0
  362. package/dist/rsvp/habit-policy.js +85 -0
  363. package/dist/rsvp/habit-stage.js +93 -0
  364. package/dist/rsvp/incident-bundle.js +97 -0
  365. package/dist/rsvp/migration.js +204 -0
  366. package/dist/rsvp/outbound-state.js +254 -0
  367. package/dist/rsvp/query.js +118 -0
  368. package/dist/rsvp/replay.js +233 -0
  369. package/dist/rsvp/snapshot.js +232 -0
  370. package/dist/scripts/claude-code-hook.js +41 -0
  371. package/dist/scripts/claude-code-stop-hook.js +47 -0
  372. package/dist/senses/a2a-entry.js +115 -0
  373. package/dist/senses/attention-queue.js +186 -0
  374. package/dist/senses/await-turn-message.js +58 -0
  375. package/dist/senses/bluebubbles/active-turns.js +216 -0
  376. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  377. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  378. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +226 -19
  379. package/dist/senses/bluebubbles/entry.js +77 -0
  380. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  381. package/dist/senses/bluebubbles/index.js +2937 -0
  382. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  383. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  384. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  385. package/dist/senses/bluebubbles/outbound-state.js +304 -0
  386. package/dist/senses/bluebubbles/processed-log.js +133 -0
  387. package/dist/senses/bluebubbles/replay.js +284 -0
  388. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  389. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  390. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  391. package/dist/senses/cli/bracketed-paste.js +82 -0
  392. package/dist/senses/cli/image-paste.js +287 -0
  393. package/dist/senses/cli/image-ref-navigation.js +75 -0
  394. package/dist/senses/cli/ink-app.js +156 -0
  395. package/dist/senses/cli/inline-diff.js +64 -0
  396. package/dist/senses/cli/input-keys.js +174 -0
  397. package/dist/senses/cli/kill-ring.js +86 -0
  398. package/dist/senses/cli/message-list.js +51 -0
  399. package/dist/senses/cli/ouro-tui.js +607 -0
  400. package/dist/senses/cli/spinner-imperative.js +135 -0
  401. package/dist/senses/cli/spinner.js +101 -0
  402. package/dist/senses/cli/status-line.js +60 -0
  403. package/dist/senses/cli/streaming-markdown.js +526 -0
  404. package/dist/senses/cli/tool-display.js +85 -0
  405. package/dist/senses/cli/tool-render.js +85 -0
  406. package/dist/senses/cli/tui-store.js +240 -0
  407. package/dist/senses/cli/virtual-list.js +35 -0
  408. package/dist/senses/cli-entry.js +60 -8
  409. package/dist/senses/cli-layout.js +100 -0
  410. package/dist/senses/cli.js +521 -214
  411. package/dist/senses/commands.js +66 -3
  412. package/dist/senses/context-packet-ledger.js +245 -0
  413. package/dist/senses/context-packets.js +154 -0
  414. package/dist/senses/habit-turn-message.js +160 -0
  415. package/dist/senses/mail-entry.js +66 -0
  416. package/dist/senses/mail.js +395 -0
  417. package/dist/senses/pipeline.js +952 -178
  418. package/dist/senses/private-runtime-worker.js +723 -0
  419. package/dist/senses/private-runtime.js +1157 -0
  420. package/dist/senses/proactive-content-guard.js +51 -0
  421. package/dist/senses/shared-turn.js +416 -0
  422. package/dist/senses/surface-tool.js +109 -0
  423. package/dist/senses/teams-entry.js +60 -8
  424. package/dist/senses/teams.js +397 -112
  425. package/dist/senses/trust-gate.js +104 -9
  426. package/dist/senses/voice/audio-playback.js +237 -0
  427. package/dist/senses/voice/audio-routing.js +119 -0
  428. package/dist/senses/voice/elevenlabs.js +202 -0
  429. package/dist/senses/voice/floor-control.js +431 -0
  430. package/dist/senses/voice/floor-controller.js +115 -0
  431. package/dist/senses/voice/golden-path.js +116 -0
  432. package/dist/senses/voice/index.js +29 -0
  433. package/dist/senses/voice/meeting.js +113 -0
  434. package/dist/senses/voice/outbound.js +190 -0
  435. package/dist/senses/voice/phone.js +33 -0
  436. package/dist/senses/voice/playback.js +139 -0
  437. package/dist/senses/voice/realtime-eval.js +496 -0
  438. package/dist/senses/voice/realtime-trace.js +531 -0
  439. package/dist/senses/voice/transcript.js +70 -0
  440. package/dist/senses/voice/turn.js +191 -0
  441. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  442. package/dist/senses/voice/twilio-phone.js +5081 -0
  443. package/dist/senses/voice/types.js +2 -0
  444. package/dist/senses/voice/whisper.js +161 -0
  445. package/dist/senses/voice-entry.js +81 -0
  446. package/dist/senses/voice-realtime-eval-command.js +99 -0
  447. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  448. package/dist/senses/voice-twilio-entry.js +87 -0
  449. package/dist/trips/core.js +138 -0
  450. package/dist/trips/store.js +265 -0
  451. package/dist/util/frontmatter.js +69 -0
  452. package/package.json +57 -12
  453. package/skills/agent-commerce.md +113 -0
  454. package/skills/browser-navigation.md +117 -0
  455. package/skills/commerce-setup-guide.md +116 -0
  456. package/skills/commerce-setup.md +84 -0
  457. package/skills/configure-dev-tools.md +99 -0
  458. package/skills/travel-planning.md +138 -0
  459. package/dist/heart/daemon/auth-flow.js +0 -409
  460. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  461. package/dist/heart/daemon/update-hooks.js +0 -138
  462. package/dist/heart/safe-workspace.js +0 -228
  463. package/dist/heart/session-recall.js +0 -116
  464. package/dist/mind/friends/channel.js +0 -84
  465. package/dist/mind/friends/group-context.js +0 -144
  466. package/dist/mind/friends/resolver.js +0 -84
  467. package/dist/mind/friends/store-file.js +0 -190
  468. package/dist/mind/friends/store.js +0 -4
  469. package/dist/mind/friends/tokens.js +0 -26
  470. package/dist/mind/friends/trust-explanation.js +0 -74
  471. package/dist/mind/friends/types.js +0 -29
  472. package/dist/repertoire/tasks/board.js +0 -134
  473. package/dist/repertoire/tasks/index.js +0 -224
  474. package/dist/repertoire/tasks/lifecycle.js +0 -80
  475. package/dist/repertoire/tasks/middleware.js +0 -65
  476. package/dist/repertoire/tasks/parser.js +0 -173
  477. package/dist/repertoire/tasks/scanner.js +0 -132
  478. package/dist/repertoire/tasks/transitions.js +0 -144
  479. package/dist/senses/bluebubbles-entry.js +0 -13
  480. package/dist/senses/bluebubbles.js +0 -1180
  481. package/dist/senses/debug-activity.js +0 -148
  482. package/dist/senses/inner-dialog-worker.js +0 -90
  483. package/dist/senses/inner-dialog.js +0 -480
  484. package/subagents/README.md +0 -7
  485. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  486. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  487. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  488. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  489. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  490. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  491. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  492. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  493. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  494. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  495. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  496. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  497. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  498. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  499. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  500. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  501. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -7,44 +7,196 @@ exports.resetSharedMcpManager = resetSharedMcpManager;
7
7
  const mcp_client_1 = require("./mcp-client");
8
8
  const identity_1 = require("../heart/identity");
9
9
  const runtime_1 = require("../nerves/runtime");
10
+ const credential_access_1 = require("./credential-access");
11
+ const plugin_mcp_1 = require("./plugin-mcp");
10
12
  const MAX_RESTART_RETRIES = 5;
11
13
  const RESTART_DELAY_MS = 1000;
14
+ /**
15
+ * Merge builtin (agent.json mcpServers) + plugin-declared (.mcp.json) servers.
16
+ *
17
+ * Builtin wins on name collision. Returns the merged config map plus a
18
+ * `pluginOrigins` map (server-name → plugin-id) for tools-surfacing namespace.
19
+ *
20
+ * Shared by `getSharedMcpManager()` (initial start) and `McpManager.reconcile()`
21
+ * (re-read on each turn). Both code paths MUST use the same merge logic — if
22
+ * reconcile reads only builtin, plugin servers get classified as "removed"
23
+ * on the second turn and torn down. See alpha.635 fix.
24
+ *
25
+ * `runtimeServers` are per-turn, per-agent overrides (e.g. Workbench's
26
+ * `ouro_workbench`) supplied as PARAMETER data for the current turn — never read
27
+ * from module state. They merge with the HIGHEST precedence (after builtin), so
28
+ * a stale `agent.json` entry loses to the live runtime path. Because they are a
29
+ * parameter, a turn that omits them produces a merged set WITHOUT them, and
30
+ * `reconcile()` then tears the runtime server down — this is the no-leak
31
+ * invariant that keeps the runtime MCP from bleeding into a different agent's
32
+ * concurrent turn on the shared daemon.
33
+ */
34
+ function buildMergedServerConfig(runtimeServers) {
35
+ const config = (0, identity_1.loadAgentConfig)();
36
+ const builtinServers = config.mcpServers ?? {};
37
+ const pluginServers = (0, plugin_mcp_1.listPluginMcpServers)();
38
+ const mergedServers = {};
39
+ const pluginOrigins = {};
40
+ for (const p of pluginServers) {
41
+ if (builtinServers[p.serverName] !== undefined)
42
+ continue;
43
+ mergedServers[p.serverName] = (0, plugin_mcp_1.pluginMcpServerToConfig)(p);
44
+ pluginOrigins[p.serverName] = p.pluginId;
45
+ }
46
+ for (const [name, cfg] of Object.entries(builtinServers)) {
47
+ mergedServers[name] = cfg;
48
+ }
49
+ // Runtime overrides win over both plugin and builtin (highest precedence).
50
+ // They are NOT recorded in pluginOrigins, so they surface as builtin-style
51
+ // (un-namespaced) tools — matching how an agent.json mcpServers entry would.
52
+ if (runtimeServers) {
53
+ for (const [name, cfg] of Object.entries(runtimeServers)) {
54
+ mergedServers[name] = cfg;
55
+ delete pluginOrigins[name];
56
+ }
57
+ }
58
+ return { mergedServers, pluginOrigins };
59
+ }
12
60
  class McpManager {
13
61
  servers = new Map();
14
62
  shuttingDown = false;
15
- async start(servers) {
63
+ async start(servers, pluginOrigins = {}) {
16
64
  (0, runtime_1.emitNervesEvent)({
17
65
  event: "mcp.manager_start",
18
66
  component: "repertoire",
19
67
  message: "starting MCP manager",
20
- meta: { serverCount: Object.keys(servers).length },
68
+ meta: {
69
+ serverCount: Object.keys(servers).length,
70
+ pluginServerCount: Object.keys(pluginOrigins).length,
71
+ },
21
72
  });
22
73
  const entries = Object.entries(servers);
23
74
  for (const [name, config] of entries) {
24
- await this.connectServer(name, config);
75
+ await this.connectServer(name, config, pluginOrigins[name]);
25
76
  }
26
77
  }
27
78
  listAllTools() {
28
79
  const result = [];
29
80
  for (const [name, entry] of this.servers) {
30
- result.push({ server: name, tools: entry.cachedTools });
81
+ result.push({ server: name, tools: entry.cachedTools, pluginId: entry.pluginId });
31
82
  }
32
83
  return result;
33
84
  }
34
85
  async callTool(server, tool, args) {
35
- const entry = this.servers.get(server);
86
+ let entry = this.servers.get(server);
36
87
  if (!entry) {
37
88
  throw new Error(`Unknown server: ${server}`);
38
89
  }
39
90
  if (!entry.client.isConnected()) {
40
- throw new Error(`Server "${server}" is disconnected`);
91
+ await this.recoverStaleTransport(server, "pre-call disconnected");
92
+ entry = this.servers.get(server);
93
+ if (!entry?.client.isConnected()) {
94
+ throw new Error(`Server "${server}" is disconnected`);
95
+ }
96
+ }
97
+ try {
98
+ return await entry.client.callTool(tool, args);
99
+ }
100
+ catch (error) {
101
+ if (!(0, mcp_client_1.isMcpTransportError)(error)) {
102
+ throw error;
103
+ }
104
+ const reason = error instanceof Error ? error.message : String(error);
105
+ await this.recoverStaleTransport(server, reason);
106
+ const recovered = this.servers.get(server);
107
+ if (!recovered?.client.isConnected()) {
108
+ throw new Error(`Server "${server}" is disconnected after recovery: ${reason}`);
109
+ }
110
+ return recovered.client.callTool(tool, args);
111
+ }
112
+ }
113
+ async runCanaries() {
114
+ const results = [];
115
+ for (const [server, entry] of [...this.servers]) {
116
+ try {
117
+ if (!entry.client.isConnected()) {
118
+ await this.recoverStaleTransport(server, "canary disconnected");
119
+ }
120
+ const current = this.servers.get(server);
121
+ if (!current?.client.isConnected()) {
122
+ results.push({ server, ok: false, detail: "disconnected after recovery attempt" });
123
+ continue;
124
+ }
125
+ const tools = await current.client.refreshTools();
126
+ current.cachedTools = tools;
127
+ current.consecutiveFailures = 0;
128
+ results.push({ server, ok: true, detail: `${tools.length} tools listed` });
129
+ }
130
+ catch (error) {
131
+ const reason = error instanceof Error ? error.message : String(error);
132
+ if ((0, mcp_client_1.isMcpTransportError)(error)) {
133
+ await this.recoverStaleTransport(server, reason);
134
+ }
135
+ results.push({ server, ok: false, detail: reason });
136
+ }
137
+ }
138
+ return results;
139
+ }
140
+ /** Re-read agent config AND enabled-plugin .mcp.json files, then connect new
141
+ * servers / disconnect removed ones. Must include plugin-declared servers
142
+ * in the desired set — otherwise plugin servers (e.g. mcp__desk__*) are
143
+ * treated as "removed" on every call and get torn down between turns.
144
+ *
145
+ * `runtimeServers` are the current turn's per-agent overrides. They MUST be
146
+ * passed on every reconcile for the agent that owns them, otherwise the
147
+ * runtime server (e.g. ouro_workbench) is classified as "removed" and torn
148
+ * down — which is exactly the desired no-leak behavior for a turn that omits
149
+ * them. */
150
+ async reconcile(runtimeServers) {
151
+ try {
152
+ const { mergedServers, pluginOrigins } = buildMergedServerConfig(runtimeServers);
153
+ const currentNames = new Set(this.servers.keys());
154
+ const desiredNames = new Set(Object.keys(mergedServers));
155
+ // Connect new servers
156
+ for (const [name, cfg] of Object.entries(mergedServers)) {
157
+ if (!currentNames.has(name)) {
158
+ (0, runtime_1.emitNervesEvent)({
159
+ event: "mcp.server_added",
160
+ component: "repertoire",
161
+ message: `connecting new MCP server: ${name}`,
162
+ meta: { server: name, command: cfg.command },
163
+ });
164
+ await this.connectServer(name, cfg, pluginOrigins[name]);
165
+ }
166
+ }
167
+ // Disconnect removed servers
168
+ for (const name of currentNames) {
169
+ if (!desiredNames.has(name)) {
170
+ (0, runtime_1.emitNervesEvent)({
171
+ event: "mcp.server_removed",
172
+ component: "repertoire",
173
+ message: `disconnecting removed MCP server: ${name}`,
174
+ meta: { server: name },
175
+ });
176
+ const entry = this.servers.get(name);
177
+ /* v8 ignore next -- defensive: name comes from this.servers.keys() this same tick, so entry is always present; the guard only protects against an awaited connectServer crash-handler racing a delete @preserve */
178
+ if (entry)
179
+ entry.client.shutdown();
180
+ this.servers.delete(name);
181
+ }
182
+ }
183
+ }
184
+ catch (error) {
185
+ (0, runtime_1.emitNervesEvent)({
186
+ level: "warn",
187
+ event: "mcp.reconcile_error",
188
+ component: "repertoire",
189
+ message: "failed to reconcile MCP servers",
190
+ meta: { reason: error instanceof Error ? error.message : String(error) },
191
+ });
41
192
  }
42
- return entry.client.callTool(tool, args);
43
193
  }
44
194
  shutdown() {
45
195
  this.shuttingDown = true;
196
+ // `_end` (not `_stop`) to pair with `mcp.manager_start` under the
197
+ // nerves audit start/end pairing rule.
46
198
  (0, runtime_1.emitNervesEvent)({
47
- event: "mcp.manager_stop",
199
+ event: "mcp.manager_end",
48
200
  component: "repertoire",
49
201
  message: "shutting down MCP manager",
50
202
  meta: { serverCount: this.servers.size },
@@ -54,14 +206,73 @@ class McpManager {
54
206
  }
55
207
  this.servers.clear();
56
208
  }
57
- async connectServer(name, config) {
58
- const client = new mcp_client_1.McpClient(config);
209
+ /**
210
+ * Resolve `vault:DOMAIN/FIELD` references in server env config.
211
+ * Returns resolved env or throws with a descriptive error.
212
+ */
213
+ async resolveVaultEnv(_serverName, env) {
214
+ const resolved = { ...env };
215
+ // Short-circuit: only spin up a credential store if at least one env value
216
+ // actually requests vault resolution. Plugin MCP servers commonly ship with
217
+ // `env: {}` or pure-string envs, and we shouldn't pay the credential-store
218
+ // boot cost (or fail in test envs that have no vault) for those cases.
219
+ const hasVaultRef = Object.values(resolved).some((v) => /^vault:/.test(v));
220
+ if (!hasVaultRef)
221
+ return resolved;
222
+ const store = (0, credential_access_1.getCredentialStore)();
223
+ for (const [key, value] of Object.entries(resolved)) {
224
+ const match = value.match(/^vault:([^/]+)\/(.+)$/);
225
+ if (!match)
226
+ continue;
227
+ const [, domain, field] = match;
228
+ try {
229
+ resolved[key] = await store.getRawSecret(domain, field);
230
+ }
231
+ catch (err) {
232
+ /* v8 ignore next -- reason @preserve */
233
+ const reason = err instanceof Error ? err.message : String(err);
234
+ // Classify the error for actionable messaging
235
+ let classification = "vault unreachable";
236
+ if (reason.includes("no credential found")) {
237
+ classification = "item not found";
238
+ }
239
+ else if (reason.includes("field") && reason.includes("not found")) {
240
+ classification = "field empty";
241
+ }
242
+ throw new Error(`vault:${domain}/${field} could not be resolved: ${classification}`);
243
+ }
244
+ }
245
+ return resolved;
246
+ }
247
+ async connectServer(name, config, pluginId) {
248
+ // Resolve vault: references in env before spawning
249
+ let resolvedConfig = config;
250
+ if (config.env) {
251
+ try {
252
+ const resolvedEnv = await this.resolveVaultEnv(name, config.env);
253
+ resolvedConfig = { ...config, env: resolvedEnv };
254
+ }
255
+ catch (err) {
256
+ /* v8 ignore next -- reason @preserve */
257
+ const reason = err instanceof Error ? err.message : String(err);
258
+ (0, runtime_1.emitNervesEvent)({
259
+ level: "error",
260
+ event: "mcp.vault_resolve_error",
261
+ component: "repertoire",
262
+ message: `skipping MCP server "${name}": ${reason}`,
263
+ meta: { server: name, reason },
264
+ });
265
+ return; // Skip this server, continue to next
266
+ }
267
+ }
268
+ const client = new mcp_client_1.McpClient(resolvedConfig);
59
269
  const entry = {
60
270
  name,
61
271
  config,
62
272
  client,
63
273
  cachedTools: [],
64
274
  consecutiveFailures: 0,
275
+ pluginId,
65
276
  };
66
277
  this.servers.set(name, entry);
67
278
  client.onClose(() => {
@@ -76,14 +287,17 @@ class McpManager {
76
287
  entry.consecutiveFailures = 0;
77
288
  }
78
289
  catch (error) {
290
+ const reason = error instanceof Error ? error.message : String(error);
79
291
  (0, runtime_1.emitNervesEvent)({
80
292
  level: "error",
81
293
  event: "mcp.connect_error",
82
294
  component: "repertoire",
83
- message: `failed to connect MCP server: ${name}`,
295
+ message: `failed to connect MCP server "${name}" (command: ${config.command}). Check that the command exists and is properly configured. Reason: ${reason}`,
84
296
  meta: {
85
297
  server: name,
86
- reason: error instanceof Error ? error.message : String(error),
298
+ command: config.command,
299
+ args: config.args,
300
+ reason,
87
301
  },
88
302
  });
89
303
  }
@@ -99,8 +313,8 @@ class McpManager {
99
313
  level: "error",
100
314
  event: "mcp.connect_error",
101
315
  component: "repertoire",
102
- message: `MCP server "${name}" exceeded max restart retries (${MAX_RESTART_RETRIES})`,
103
- meta: { server: name, failures: entry.consecutiveFailures },
316
+ message: `MCP server "${name}" exceeded max restart retries (${MAX_RESTART_RETRIES}). Giving up — check that "${entry.config.command}" exists and is properly configured in agent.json mcpServers.`,
317
+ meta: { server: name, command: entry.config.command, failures: entry.consecutiveFailures },
104
318
  });
105
319
  return;
106
320
  }
@@ -128,6 +342,7 @@ class McpManager {
128
342
  return;
129
343
  // Remove old entry and reconnect
130
344
  this.servers.delete(name);
345
+ entry.client.shutdown();
131
346
  await this.connectServer(name, entry.config);
132
347
  // Preserve failure count
133
348
  const newEntry = this.servers.get(name);
@@ -135,6 +350,17 @@ class McpManager {
135
350
  newEntry.consecutiveFailures = entry.consecutiveFailures;
136
351
  }
137
352
  }
353
+ /* v8 ignore stop */
354
+ async recoverStaleTransport(name, reason) {
355
+ (0, runtime_1.emitNervesEvent)({
356
+ level: "warn",
357
+ event: "mcp.transport_recovery",
358
+ component: "repertoire",
359
+ message: `recovering stale MCP transport: ${name}`,
360
+ meta: { server: name, reason },
361
+ });
362
+ await this.restartServer(name);
363
+ }
138
364
  }
139
365
  exports.McpManager = McpManager;
140
366
  let _sharedManager = null;
@@ -143,21 +369,34 @@ let _sharedManagerPromise = null;
143
369
  * Get or create a shared McpManager instance from the agent's config.
144
370
  * Returns null if no mcpServers are configured.
145
371
  * Safe to call from multiple senses — will only create one instance.
372
+ *
373
+ * `options.runtimeServers` are the current turn's per-agent MCP overrides (e.g.
374
+ * Workbench's `ouro_workbench`). They are PARAMETER data for this call only —
375
+ * passed into the merge for both the initial `start()` and every subsequent
376
+ * `reconcile()`, and never persisted as module state. A call that omits them
377
+ * reconciles to a set WITHOUT them, tearing any prior runtime server down — the
378
+ * no-leak invariant for the shared multi-agent daemon.
146
379
  */
147
- async function getSharedMcpManager() {
148
- if (_sharedManager)
380
+ async function getSharedMcpManager(options) {
381
+ const runtimeServers = options?.runtimeServers;
382
+ // If manager exists, reconcile to pick up config changes (new/removed servers)
383
+ // AND this turn's runtime overrides. Passing runtimeServers per-call is what
384
+ // scopes the runtime MCP to the active agent's turn.
385
+ if (_sharedManager) {
386
+ await _sharedManager.reconcile(runtimeServers);
149
387
  return _sharedManager;
388
+ }
150
389
  /* v8 ignore next -- race guard: deduplicates concurrent initialization calls @preserve */
151
390
  if (_sharedManagerPromise)
152
391
  return _sharedManagerPromise;
392
+ // Always re-check config — agent may have added servers since last call
153
393
  _sharedManagerPromise = (async () => {
154
394
  try {
155
- const config = (0, identity_1.loadAgentConfig)();
156
- const servers = config.mcpServers;
157
- if (!servers || Object.keys(servers).length === 0)
395
+ const { mergedServers, pluginOrigins } = buildMergedServerConfig(runtimeServers);
396
+ if (Object.keys(mergedServers).length === 0)
158
397
  return null;
159
398
  const manager = new McpManager();
160
- await manager.start(servers);
399
+ await manager.start(mergedServers, pluginOrigins);
161
400
  _sharedManager = manager;
162
401
  return manager;
163
402
  }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /**
3
+ * First-class MCP tool integration — converts MCP server tools into ToolDefinitions
4
+ * so the model can call them directly without shell indirection.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.mcpToolsAsDefinitions = mcpToolsAsDefinitions;
8
+ const runtime_1 = require("../nerves/runtime");
9
+ /**
10
+ * Convert all tools from an McpManager into ToolDefinition objects.
11
+ *
12
+ * Naming rules:
13
+ * - Builtin servers (agent.json `mcpServers`) — legacy `{server}_{tool}`
14
+ * shape (e.g., `browser_navigate`), with double-prefix avoidance when
15
+ * the tool already starts with the server name.
16
+ * - Plugin servers (from `<plugin>/.mcp.json`, W6 Unit 9) — Anthropic public
17
+ * convention `mcp__{server}__{tool}` (e.g., `mcp__desk__task_create`).
18
+ * This matches Claude Code's external naming and the on-prompt promise
19
+ * in `desk-section.ts` (`mcp__desk__*`).
20
+ *
21
+ * The handler always calls `mcpManager.callTool()` with the un-prefixed
22
+ * `(server, tool)` pair regardless of how the surfaced name was shaped.
23
+ */
24
+ function mcpToolsAsDefinitions(mcpManager) {
25
+ if (!mcpManager)
26
+ return [];
27
+ return mcpManager.listAllTools().flatMap((entry) => {
28
+ const isPluginSourced = Boolean(entry.pluginId);
29
+ return entry.tools.map((tool) => ({
30
+ tool: {
31
+ type: "function",
32
+ function: {
33
+ name: isPluginSourced
34
+ ? `mcp__${entry.server}__${tool.name}`
35
+ : tool.name.startsWith(`${entry.server}_`) || tool.name === entry.server
36
+ ? tool.name
37
+ : `${entry.server}_${tool.name}`,
38
+ description: tool.description || `MCP tool: ${tool.name} (server: ${entry.server})`,
39
+ parameters: tool.inputSchema ?? { type: "object", properties: {} },
40
+ },
41
+ },
42
+ riskProfile: {
43
+ mutates: "external_side_effect",
44
+ risk: "high",
45
+ reason: "MCP tools may mutate external systems",
46
+ },
47
+ handler: async (args) => {
48
+ (0, runtime_1.emitNervesEvent)({
49
+ event: "mcp.tool_start",
50
+ component: "repertoire",
51
+ message: `calling MCP tool ${entry.server}/${tool.name}`,
52
+ meta: { server: entry.server, tool: tool.name },
53
+ });
54
+ try {
55
+ const result = await mcpManager.callTool(entry.server, tool.name, args);
56
+ const text = result.content
57
+ .filter((c) => c.type === "text" && c.text)
58
+ .map((c) => c.text)
59
+ .join("");
60
+ (0, runtime_1.emitNervesEvent)({
61
+ event: "mcp.tool_end",
62
+ component: "repertoire",
63
+ message: `MCP tool ${entry.server}/${tool.name} completed`,
64
+ meta: { server: entry.server, tool: tool.name },
65
+ });
66
+ return text;
67
+ }
68
+ catch (error) {
69
+ const reason = error instanceof Error ? error.message : String(error);
70
+ (0, runtime_1.emitNervesEvent)({
71
+ level: "error",
72
+ event: "mcp.tool_error",
73
+ component: "repertoire",
74
+ message: `MCP tool ${entry.server}/${tool.name} failed: ${reason}`,
75
+ meta: { server: entry.server, tool: tool.name, reason },
76
+ });
77
+ return `[mcp error] ${entry.server}/${tool.name}: ${reason}`;
78
+ }
79
+ },
80
+ mcpServer: entry.server,
81
+ }));
82
+ });
83
+ }
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.listPluginMcpServers = listPluginMcpServers;
37
+ exports.pluginMcpServerToConfig = pluginMcpServerToConfig;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const identity_1 = require("../heart/identity");
41
+ const runtime_1 = require("../nerves/runtime");
42
+ const plugins_1 = require("./plugins");
43
+ /**
44
+ * Resolve `${VAR}` and `${VAR:-default}` against the process env (with a
45
+ * caller-supplied override map applied first — used to inject the `DESK`
46
+ * fallback bound to the agent's bundle desk root).
47
+ *
48
+ * Anything that isn't a recognized `${...}` token passes through verbatim.
49
+ * Multiple substitutions per string are supported.
50
+ */
51
+ function resolveVars(input, overrides) {
52
+ return input.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)(:-([^}]*))?\}/g, (_match, varName, _full, def) => {
53
+ if (overrides[varName] !== undefined)
54
+ return overrides[varName];
55
+ const fromEnv = process.env[varName];
56
+ if (fromEnv !== undefined)
57
+ return fromEnv;
58
+ if (def !== undefined)
59
+ return def;
60
+ return "";
61
+ });
62
+ }
63
+ function resolveArgs(args, overrides) {
64
+ return args.map((a) => resolveVars(a, overrides));
65
+ }
66
+ function resolveEnv(env, overrides) {
67
+ const out = {};
68
+ for (const [k, v] of Object.entries(env)) {
69
+ out[k] = resolveVars(v, overrides);
70
+ }
71
+ return out;
72
+ }
73
+ function readPluginMcpManifest(pluginRoot) {
74
+ const manifestPath = path.join(pluginRoot, ".mcp.json");
75
+ if (!fs.existsSync(manifestPath))
76
+ return null;
77
+ const raw = fs.readFileSync(manifestPath, "utf-8");
78
+ try {
79
+ const parsed = JSON.parse(raw);
80
+ const servers = parsed?.mcpServers;
81
+ if (!servers || typeof servers !== "object")
82
+ return {};
83
+ return servers;
84
+ }
85
+ catch (err) {
86
+ /* v8 ignore next -- err.message vs String(err) branch is defensive @preserve */
87
+ const reason = err instanceof Error ? err.message : String(err);
88
+ (0, runtime_1.emitNervesEvent)({
89
+ level: "error",
90
+ event: "plugin_mcp.parse_error",
91
+ component: "repertoire",
92
+ message: `failed to parse plugin .mcp.json at ${manifestPath}: ${reason}`,
93
+ meta: { manifestPath, reason },
94
+ });
95
+ return null;
96
+ }
97
+ }
98
+ /**
99
+ * List the MCP servers declared across the current agent's enabled plugins.
100
+ *
101
+ * Returns a flat list — one entry per `(plugin, server-name)` pair — already
102
+ * resolved against process env + the `DESK` bundle-default. The result is
103
+ * suitable for direct hand-off to `McpManager.start()` after key-flattening.
104
+ *
105
+ * `homeDir` is an optional override for the `~/.ouro-cli/` root (test-only).
106
+ */
107
+ function listPluginMcpServers(homeDir) {
108
+ (0, runtime_1.emitNervesEvent)({
109
+ event: "plugin_mcp.list_start",
110
+ component: "repertoire",
111
+ message: "discovering plugin-declared MCP servers",
112
+ meta: { operation: "listPluginMcpServers" },
113
+ });
114
+ const config = (0, identity_1.loadAgentConfig)();
115
+ const declaredPlugins = config.plugins ?? [];
116
+ const pluginsRoot = (0, plugins_1.getPluginsRoot)(homeDir);
117
+ // Per-agent override: DESK defaults to <bundleRoot>/desk/ when not explicitly set.
118
+ const overrides = {};
119
+ if (process.env.DESK === undefined) {
120
+ overrides.DESK = path.join((0, identity_1.getAgentRoot)(), "desk");
121
+ }
122
+ const out = [];
123
+ for (const plugin of declaredPlugins) {
124
+ if (!plugin.enabled)
125
+ continue;
126
+ const pluginDir = (0, plugins_1.getPluginDir)(plugin.id, homeDir);
127
+ // If the plugins root or plugin dir doesn't exist, skip (installed-but-removed
128
+ // or never-installed). The manifest read does its own .mcp.json existence
129
+ // check; we only need to avoid touching missing plugin dirs.
130
+ if (!fs.existsSync(pluginsRoot))
131
+ break;
132
+ if (!fs.existsSync(pluginDir))
133
+ continue;
134
+ const manifest = readPluginMcpManifest(pluginDir);
135
+ if (!manifest)
136
+ continue;
137
+ for (const [serverName, entry] of Object.entries(manifest)) {
138
+ if (!entry || typeof entry.command !== "string" || entry.command.length === 0) {
139
+ continue;
140
+ }
141
+ out.push({
142
+ pluginId: plugin.id,
143
+ serverName,
144
+ command: resolveVars(entry.command, overrides),
145
+ args: resolveArgs(entry.args ?? [], overrides),
146
+ env: resolveEnv(entry.env ?? {}, overrides),
147
+ cwd: pluginDir,
148
+ });
149
+ }
150
+ }
151
+ (0, runtime_1.emitNervesEvent)({
152
+ event: "plugin_mcp.list_end",
153
+ component: "repertoire",
154
+ message: "discovered plugin-declared MCP servers",
155
+ meta: {
156
+ operation: "listPluginMcpServers",
157
+ pluginCount: declaredPlugins.length,
158
+ serverCount: out.length,
159
+ },
160
+ });
161
+ return out;
162
+ }
163
+ /**
164
+ * Adapter: convert a `PluginMcpServer` into the shape `McpManager.start()`
165
+ * already consumes (`McpServerConfig`). Used by `getSharedMcpManager()` so
166
+ * builtin + plugin servers can be merged into one start call.
167
+ */
168
+ function pluginMcpServerToConfig(server) {
169
+ return {
170
+ command: server.command,
171
+ args: server.args,
172
+ env: server.env,
173
+ cwd: server.cwd,
174
+ };
175
+ }