@ouro.bot/cli 0.1.0-alpha.92 → 0.1.0-alpha.921

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 (717) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5826 -16
  16. package/deploy/unraid/Dockerfile +58 -0
  17. package/deploy/unraid/README.txt +2997 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-butler-upgrade.mjs +1254 -0
  34. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  35. package/deploy/unraid/sanctuary-replay-gate.mjs +1564 -0
  36. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  37. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2086 -0
  38. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  39. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  40. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  41. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  42. package/deploy/unraid/sanctuary.ouro/awaiting/house-care-sweep.md +17 -0
  43. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  44. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  45. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +2231 -0
  46. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  49. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +33 -0
  50. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +27 -0
  51. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +22 -0
  52. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  53. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +232 -0
  54. package/deploy/unraid/sanctuary.xml +30 -0
  55. package/dist/a2a/card.js +57 -0
  56. package/dist/a2a/client.js +250 -0
  57. package/dist/a2a/config.js +50 -0
  58. package/dist/a2a/delegated-command-grants.js +93 -0
  59. package/dist/a2a/delegated-command.js +197 -0
  60. package/dist/a2a/delegation-stores.js +56 -0
  61. package/dist/a2a/did-resolution.js +93 -0
  62. package/dist/a2a/escalation-grants.js +84 -0
  63. package/dist/a2a/escalation-wiring.js +60 -0
  64. package/dist/a2a/identity.js +258 -0
  65. package/dist/a2a/inbound-share.js +110 -0
  66. package/dist/a2a/mission-result-wire.js +196 -0
  67. package/dist/a2a/onboarding.js +133 -0
  68. package/dist/a2a/operator-trust.js +382 -0
  69. package/dist/a2a/outbox-client.js +57 -0
  70. package/dist/a2a/outbox-store.js +188 -0
  71. package/dist/a2a/outbox-wire.js +95 -0
  72. package/dist/a2a/pin-store.js +132 -0
  73. package/dist/a2a/replay-grant-holders.js +33 -0
  74. package/dist/a2a/replay-harness.js +188 -0
  75. package/dist/a2a/resolution-proof.js +53 -0
  76. package/dist/a2a/sealed-chat.js +113 -0
  77. package/dist/a2a/seen-ledger.js +120 -0
  78. package/dist/a2a/server.js +771 -0
  79. package/dist/a2a/task-store.js +69 -0
  80. package/dist/a2a/transport.js +45 -0
  81. package/dist/a2a/trust-commands.js +203 -0
  82. package/dist/a2a/trusted-files.js +185 -0
  83. package/dist/a2a/types.js +3 -0
  84. package/dist/arc/attention-types.js +8 -0
  85. package/dist/arc/cares.js +360 -0
  86. package/dist/arc/episodes.js +118 -0
  87. package/dist/arc/evolution.js +490 -0
  88. package/dist/arc/flight-recorder.js +1034 -0
  89. package/dist/arc/intentions.js +134 -0
  90. package/dist/arc/json-store.js +117 -0
  91. package/dist/arc/obligations.js +386 -0
  92. package/dist/arc/packets.js +336 -0
  93. package/dist/arc/presence.js +185 -0
  94. package/dist/arc/task-lifecycle.js +57 -0
  95. package/dist/commerce/store.js +755 -0
  96. package/dist/commerce/types.js +3 -0
  97. package/dist/heart/active-work.js +798 -40
  98. package/dist/heart/agent-entry.js +252 -3
  99. package/dist/heart/approval-files.js +113 -0
  100. package/dist/heart/approval-store.js +960 -0
  101. package/dist/heart/attachments/image-normalize.js +194 -0
  102. package/dist/heart/attachments/materialize.js +97 -0
  103. package/dist/heart/attachments/originals.js +88 -0
  104. package/dist/heart/attachments/render.js +29 -0
  105. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  106. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  107. package/dist/heart/attachments/sources/index.js +18 -0
  108. package/dist/heart/attachments/sources/telegram.js +71 -0
  109. package/dist/heart/attachments/store.js +132 -0
  110. package/dist/heart/attachments/types.js +93 -0
  111. package/dist/heart/auth/auth-flow.js +495 -0
  112. package/dist/heart/autonomy-budget.js +478 -0
  113. package/dist/heart/awaiting/a2a-await-delivery.js +109 -0
  114. package/dist/heart/awaiting/await-alert.js +152 -0
  115. package/dist/heart/awaiting/await-expiry.js +143 -0
  116. package/dist/heart/awaiting/await-loader.js +91 -0
  117. package/dist/heart/awaiting/await-parser.js +152 -0
  118. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  119. package/dist/heart/awaiting/await-scheduler.js +391 -0
  120. package/dist/heart/background-operations.js +281 -0
  121. package/dist/heart/bluebubbles-host-account.js +78 -0
  122. package/dist/heart/bridges/manager.js +137 -17
  123. package/dist/heart/bridges/store.js +14 -2
  124. package/dist/heart/bundle-state.js +168 -0
  125. package/dist/heart/commitments.js +44 -18
  126. package/dist/heart/config-registry.js +331 -0
  127. package/dist/heart/config.js +174 -131
  128. package/dist/heart/context-loss-gauntlet.js +387 -0
  129. package/dist/heart/context-loss-sentinel.js +1159 -0
  130. package/dist/heart/core.js +2364 -578
  131. package/dist/heart/cross-chat-delivery.js +9 -22
  132. package/dist/heart/daemon/agent-config-check.js +451 -0
  133. package/dist/heart/daemon/agent-discovery.js +283 -3
  134. package/dist/heart/daemon/agent-home.js +319 -0
  135. package/dist/heart/daemon/agent-service.js +542 -0
  136. package/dist/heart/daemon/agentic-repair.js +547 -0
  137. package/dist/heart/daemon/await-private-wake.js +59 -0
  138. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  139. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  140. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  141. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  142. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  143. package/dist/heart/daemon/cadence.js +180 -0
  144. package/dist/heart/daemon/cli-arg-redaction.js +26 -0
  145. package/dist/heart/daemon/cli-defaults.js +876 -0
  146. package/dist/heart/daemon/cli-desk.js +322 -0
  147. package/dist/heart/daemon/cli-exec.js +9199 -0
  148. package/dist/heart/daemon/cli-help.js +735 -0
  149. package/dist/heart/daemon/cli-parse.js +3211 -0
  150. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  151. package/dist/heart/daemon/cli-render.js +819 -0
  152. package/dist/heart/daemon/cli-types.js +8 -0
  153. package/dist/heart/daemon/connect-bay.js +323 -0
  154. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  155. package/dist/heart/daemon/container-healthcheck.js +112 -0
  156. package/dist/heart/daemon/container-runtime.js +97 -0
  157. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  158. package/dist/heart/daemon/container-spec-auditor.js +235 -0
  159. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  160. package/dist/heart/daemon/daemon-cli.js +29 -2350
  161. package/dist/heart/daemon/daemon-entry.js +953 -11
  162. package/dist/heart/daemon/daemon-health.js +186 -0
  163. package/dist/heart/daemon/daemon-rollup.js +57 -0
  164. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  165. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  166. package/dist/heart/daemon/daemon.js +2084 -105
  167. package/dist/heart/daemon/dns-workflow.js +394 -0
  168. package/dist/heart/daemon/doctor-types.js +8 -0
  169. package/dist/heart/daemon/doctor.js +1766 -0
  170. package/dist/heart/daemon/freshness.js +345 -0
  171. package/dist/heart/daemon/habit-private-wake.js +61 -0
  172. package/dist/heart/daemon/health-monitor.js +154 -11
  173. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  174. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  175. package/dist/heart/daemon/http-health-probe.js +80 -0
  176. package/dist/heart/daemon/human-command-screens.js +234 -0
  177. package/dist/heart/daemon/human-readiness.js +114 -0
  178. package/dist/heart/daemon/inner-status.js +78 -0
  179. package/dist/heart/daemon/interactive-repair.js +394 -0
  180. package/dist/heart/daemon/launchd.js +37 -8
  181. package/dist/heart/daemon/log-tailer.js +79 -10
  182. package/dist/heart/daemon/logs-prune.js +132 -0
  183. package/dist/heart/daemon/mcp-canary.js +524 -0
  184. package/dist/heart/daemon/message-router.js +65 -5
  185. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  186. package/dist/heart/daemon/os-cron-deps.js +135 -0
  187. package/dist/heart/daemon/os-cron.js +22 -14
  188. package/dist/heart/daemon/ouro-bot-entry.js +6 -3
  189. package/dist/heart/daemon/ouro-entry.js +5 -2
  190. package/dist/heart/daemon/plugin-cli.js +432 -0
  191. package/dist/heart/daemon/process-manager.js +760 -61
  192. package/dist/heart/daemon/provider-discovery.js +137 -0
  193. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  194. package/dist/heart/daemon/prunable-bundle.js +144 -0
  195. package/dist/heart/daemon/pulse.js +511 -0
  196. package/dist/heart/daemon/readiness-repair.js +365 -0
  197. package/dist/heart/daemon/run-hooks.js +2 -0
  198. package/dist/heart/daemon/runtime-logging.js +47 -14
  199. package/dist/heart/daemon/runtime-metadata.js +2 -30
  200. package/dist/heart/daemon/runtime-mode.js +13 -2
  201. package/dist/heart/daemon/safe-mode.js +161 -0
  202. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  203. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  204. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  205. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  206. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  207. package/dist/heart/daemon/sanctuary-authority-epoch.js +281 -0
  208. package/dist/heart/daemon/sanctuary-authority-installation.js +161 -0
  209. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  210. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +1267 -0
  211. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  212. package/dist/heart/daemon/sanctuary-bundle-migration.js +730 -0
  213. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  214. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +493 -0
  215. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  216. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  217. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  218. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  219. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  220. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  221. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  222. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +475 -0
  223. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  224. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +676 -0
  225. package/dist/heart/daemon/sense-manager.js +733 -48
  226. package/dist/heart/daemon/session-id-resolver.js +131 -0
  227. package/dist/heart/daemon/skill-management-installer.js +1 -1
  228. package/dist/heart/daemon/socket-client.js +180 -12
  229. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  230. package/dist/heart/daemon/startup-tui.js +339 -0
  231. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  232. package/dist/heart/daemon/task-scheduler.js +117 -39
  233. package/dist/heart/daemon/terminal-ui.js +503 -0
  234. package/dist/heart/daemon/thoughts.js +138 -54
  235. package/dist/heart/daemon/up-progress.js +366 -0
  236. package/dist/heart/daemon/vault-items.js +56 -0
  237. package/dist/heart/delegation.js +1 -4
  238. package/dist/heart/external-events/router.js +1516 -0
  239. package/dist/heart/failure-reports.js +336 -0
  240. package/dist/heart/file-lock.js +109 -0
  241. package/dist/heart/frontend-approval-runtime.js +506 -0
  242. package/dist/heart/frontend-journal.js +215 -0
  243. package/dist/heart/frontend-session-service.js +237 -0
  244. package/dist/heart/frontend-socket-client.js +164 -0
  245. package/dist/heart/frontend-socket.js +400 -0
  246. package/dist/heart/habits/habit-cancel.js +810 -0
  247. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  248. package/dist/heart/habits/habit-migration.js +194 -0
  249. package/dist/heart/habits/habit-parser.js +278 -0
  250. package/dist/heart/habits/habit-runtime-state.js +93 -0
  251. package/dist/heart/habits/habit-scheduler.js +653 -0
  252. package/dist/heart/habits/habit-session-summary.js +318 -0
  253. package/dist/heart/habits/habit-session.js +636 -0
  254. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  255. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  256. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  257. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  258. package/dist/heart/identity.js +230 -59
  259. package/dist/heart/kept-notes.js +289 -0
  260. package/dist/heart/kicks.js +1 -1
  261. package/dist/heart/machine-identity.js +175 -0
  262. package/dist/heart/mail-import-discovery.js +356 -0
  263. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  264. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  265. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  266. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  267. package/dist/heart/mailbox/mailbox-http-transport.js +272 -0
  268. package/dist/heart/mailbox/mailbox-http.js +99 -0
  269. package/dist/heart/mailbox/mailbox-read.js +39 -0
  270. package/dist/heart/mailbox/mailbox-types.js +27 -0
  271. package/dist/heart/mailbox/mailbox-view.js +197 -0
  272. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  273. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  274. package/dist/heart/mailbox/readers/mail.js +375 -0
  275. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  276. package/dist/heart/mailbox/readers/sessions.js +231 -0
  277. package/dist/heart/mailbox/readers/shared.js +111 -0
  278. package/dist/heart/mcp/mcp-server.js +696 -0
  279. package/dist/heart/migrate-config.js +100 -0
  280. package/dist/heart/model-capabilities.js +83 -16
  281. package/dist/heart/orientation-frame.js +345 -0
  282. package/dist/heart/platform.js +81 -0
  283. package/dist/heart/primitives.js +1 -1
  284. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  285. package/dist/heart/private-runtime/index.js +18 -0
  286. package/dist/heart/private-runtime/ledger.js +221 -0
  287. package/dist/heart/private-runtime/policy.js +260 -0
  288. package/dist/heart/private-runtime/types.js +2 -0
  289. package/dist/heart/progress-story.js +1 -1
  290. package/dist/heart/provider-attempt.js +137 -0
  291. package/dist/heart/provider-binding-resolver.js +273 -0
  292. package/dist/heart/provider-credentials.js +449 -0
  293. package/dist/heart/provider-failover.js +311 -0
  294. package/dist/heart/provider-models.js +96 -0
  295. package/dist/heart/provider-ping.js +265 -0
  296. package/dist/heart/provider-readiness-cache.js +119 -0
  297. package/dist/heart/provider-visibility.js +188 -0
  298. package/dist/heart/providers/anthropic-token.js +131 -0
  299. package/dist/heart/providers/anthropic.js +173 -60
  300. package/dist/heart/providers/azure.js +23 -11
  301. package/dist/heart/providers/error-classification.js +127 -0
  302. package/dist/heart/providers/github-copilot.js +38 -39
  303. package/dist/heart/providers/minimax-vlm.js +189 -0
  304. package/dist/heart/providers/minimax.js +26 -8
  305. package/dist/heart/providers/openai-codex-token.js +349 -0
  306. package/dist/heart/providers/openai-codex.js +55 -40
  307. package/dist/heart/providers/openai-compatible.js +177 -0
  308. package/dist/heart/reply-style.js +52 -0
  309. package/dist/heart/run-ledger.js +247 -0
  310. package/dist/heart/runtime-capability-check.js +170 -0
  311. package/dist/heart/runtime-credentials.js +607 -0
  312. package/dist/heart/runtime-cwd.js +87 -0
  313. package/dist/heart/sense-truth.js +24 -4
  314. package/dist/heart/session-activity.js +92 -24
  315. package/dist/heart/session-events.js +1504 -0
  316. package/dist/heart/session-playback-cli-main.js +5 -0
  317. package/dist/heart/session-playback-cli.js +36 -0
  318. package/dist/heart/session-playback.js +231 -0
  319. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  320. package/dist/heart/session-redaction-repair.js +552 -0
  321. package/dist/heart/session-stats-cli-main.js +5 -0
  322. package/dist/heart/session-stats.js +183 -0
  323. package/dist/heart/session-transcript.js +133 -0
  324. package/dist/heart/shelf-claims.js +78 -0
  325. package/dist/heart/shepherd-config.js +113 -0
  326. package/dist/heart/source-grounding.js +297 -0
  327. package/dist/heart/start-of-turn-packet.js +372 -0
  328. package/dist/heart/steward-policy.js +656 -0
  329. package/dist/heart/streaming.js +609 -207
  330. package/dist/heart/structured-output.js +196 -0
  331. package/dist/heart/sync-classification.js +176 -0
  332. package/dist/heart/sync-health.js +152 -0
  333. package/dist/heart/sync.js +726 -0
  334. package/dist/heart/target-resolution.js +11 -7
  335. package/dist/heart/tempo.js +93 -0
  336. package/dist/heart/temporal-view.js +41 -0
  337. package/dist/heart/timeouts.js +101 -0
  338. package/dist/heart/tool-activity-callbacks.js +59 -0
  339. package/dist/heart/tool-approval.js +382 -0
  340. package/dist/heart/tool-description.js +155 -0
  341. package/dist/heart/tool-friction.js +55 -0
  342. package/dist/heart/tool-loop.js +206 -0
  343. package/dist/heart/turn-context.js +496 -0
  344. package/dist/heart/turn-execution-lease.js +30 -0
  345. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  346. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +3 -2
  347. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  348. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  349. package/dist/heart/versioning/ouro-version-manager.js +432 -0
  350. package/dist/heart/versioning/release-sources.js +173 -0
  351. package/dist/heart/versioning/self-update-defaults.js +294 -0
  352. package/dist/heart/versioning/self-update.js +196 -0
  353. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  354. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  355. package/dist/heart/versioning/update-hooks.js +154 -0
  356. package/dist/heart/versioning/update-state.js +126 -0
  357. package/dist/heart/versioning/updater-launchd.js +150 -0
  358. package/dist/heart/versioning/version-intent.js +114 -0
  359. package/dist/heart/work-card.js +380 -0
  360. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  361. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  362. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  363. package/dist/mailbox-ui/index.html +16 -0
  364. package/dist/mailroom/attention.js +167 -0
  365. package/dist/mailroom/autonomy.js +209 -0
  366. package/dist/mailroom/blob-store.js +889 -0
  367. package/dist/mailroom/body-cache.js +61 -0
  368. package/dist/mailroom/cache-sync-cli.js +58 -0
  369. package/dist/mailroom/core.js +803 -0
  370. package/dist/mailroom/entry.js +160 -0
  371. package/dist/mailroom/file-store.js +568 -0
  372. package/dist/mailroom/hosted-cache-sync.js +384 -0
  373. package/dist/mailroom/mbox-import.js +393 -0
  374. package/dist/mailroom/migration.js +164 -0
  375. package/dist/mailroom/outbound.js +380 -0
  376. package/dist/mailroom/policy.js +263 -0
  377. package/dist/mailroom/reader.js +292 -0
  378. package/dist/mailroom/search-cache.js +513 -0
  379. package/dist/mailroom/search-relevance.js +319 -0
  380. package/dist/mailroom/smtp-ingress.js +176 -0
  381. package/dist/mailroom/source-state.js +176 -0
  382. package/dist/mailroom/thread.js +109 -0
  383. package/dist/mailroom/travel-extract.js +89 -0
  384. package/dist/mind/bundle-manifest.js +24 -2
  385. package/dist/mind/context.js +307 -139
  386. package/dist/mind/desk-section.js +362 -0
  387. package/dist/mind/diary-integrity.js +60 -0
  388. package/dist/mind/{memory.js → diary.js} +68 -77
  389. package/dist/mind/embedding-provider.js +60 -0
  390. package/dist/mind/file-state.js +179 -0
  391. package/dist/mind/friend-link-codes.js +209 -0
  392. package/dist/mind/friend-merge.js +330 -0
  393. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  394. package/dist/mind/obligation-steering.js +199 -3
  395. package/dist/mind/pending.js +36 -10
  396. package/dist/mind/prompt-budget.js +479 -0
  397. package/dist/mind/prompt-refresh.js +3 -2
  398. package/dist/mind/prompt.js +1085 -198
  399. package/dist/mind/provenance-trust.js +26 -0
  400. package/dist/mind/record-paths.js +312 -0
  401. package/dist/mind/scrutiny.js +173 -0
  402. package/dist/mind/session-transaction.js +564 -0
  403. package/dist/nerves/cli-logging.js +7 -1
  404. package/dist/nerves/coverage/audit-rules.js +15 -6
  405. package/dist/nerves/coverage/audit.js +28 -2
  406. package/dist/nerves/coverage/cli.js +1 -1
  407. package/dist/nerves/coverage/contract.js +5 -5
  408. package/dist/nerves/coverage/file-completeness.js +139 -5
  409. package/dist/nerves/coverage/run-artifacts.js +55 -35
  410. package/dist/nerves/coverage/source-scanner.js +4 -4
  411. package/dist/nerves/event-buffer.js +111 -0
  412. package/dist/nerves/index.js +293 -9
  413. package/dist/nerves/observation.js +20 -0
  414. package/dist/nerves/redact.js +79 -0
  415. package/dist/nerves/review/cli-main.js +5 -0
  416. package/dist/nerves/review/cli.js +156 -0
  417. package/dist/nerves/review/core.js +159 -0
  418. package/dist/nerves/runtime.js +17 -1
  419. package/dist/repertoire/ado-client.js +15 -56
  420. package/dist/repertoire/ado-semantic.js +16 -10
  421. package/dist/repertoire/api-client.js +97 -0
  422. package/dist/repertoire/bitwarden-store.js +1201 -0
  423. package/dist/repertoire/bundle-templates.js +71 -0
  424. package/dist/repertoire/bw-installer.js +231 -0
  425. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  426. package/dist/repertoire/coding/context-pack.js +331 -0
  427. package/dist/repertoire/coding/feedback.js +174 -32
  428. package/dist/repertoire/coding/index.js +15 -3
  429. package/dist/repertoire/coding/manager.js +159 -10
  430. package/dist/repertoire/coding/spawner.js +40 -11
  431. package/dist/repertoire/coding/tools.js +182 -18
  432. package/dist/repertoire/coding/workbench-client.js +272 -0
  433. package/dist/repertoire/coding/workbench-manager.js +346 -0
  434. package/dist/repertoire/commerce-errors.js +109 -0
  435. package/dist/repertoire/commerce-self-test.js +156 -0
  436. package/dist/repertoire/credential-access.js +183 -0
  437. package/dist/repertoire/desk/classifier.js +362 -0
  438. package/dist/repertoire/duffel-client.js +185 -0
  439. package/dist/repertoire/github-client.js +14 -55
  440. package/dist/repertoire/graph-client.js +11 -52
  441. package/dist/repertoire/guardrails.js +968 -20
  442. package/dist/repertoire/house-sweep.js +469 -0
  443. package/dist/repertoire/mcp-client.js +58 -5
  444. package/dist/repertoire/mcp-manager.js +427 -139
  445. package/dist/repertoire/mcp-tools.js +132 -0
  446. package/dist/repertoire/mcp-write-guard.js +46 -0
  447. package/dist/repertoire/plugin-mcp.js +175 -0
  448. package/dist/repertoire/plugins.js +253 -0
  449. package/dist/repertoire/relationship-authorization.js +322 -0
  450. package/dist/repertoire/sanctuary-container-policy.js +46 -0
  451. package/dist/repertoire/shell-sessions.js +134 -0
  452. package/dist/repertoire/skills.js +48 -4
  453. package/dist/repertoire/stripe-client.js +131 -0
  454. package/dist/repertoire/tool-arguments.js +182 -0
  455. package/dist/repertoire/tool-results.js +29 -0
  456. package/dist/repertoire/tools-a2a.js +699 -0
  457. package/dist/repertoire/tools-attachments.js +322 -0
  458. package/dist/repertoire/tools-awaiting.js +872 -0
  459. package/dist/repertoire/tools-base.js +83 -1168
  460. package/dist/repertoire/tools-bluebubbles.js +2 -0
  461. package/dist/repertoire/tools-bridge.js +144 -0
  462. package/dist/repertoire/tools-bundle.js +995 -0
  463. package/dist/repertoire/tools-commerce.js +253 -0
  464. package/dist/repertoire/tools-config.js +186 -0
  465. package/dist/repertoire/tools-continuity.js +575 -0
  466. package/dist/repertoire/tools-credential.js +383 -0
  467. package/dist/repertoire/tools-escalation.js +84 -0
  468. package/dist/repertoire/tools-evolution.js +527 -0
  469. package/dist/repertoire/tools-files.js +344 -0
  470. package/dist/repertoire/tools-flight.js +290 -0
  471. package/dist/repertoire/tools-flow.js +119 -0
  472. package/dist/repertoire/tools-friend-link.js +57 -0
  473. package/dist/repertoire/tools-github.js +3 -8
  474. package/dist/repertoire/tools-habits.js +103 -0
  475. package/dist/repertoire/tools-house-care.js +174 -0
  476. package/dist/repertoire/tools-mail.js +1828 -0
  477. package/dist/repertoire/tools-notes.js +496 -0
  478. package/dist/repertoire/tools-obligations.js +182 -0
  479. package/dist/repertoire/tools-orientation.js +31 -0
  480. package/dist/repertoire/tools-record.js +482 -0
  481. package/dist/repertoire/tools-rsvp.js +139 -0
  482. package/dist/repertoire/tools-runtime.js +238 -0
  483. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  484. package/dist/repertoire/tools-session.js +1133 -0
  485. package/dist/repertoire/tools-shell.js +149 -0
  486. package/dist/repertoire/tools-shepherd.js +262 -0
  487. package/dist/repertoire/tools-steward-policy.js +147 -0
  488. package/dist/repertoire/tools-stripe.js +224 -0
  489. package/dist/repertoire/tools-surface.js +369 -0
  490. package/dist/repertoire/tools-teams.js +12 -39
  491. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  492. package/dist/repertoire/tools-travel.js +125 -0
  493. package/dist/repertoire/tools-trip.js +982 -0
  494. package/dist/repertoire/tools-unraid.js +556 -0
  495. package/dist/repertoire/tools-user-profile.js +146 -0
  496. package/dist/repertoire/tools-vault.js +40 -0
  497. package/dist/repertoire/tools-voice-local.js +198 -0
  498. package/dist/repertoire/tools-voice.js +145 -0
  499. package/dist/repertoire/tools.js +514 -156
  500. package/dist/repertoire/travel-api-client.js +360 -0
  501. package/dist/repertoire/unraid-client.js +155 -0
  502. package/dist/repertoire/unraid-restart.js +339 -0
  503. package/dist/repertoire/user-profile.js +131 -0
  504. package/dist/repertoire/vault-setup.js +246 -0
  505. package/dist/repertoire/vault-unlock.js +686 -0
  506. package/dist/rsvp/aisleplanner-client.js +354 -0
  507. package/dist/rsvp/cli.js +936 -0
  508. package/dist/rsvp/config.js +327 -0
  509. package/dist/rsvp/cutover.js +433 -0
  510. package/dist/rsvp/diagnostics.js +232 -0
  511. package/dist/rsvp/diff-renderer.js +176 -0
  512. package/dist/rsvp/habit-policy.js +110 -0
  513. package/dist/rsvp/habit-stage.js +123 -0
  514. package/dist/rsvp/incident-bundle.js +97 -0
  515. package/dist/rsvp/migration.js +204 -0
  516. package/dist/rsvp/native-habit-runner.js +630 -0
  517. package/dist/rsvp/outbound-state.js +628 -0
  518. package/dist/rsvp/query.js +118 -0
  519. package/dist/rsvp/replay.js +233 -0
  520. package/dist/rsvp/snapshot.js +232 -0
  521. package/dist/rsvp/spend-ledger.js +175 -0
  522. package/dist/scripts/claude-code-hook.js +41 -0
  523. package/dist/scripts/claude-code-stop-hook.js +47 -0
  524. package/dist/senses/a2a-entry.js +132 -0
  525. package/dist/senses/acp-server.js +386 -0
  526. package/dist/senses/attention-queue.js +186 -0
  527. package/dist/senses/await-turn-message.js +65 -0
  528. package/dist/senses/bluebubbles/active-turns.js +216 -0
  529. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  530. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  531. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +379 -41
  532. package/dist/senses/bluebubbles/context-packet.js +207 -0
  533. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  534. package/dist/senses/bluebubbles/entry.js +90 -0
  535. package/dist/senses/bluebubbles/host-account-verifier.js +88 -0
  536. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  537. package/dist/senses/bluebubbles/index.js +3878 -0
  538. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  539. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  540. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  541. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  542. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  543. package/dist/senses/bluebubbles/processed-log.js +133 -0
  544. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  545. package/dist/senses/bluebubbles/replay.js +284 -0
  546. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  547. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  548. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  549. package/dist/senses/bluebubbles/webhook-registration.js +257 -0
  550. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  551. package/dist/senses/cli/bracketed-paste.js +82 -0
  552. package/dist/senses/cli/image-paste.js +287 -0
  553. package/dist/senses/cli/image-ref-navigation.js +75 -0
  554. package/dist/senses/cli/ink-app.js +156 -0
  555. package/dist/senses/cli/inline-diff.js +64 -0
  556. package/dist/senses/cli/input-keys.js +174 -0
  557. package/dist/senses/cli/kill-ring.js +86 -0
  558. package/dist/senses/cli/message-list.js +51 -0
  559. package/dist/senses/cli/ouro-tui.js +607 -0
  560. package/dist/senses/cli/spinner-imperative.js +135 -0
  561. package/dist/senses/cli/spinner.js +101 -0
  562. package/dist/senses/cli/status-line.js +60 -0
  563. package/dist/senses/cli/streaming-markdown.js +526 -0
  564. package/dist/senses/cli/tool-display.js +85 -0
  565. package/dist/senses/cli/tool-render.js +85 -0
  566. package/dist/senses/cli/tui-store.js +241 -0
  567. package/dist/senses/cli/virtual-list.js +35 -0
  568. package/dist/senses/cli-entry.js +60 -8
  569. package/dist/senses/cli.js +601 -304
  570. package/dist/senses/commands.js +66 -3
  571. package/dist/senses/context-packet-ledger.js +371 -0
  572. package/dist/senses/context-packets.js +154 -0
  573. package/dist/senses/habit-lifecycle-guard.js +24 -0
  574. package/dist/senses/habit-turn-message.js +160 -0
  575. package/dist/senses/ingress-evidence.js +2 -0
  576. package/dist/senses/mail-entry.js +66 -0
  577. package/dist/senses/mail.js +524 -0
  578. package/dist/senses/pipeline.js +1158 -204
  579. package/dist/senses/private-runtime-worker.js +859 -0
  580. package/dist/senses/private-runtime.js +1627 -0
  581. package/dist/senses/proactive-content-guard.js +51 -0
  582. package/dist/senses/root-host-approval-port.js +345 -0
  583. package/dist/senses/root-host-approval-runtime.js +393 -0
  584. package/dist/senses/sanctuary-authority-resident.js +102 -0
  585. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  586. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  587. package/dist/senses/sanctuary-grounding.js +118 -0
  588. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  589. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  590. package/dist/senses/sanctuary-health-runner.js +104 -0
  591. package/dist/senses/sanctuary-health.js +422 -0
  592. package/dist/senses/sanctuary-install-state-contract.js +169 -0
  593. package/dist/senses/sanctuary-interactive-control.js +410 -0
  594. package/dist/senses/sanctuary-media-catalog-contract.js +259 -0
  595. package/dist/senses/sanctuary-media-optimization.js +514 -0
  596. package/dist/senses/sanctuary-runtime.js +369 -0
  597. package/dist/senses/sanctuary-sab.js +85 -0
  598. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  599. package/dist/senses/shared-turn.js +793 -0
  600. package/dist/senses/shepherd/client.js +196 -0
  601. package/dist/senses/shepherd/cmux.js +352 -0
  602. package/dist/senses/shepherd/herdr.js +315 -0
  603. package/dist/senses/shepherd/host.js +14 -0
  604. package/dist/senses/shepherd/judge.js +137 -0
  605. package/dist/senses/shepherd/owner-notice.js +251 -0
  606. package/dist/senses/shepherd/redact.js +66 -0
  607. package/dist/senses/shepherd/returns.js +79 -0
  608. package/dist/senses/shepherd/sense.js +310 -0
  609. package/dist/senses/shepherd/terminal-process.js +99 -0
  610. package/dist/senses/shepherd-entry.js +78 -0
  611. package/dist/senses/surface-tool.js +109 -0
  612. package/dist/senses/teams-entry.js +68 -8
  613. package/dist/senses/teams.js +598 -233
  614. package/dist/senses/telegram-admission.js +718 -0
  615. package/dist/senses/telegram-approval-runtime.js +793 -0
  616. package/dist/senses/telegram-attachments.js +186 -0
  617. package/dist/senses/telegram-audit-ledger.js +220 -0
  618. package/dist/senses/telegram-authority-transport.js +231 -0
  619. package/dist/senses/telegram-client.js +1749 -0
  620. package/dist/senses/telegram-effect-adapter.js +900 -0
  621. package/dist/senses/telegram-entry.js +83 -0
  622. package/dist/senses/telegram-handoff.js +80 -0
  623. package/dist/senses/telegram.js +2405 -0
  624. package/dist/senses/trust-gate.js +104 -9
  625. package/dist/senses/voice/audio-playback.js +237 -0
  626. package/dist/senses/voice/audio-routing.js +119 -0
  627. package/dist/senses/voice/call-auth.js +250 -0
  628. package/dist/senses/voice/elevenlabs.js +202 -0
  629. package/dist/senses/voice/floor-control.js +431 -0
  630. package/dist/senses/voice/floor-controller.js +115 -0
  631. package/dist/senses/voice/golden-path.js +116 -0
  632. package/dist/senses/voice/index.js +29 -0
  633. package/dist/senses/voice/local-audio-control.js +344 -0
  634. package/dist/senses/voice/local-audio-devices.js +516 -0
  635. package/dist/senses/voice/local-audio-disclosure.js +174 -0
  636. package/dist/senses/voice/local-audio-identity.js +103 -0
  637. package/dist/senses/voice/local-audio-join.js +325 -0
  638. package/dist/senses/voice/local-audio-mute.js +199 -0
  639. package/dist/senses/voice/local-audio-notify.js +121 -0
  640. package/dist/senses/voice/local-audio-prompts.js +116 -0
  641. package/dist/senses/voice/local-audio-transport.js +427 -0
  642. package/dist/senses/voice/local-audio.js +281 -0
  643. package/dist/senses/voice/local-media-stream.js +145 -0
  644. package/dist/senses/voice/meeting.js +113 -0
  645. package/dist/senses/voice/outbound.js +190 -0
  646. package/dist/senses/voice/phone.js +33 -0
  647. package/dist/senses/voice/playback.js +139 -0
  648. package/dist/senses/voice/process-guards.js +51 -0
  649. package/dist/senses/voice/realtime-eval.js +496 -0
  650. package/dist/senses/voice/realtime-tool-schema.js +195 -0
  651. package/dist/senses/voice/realtime-trace.js +531 -0
  652. package/dist/senses/voice/transcript.js +70 -0
  653. package/dist/senses/voice/turn.js +191 -0
  654. package/dist/senses/voice/twilio-phone-runtime.js +836 -0
  655. package/dist/senses/voice/twilio-phone.js +5454 -0
  656. package/dist/senses/voice/types.js +2 -0
  657. package/dist/senses/voice/whisper.js +161 -0
  658. package/dist/senses/voice-entry.js +83 -0
  659. package/dist/senses/voice-realtime-eval-command.js +99 -0
  660. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  661. package/dist/senses/voice-twilio-entry.js +87 -0
  662. package/dist/trips/core.js +138 -0
  663. package/dist/trips/store.js +265 -0
  664. package/dist/util/frontmatter.js +69 -0
  665. package/npm-shrinkwrap.json +8100 -0
  666. package/package.json +74 -13
  667. package/skills/agent-commerce.md +113 -0
  668. package/skills/browser-navigation.md +117 -0
  669. package/skills/commerce-setup-guide.md +116 -0
  670. package/skills/commerce-setup.md +84 -0
  671. package/skills/configure-dev-tools.md +99 -0
  672. package/skills/travel-planning.md +138 -0
  673. package/dist/heart/daemon/auth-flow.js +0 -430
  674. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  675. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  676. package/dist/heart/daemon/update-hooks.js +0 -138
  677. package/dist/heart/obligations.js +0 -191
  678. package/dist/heart/safe-workspace.js +0 -362
  679. package/dist/heart/session-recall.js +0 -116
  680. package/dist/mind/friends/channel.js +0 -84
  681. package/dist/mind/friends/group-context.js +0 -144
  682. package/dist/mind/friends/resolver.js +0 -84
  683. package/dist/mind/friends/store-file.js +0 -190
  684. package/dist/mind/friends/store.js +0 -4
  685. package/dist/mind/friends/tokens.js +0 -26
  686. package/dist/mind/friends/trust-explanation.js +0 -74
  687. package/dist/mind/friends/types.js +0 -29
  688. package/dist/repertoire/tasks/board.js +0 -134
  689. package/dist/repertoire/tasks/index.js +0 -224
  690. package/dist/repertoire/tasks/lifecycle.js +0 -80
  691. package/dist/repertoire/tasks/middleware.js +0 -65
  692. package/dist/repertoire/tasks/parser.js +0 -173
  693. package/dist/repertoire/tasks/scanner.js +0 -132
  694. package/dist/repertoire/tasks/transitions.js +0 -144
  695. package/dist/senses/bluebubbles-entry.js +0 -13
  696. package/dist/senses/bluebubbles.js +0 -1181
  697. package/dist/senses/debug-activity.js +0 -154
  698. package/dist/senses/inner-dialog-worker.js +0 -90
  699. package/dist/senses/inner-dialog.js +0 -525
  700. package/subagents/README.md +0 -7
  701. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  702. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  703. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  704. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  705. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  706. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  707. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  708. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  709. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  710. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  711. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  712. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  713. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  714. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  715. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  716. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  717. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,771 @@
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.ESCALATION_CONFIRM_INTERVAL_MS = void 0;
37
+ exports.a2aChatRelationship = a2aChatRelationship;
38
+ exports.startA2AServer = startA2AServer;
39
+ const http = __importStar(require("node:http"));
40
+ const node_crypto_1 = require("node:crypto");
41
+ const a2a_client_1 = require("@ouro.bot/friends/a2a-client");
42
+ const friends_1 = require("@ouro.bot/friends");
43
+ const identity_1 = require("../heart/identity");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ const shared_turn_1 = require("../senses/shared-turn");
46
+ const card_1 = require("./card");
47
+ const config_1 = require("./config");
48
+ const pin_store_1 = require("./pin-store");
49
+ const seen_ledger_1 = require("./seen-ledger");
50
+ const did_resolution_1 = require("./did-resolution");
51
+ const inbound_share_1 = require("./inbound-share");
52
+ const sanctuary_runtime_1 = require("../senses/sanctuary-runtime");
53
+ const sealed_chat_1 = require("./sealed-chat");
54
+ const relationship_authorization_1 = require("../repertoire/relationship-authorization");
55
+ const mission_result_wire_1 = require("./mission-result-wire");
56
+ const delegation_stores_1 = require("./delegation-stores");
57
+ const task_store_1 = require("./task-store");
58
+ const delegated_command_1 = require("./delegated-command");
59
+ const outbox_wire_1 = require("./outbox-wire");
60
+ const failure_reports_1 = require("../heart/failure-reports");
61
+ const MAX_A2A_REQUEST_BYTES = 128 * 1024;
62
+ const MAX_A2A_MESSAGE_TEXT_CHARS = 16_000;
63
+ exports.ESCALATION_CONFIRM_INTERVAL_MS = 5 * 60 * 1000;
64
+ class A2ARequestError extends Error {
65
+ status;
66
+ code;
67
+ constructor(status, code, message) {
68
+ super(message);
69
+ this.status = status;
70
+ this.code = code;
71
+ }
72
+ }
73
+ function jsonResponse(id, result) {
74
+ return { jsonrpc: "2.0", id: id ?? null, result };
75
+ }
76
+ function errorResponse(id, code, message, data) {
77
+ return { jsonrpc: "2.0", id: id ?? null, error: { code, message, ...(data !== undefined ? { data } : {}) } };
78
+ }
79
+ async function readBody(req) {
80
+ const chunks = [];
81
+ let total = 0;
82
+ for await (const chunk of req) {
83
+ /* v8 ignore next -- Node HTTP request bodies arrive as Buffers in this runtime; string chunks are defensive stream compatibility @preserve */
84
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
85
+ total += buffer.byteLength;
86
+ if (total > MAX_A2A_REQUEST_BYTES) {
87
+ throw new A2ARequestError(413, -32000, `A2A request body exceeds ${MAX_A2A_REQUEST_BYTES} bytes`);
88
+ }
89
+ chunks.push(buffer);
90
+ }
91
+ return Buffer.concat(chunks).toString("utf-8");
92
+ }
93
+ function writeJson(res, status, payload) {
94
+ const body = `${JSON.stringify(payload, null, 2)}\n`;
95
+ res.writeHead(status, {
96
+ "content-type": "application/json; charset=utf-8",
97
+ "content-length": Buffer.byteLength(body),
98
+ });
99
+ res.end(body);
100
+ }
101
+ function textFromMessage(message) {
102
+ if (!message || typeof message !== "object")
103
+ return "";
104
+ const parts = message.parts;
105
+ if (!Array.isArray(parts))
106
+ return "";
107
+ return parts
108
+ .map((part) => {
109
+ if (!part || typeof part !== "object")
110
+ return "";
111
+ const text = part.text;
112
+ return typeof text === "string" ? text : "";
113
+ })
114
+ .filter(Boolean)
115
+ .join("\n")
116
+ .trim();
117
+ }
118
+ function messageFromParams(params) {
119
+ if (!params || typeof params !== "object")
120
+ return null;
121
+ const message = params.message;
122
+ if (!message || typeof message !== "object")
123
+ return null;
124
+ return message;
125
+ }
126
+ function metadataRecord(value) {
127
+ /* v8 ignore next -- protocol callers pass JSON-RPC param/message objects; this guard keeps malformed direct input inert @preserve */
128
+ if (!value || typeof value !== "object")
129
+ return undefined;
130
+ /* v8 ignore next -- JSON-RPC params/messages are objects in supported calls; array guard protects malformed direct input @preserve */
131
+ if (Array.isArray(value))
132
+ return undefined;
133
+ const metadata = value.metadata;
134
+ return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : undefined;
135
+ }
136
+ function metadataStringFromRecord(metadata, key) {
137
+ const value = metadata?.[key];
138
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
139
+ }
140
+ function metadataString(message, key) {
141
+ return metadataStringFromRecord(metadataRecord(message), key);
142
+ }
143
+ function headerString(req, key) {
144
+ const value = req.headers[key];
145
+ /* v8 ignore next -- Node lower-cases singular request headers here; array values are defensive compatibility @preserve */
146
+ if (Array.isArray(value))
147
+ return value[0];
148
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
149
+ }
150
+ /* v8 ignore start -- default runner crosses into the full live agent pipeline; shared-turn covers that pipeline and server tests inject a deterministic runner @preserve */
151
+ function storageKeyFor(peerExternalId) {
152
+ return `a2a-${(0, node_crypto_1.createHash)("sha256").update(peerExternalId).digest("hex").slice(0, 24)}`;
153
+ }
154
+ async function defaultTurnRunner(input) {
155
+ const result = await (0, shared_turn_1.runSenseTurn)({
156
+ agentName: input.agentName,
157
+ channel: "a2a",
158
+ friendId: storageKeyFor(input.peerAgentId),
159
+ sessionKey: input.sessionKey,
160
+ userMessage: input.message,
161
+ latencyMode: "standard",
162
+ identity: {
163
+ provider: "a2a-agent",
164
+ externalId: input.peerAgentId,
165
+ displayName: input.peerName,
166
+ },
167
+ // The Butler's house tools read a typed Sanctuary runtime from the tool context; the
168
+ // Telegram sense attaches it, and a verified A2A friend's turn needs it too (without it
169
+ // every Unraid read answered "Sanctuary runtime is unavailable"). The relationship
170
+ // profile still decides which of those tools the peer may call.
171
+ toolContext: {
172
+ ...((0, sanctuary_runtime_1.isSanctuaryAgent)(input.agentName) ? (0, sanctuary_runtime_1.createSanctuaryToolContext)(input.agentName) : {}),
173
+ ...(input.relationshipAuthorization ? { relationshipAuthorization: input.relationshipAuthorization } : {}),
174
+ ...(input.delegatedCommand ? { delegatedCommand: input.delegatedCommand } : {}),
175
+ },
176
+ });
177
+ return { response: result.response };
178
+ }
179
+ /* v8 ignore stop */
180
+ /** The relationship that scopes a verified friend's A2A chat turn, from the agent's
181
+ * own capability registry. No registry (or an invalid one) means no relationship,
182
+ * which Sanctuary's tool selection turns into "no tools" for a remote turn. */
183
+ function a2aChatRelationship(agentRoot, friend, requestId) {
184
+ let registry;
185
+ try {
186
+ registry = (0, relationship_authorization_1.loadRelationshipCapabilityRegistry)(agentRoot);
187
+ }
188
+ catch {
189
+ return undefined;
190
+ }
191
+ return (0, relationship_authorization_1.createRelationshipAuthorizationEvaluator)({ friend, registry, requestId, requestPhase: "inbound" });
192
+ }
193
+ function accessTokenHash(accessToken) {
194
+ return (0, node_crypto_1.createHash)("sha256").update(accessToken).digest("hex");
195
+ }
196
+ function accessTokenScope(accessToken) {
197
+ return `a2a-task-token:${accessTokenHash(accessToken)}`;
198
+ }
199
+ function untrustedTurnPeerExternalId() {
200
+ return "unauthenticated-a2a-peer";
201
+ }
202
+ /** Whether an inbound message carries a friends sealed DataPart (`kind:"data"`). */
203
+ function messageHasDataPart(message) {
204
+ /* v8 ignore next -- defensive: callers pass a parsed inbound whose `parts` is always an array; guards malformed direct input @preserve */
205
+ if (!Array.isArray(message.parts))
206
+ return false;
207
+ return message.parts.some((part) => part && part.kind === "data");
208
+ }
209
+ /** Map a friends `receiveShare` rejection reason → a JSON-RPC error code.
210
+ * Malformed-shape reasons map to invalid-params (-32602); auth/trust/replay
211
+ * rejections map to a dedicated A2A "rejected" code (-32003). */
212
+ function rejectionErrorCode(reason) {
213
+ if (reason === "malformed_message" || reason === "malformed_plaintext")
214
+ return -32602;
215
+ return -32003;
216
+ }
217
+ function senderHintFromMessage(req, inbound) {
218
+ const idHint = metadataString(inbound, "senderAgentId")
219
+ ?? metadataString(inbound, "senderCardUrl")
220
+ ?? metadataString(inbound, "agentId")
221
+ ?? metadataString(inbound, "cardUrl")
222
+ ?? headerString(req, "x-a2a-agent-id");
223
+ const name = metadataString(inbound, "senderName")
224
+ ?? metadataString(inbound, "agentName")
225
+ ?? headerString(req, "x-a2a-agent-name")
226
+ ?? idHint
227
+ ?? "Unauthenticated A2A peer";
228
+ return { idHint, name };
229
+ }
230
+ function isTerminalTaskState(state) {
231
+ return state === "TASK_STATE_COMPLETED"
232
+ || state === "TASK_STATE_FAILED"
233
+ || state === "TASK_STATE_CANCELED"
234
+ || state === "TASK_STATE_REJECTED"
235
+ || state === "completed"
236
+ || state === "failed"
237
+ || state === "canceled"
238
+ || state === "rejected";
239
+ }
240
+ function accessTokenFromParams(params) {
241
+ /* v8 ignore next -- GetTask/CancelTask validate object params before token extraction; this keeps direct helper use defensive @preserve */
242
+ if (!params || typeof params !== "object" || Array.isArray(params))
243
+ return undefined;
244
+ const record = params;
245
+ const direct = record.accessToken ?? record.access_token;
246
+ if (typeof direct === "string" && direct.trim())
247
+ return direct.trim();
248
+ return metadataStringFromRecord(metadataRecord(params), "accessToken");
249
+ }
250
+ function taskA2AMetadata(task) {
251
+ const a2a = task.metadata?.a2a;
252
+ /* v8 ignore next -- server-created tasks always carry object auth metadata; fallback protects legacy/corrupt task files @preserve */
253
+ if (!a2a || typeof a2a !== "object" || Array.isArray(a2a))
254
+ return {};
255
+ return a2a;
256
+ }
257
+ /** A friends sealed DataPart: opaque ciphertext addressed to one DID, so it is safe
258
+ * to expose to the task holder (a sealed chat reply travels this way). */
259
+ function isSealedFriendsPart(part) {
260
+ const data = part.data;
261
+ return part.kind === "data" && !!data && typeof data === "object" && typeof data.sealed === "object" && data.sealed !== null && typeof data.recipientDid === "string";
262
+ }
263
+ function publicMessage(message, style) {
264
+ const parts = message.parts
265
+ .filter((part) => part && typeof part === "object" && (typeof part.text === "string" || isSealedFriendsPart(part)))
266
+ .map((part) => style === "legacy" ? { ...part, kind: part.kind ?? "text" } : part);
267
+ if (style === "latest")
268
+ return { ...message, kind: "message", parts };
269
+ return {
270
+ ...message,
271
+ kind: "message",
272
+ role: message.role === "ROLE_AGENT" ? "agent" : message.role === "ROLE_USER" ? "user" : message.role,
273
+ parts,
274
+ };
275
+ }
276
+ function legacyTaskState(state) {
277
+ if (state === "TASK_STATE_SUBMITTED")
278
+ return "submitted";
279
+ if (state === "TASK_STATE_WORKING")
280
+ return "working";
281
+ if (state === "TASK_STATE_COMPLETED")
282
+ return "completed";
283
+ if (state === "TASK_STATE_FAILED")
284
+ return "failed";
285
+ if (state === "TASK_STATE_CANCELED")
286
+ return "canceled";
287
+ if (state === "TASK_STATE_REJECTED")
288
+ return "rejected";
289
+ if (state === "TASK_STATE_AUTH_REQUIRED")
290
+ return "auth-required";
291
+ if (state === "TASK_STATE_INPUT_REQUIRED")
292
+ return "input-required";
293
+ return state;
294
+ }
295
+ function publicTask(task, accessToken, style, includeAccessToken) {
296
+ const a2a = taskA2AMetadata(task);
297
+ const { accessTokenHash: _accessTokenHash, taskScopeHash: _taskScopeHash, ...safeA2A } = a2a;
298
+ const statusMessage = task.status.message ? publicMessage(task.status.message, style) : undefined;
299
+ return {
300
+ ...task,
301
+ kind: task.kind ?? "task",
302
+ status: {
303
+ ...task.status,
304
+ state: style === "legacy" ? legacyTaskState(task.status.state) : task.status.state,
305
+ ...(statusMessage ? { message: statusMessage } : {}),
306
+ },
307
+ history: task.history.map((message) => publicMessage(message, style)),
308
+ ...(task.artifacts ? {
309
+ artifacts: task.artifacts.map((artifact) => ({
310
+ ...artifact,
311
+ parts: style === "legacy"
312
+ ? artifact.parts.map((part) => ({ ...part, kind: part.kind ?? "text" }))
313
+ : artifact.parts,
314
+ })),
315
+ } : {}),
316
+ metadata: {
317
+ ...task.metadata,
318
+ a2a: {
319
+ ...safeA2A,
320
+ ...(includeAccessToken ? { accessToken } : {}),
321
+ },
322
+ },
323
+ };
324
+ }
325
+ function taskAuthorized(task, accessToken) {
326
+ const a2a = taskA2AMetadata(task);
327
+ return a2a.accessTokenHash === accessTokenHash(accessToken);
328
+ }
329
+ function taskFor(input) {
330
+ const now = new Date().toISOString();
331
+ const history = [...(input.previousTask?.history ?? []), input.inbound];
332
+ const previousA2A = input.previousTask ? taskA2AMetadata(input.previousTask) : {};
333
+ const responseParts = input.responseParts ?? (input.response ? [{ text: input.response }] : undefined);
334
+ const responseMessage = responseParts
335
+ ? {
336
+ kind: "message",
337
+ role: "ROLE_AGENT",
338
+ taskId: input.taskId,
339
+ contextId: input.contextId,
340
+ messageId: (0, node_crypto_1.randomUUID)(),
341
+ parts: responseParts,
342
+ }
343
+ : undefined;
344
+ if (responseMessage)
345
+ history.push(responseMessage);
346
+ return {
347
+ kind: "task",
348
+ id: input.taskId,
349
+ contextId: input.contextId,
350
+ status: {
351
+ state: input.state,
352
+ timestamp: now,
353
+ ...(responseMessage ? { message: responseMessage } : {}),
354
+ },
355
+ history,
356
+ metadata: {
357
+ ...input.previousTask?.metadata,
358
+ a2a: {
359
+ ...previousA2A,
360
+ accessTokenHash: accessTokenHash(input.accessToken),
361
+ ...(input.clientTaskId ? { clientTaskId: input.clientTaskId } : {}),
362
+ },
363
+ },
364
+ ...(responseMessage ? {
365
+ artifacts: [{
366
+ artifactId: `artifact-${input.taskId}`,
367
+ name: "response",
368
+ parts: responseMessage.parts,
369
+ }],
370
+ } : {}),
371
+ };
372
+ }
373
+ async function startA2AServer(options) {
374
+ const host = options.host ?? config_1.A2A_DEFAULT_HOST;
375
+ /* v8 ignore next -- daemon-managed A2A owns the default-port path; protocol tests bind port 0 to avoid collisions @preserve */
376
+ const port = options.port ?? (0, config_1.defaultA2APort)(options.agentName);
377
+ const a2aPath = (0, config_1.normalizeA2APath)(options.path);
378
+ /* v8 ignore next -- foreground CLI/default daemon paths own the ambient agent-root fallback; protocol tests inject an isolated root @preserve */
379
+ const agentRoot = options.agentRoot ?? (0, identity_1.getAgentRoot)(options.agentName);
380
+ const taskStore = new task_store_1.FileA2ATaskStore(agentRoot);
381
+ /* v8 ignore next -- default runner crosses into the full live agent pipeline; shared-turn covers that pipeline and server tests inject a deterministic runner @preserve */
382
+ const turnRunner = options.turnRunner ?? defaultTurnRunner;
383
+ // The inbound friends-DataPart bridge is available only when the agent has a
384
+ // cryptographic identity (its did:key + X25519 unseal keys). Build its durable
385
+ // stores once at start; without an identity, inbound stays on the text path.
386
+ let inboundShareDeps;
387
+ if (options.identity) {
388
+ const friendsDir = `${agentRoot}/friends`;
389
+ inboundShareDeps = {
390
+ sodium: await (0, a2a_client_1.ready)(),
391
+ store: new friends_1.FileFriendStore(friendsDir),
392
+ // The SAME canonical mission store the Slice-4 delegation tools use, so an
393
+ // inbound `importCoordination` write lands where the read/prepare surface reads.
394
+ missionStore: (0, delegation_stores_1.delegationStoresFor)(agentRoot).missionStore,
395
+ pinStore: new pin_store_1.FileA2APinStore(agentRoot),
396
+ seen: new seen_ledger_1.FileA2ASeenLedger(agentRoot),
397
+ didResolution: (0, did_resolution_1.makeDidResolution)({ sodium: await (0, a2a_client_1.ready)() }),
398
+ identity: options.identity,
399
+ };
400
+ }
401
+ // Resolved failure reports are confirmed to the owner once the running version reaches the fix: now, after each
402
+ // resolution, and on a timer, so a fix that lands with a restart is announced without anyone calling again.
403
+ const confirmReports = async () => {
404
+ if (!options.escalation)
405
+ return;
406
+ try {
407
+ await (0, failure_reports_1.confirmResolvedReports)(agentRoot, { ...options.escalation, ...(inboundShareDeps ? { friends: inboundShareDeps.store } : {}) });
408
+ }
409
+ catch (error) {
410
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "channels", event: "channel.a2a_escalation_confirm_error", message: "confirming resolved failure reports failed", meta: { agentName: options.agentName, error: error instanceof Error ? error.message : String(error) } });
411
+ }
412
+ };
413
+ let confirmTimer;
414
+ let publicBaseUrl = options.baseUrl;
415
+ const server = http.createServer(async (req, res) => {
416
+ /* v8 ignore next -- Node always supplies url/host for accepted HTTP requests; fallback keeps malformed local calls safe @preserve */
417
+ const requestUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? `${host}:${port}`}`);
418
+ /* v8 ignore next -- host fallback is defensive for malformed local requests; publicBaseUrl/default host branches are covered @preserve */
419
+ const currentBaseUrl = publicBaseUrl ?? `http://${req.headers.host ?? `${host}:${port}`}`;
420
+ if (req.method === "GET" && (requestUrl.pathname === "/.well-known/agent-card.json" || requestUrl.pathname === "/agent-card.json")) {
421
+ writeJson(res, 200, (0, card_1.buildA2AAgentCard)({
422
+ agentName: options.agentName,
423
+ baseUrl: currentBaseUrl,
424
+ path: a2aPath,
425
+ ...(options.identity ? { did: options.identity.did } : {}),
426
+ }));
427
+ return;
428
+ }
429
+ if (req.method !== "POST" || requestUrl.pathname !== a2aPath) {
430
+ writeJson(res, 404, { error: "not found" });
431
+ return;
432
+ }
433
+ let rpc;
434
+ try {
435
+ const rawBody = await readBody(req);
436
+ rpc = JSON.parse(rawBody);
437
+ }
438
+ catch (error) {
439
+ if (error instanceof A2ARequestError) {
440
+ writeJson(res, error.status, errorResponse(null, error.code, error.message));
441
+ return;
442
+ }
443
+ writeJson(res, 400, errorResponse(null, -32700, "invalid JSON"));
444
+ return;
445
+ }
446
+ try {
447
+ if ((0, outbox_wire_1.isOutboxMethod)(rpc.method)) {
448
+ // Peer outbox methods: signed and sealed like a chat, access decided here from the verified friend record.
449
+ const outboxInbound = messageFromParams(rpc.params);
450
+ if (!outboxInbound || !inboundShareDeps) {
451
+ writeJson(res, 200, errorResponse(rpc.id, outbox_wire_1.OUTBOX_ERROR_REFUSED, "outbox calls need a signed message and an A2A identity"));
452
+ return;
453
+ }
454
+ const bridged = await (0, inbound_share_1.receiveInboundShare)({ ...outboxInbound, kind: outboxInbound.kind ?? "message" }, inboundShareDeps);
455
+ if (bridged.outcome === "rejected") {
456
+ writeJson(res, 200, errorResponse(rpc.id, rejectionErrorCode(bridged.reason), `A2A outbox call rejected: ${bridged.reason}`));
457
+ return;
458
+ }
459
+ if (bridged.outcome !== "completed" || !bridged.message) {
460
+ writeJson(res, 200, errorResponse(rpc.id, outbox_wire_1.OUTBOX_ERROR_REFUSED, "outbox calls must be a signed chat message"));
461
+ return;
462
+ }
463
+ const command = (0, outbox_wire_1.parseOutboxCommand)(bridged.message.text);
464
+ if (!command || command.method !== rpc.method) {
465
+ writeJson(res, 200, errorResponse(rpc.id, outbox_wire_1.OUTBOX_ERROR_INVALID, "the signed method does not match the requested method"));
466
+ return;
467
+ }
468
+ const outcome = await (0, outbox_wire_1.handleOutboxCommand)({ agentRoot, friend: bridged.friend, method: command.method, params: command.params, verifiedDid: bridged.verifiedDid });
469
+ if (!outcome.ok) {
470
+ writeJson(res, 200, errorResponse(rpc.id, outcome.code, outcome.message));
471
+ return;
472
+ }
473
+ if (command.method === "report/resolve")
474
+ await confirmReports();
475
+ /* v8 ignore next -- receiveShare pins the verified sender before it reports a completed message @preserve */
476
+ const outboxPinned = inboundShareDeps.pinStore.get(bridged.verifiedDid);
477
+ const contextId = outboxInbound.contextId ?? "default";
478
+ const reply = (0, sealed_chat_1.sealChatMessage)({
479
+ sodium: inboundShareDeps.sodium,
480
+ from: options.identity,
481
+ recipientDid: bridged.verifiedDid,
482
+ recipientEd25519Pub: outboxPinned.ed25519Pub,
483
+ text: JSON.stringify(outcome.result),
484
+ conversationId: contextId,
485
+ });
486
+ writeJson(res, 200, jsonResponse(rpc.id, { kind: "message", role: "ROLE_AGENT", messageId: (0, node_crypto_1.randomUUID)(), contextId, parts: reply.parts }));
487
+ return;
488
+ }
489
+ if (rpc.method === "SendMessage" || rpc.method === "message/send") {
490
+ const responseStyle = rpc.method === "message/send" ? "legacy" : "latest";
491
+ const parsedInbound = messageFromParams(rpc.params);
492
+ const inbound = parsedInbound ? { ...parsedInbound, kind: parsedInbound.kind ?? "message" } : null;
493
+ // HARNESS-OWNED RESULT WIRE (runs BEFORE the friends-share branch). A
494
+ // `mission_result`-tagged DataPart is NOT a FriendsKind — it routes to
495
+ // `importMissionResult` (assignee/correlation-gated, store-only, NO turn), never
496
+ // to `receiveShare`. Recognized by the `ouroKind` discriminator.
497
+ if (inbound && inboundShareDeps && (0, mission_result_wire_1.isMissionResultDataPart)(inbound)) {
498
+ const imported = await (0, mission_result_wire_1.receiveInboundMissionResult)(inbound, {
499
+ sodium: inboundShareDeps.sodium,
500
+ store: inboundShareDeps.store,
501
+ missionStore: inboundShareDeps.missionStore,
502
+ // The SAME authentication seam the share bridge uses — so a forged-sender
503
+ // result is rejected by the DidVerifier exactly like a forged share.
504
+ pinStore: inboundShareDeps.pinStore,
505
+ seen: inboundShareDeps.seen,
506
+ didResolution: inboundShareDeps.didResolution,
507
+ identity: inboundShareDeps.identity,
508
+ });
509
+ if (imported.outcome === "rejected") {
510
+ writeJson(res, 200, errorResponse(rpc.id, rejectionErrorCode(imported.reason), `A2A result rejected: ${imported.reason}`));
511
+ return;
512
+ }
513
+ // imported (store-only, no turn): acknowledge with a minimal completed task.
514
+ /* v8 ignore next -- "not-a-result" is unreachable here (gated by isMissionResultDataPart) @preserve */
515
+ const ackText = imported.outcome === "imported"
516
+ ? `[a2a] imported mission result from ${imported.verifiedDid}`
517
+ /* v8 ignore next -- defensive: the gate above guarantees imported|rejected @preserve */
518
+ : "[a2a] mission result";
519
+ const contextId = inbound.contextId ?? "default";
520
+ const taskId = (0, node_crypto_1.randomUUID)();
521
+ const accessToken = (0, node_crypto_1.randomUUID)();
522
+ const ackTask = taskFor({ taskId, accessToken, contextId, inbound, state: "TASK_STATE_COMPLETED", response: ackText });
523
+ taskStore.put(ackTask, accessTokenScope(accessToken));
524
+ writeJson(res, 200, jsonResponse(rpc.id, publicTask(ackTask, accessToken, responseStyle, true)));
525
+ return;
526
+ }
527
+ // Inbound friends-DataPart branch (runs BEFORE the legacy text path). A
528
+ // sealed DataPart is unwrapped + verified through the bridge; the turn is
529
+ // then keyed on the VERIFIED sender DID (replacing the unauthenticated
530
+ // sentinel). A non-friends (text) message falls through unchanged.
531
+ let verifiedPeerAgentId;
532
+ let verifiedPeerName;
533
+ let verifiedShareText;
534
+ let verifiedChat;
535
+ if (inbound && inboundShareDeps && messageHasDataPart(inbound)) {
536
+ const bridged = await (0, inbound_share_1.receiveInboundShare)(inbound, inboundShareDeps);
537
+ if (bridged.outcome === "rejected") {
538
+ writeJson(res, 200, errorResponse(rpc.id, rejectionErrorCode(bridged.reason), `A2A share rejected: ${bridged.reason}`));
539
+ return;
540
+ }
541
+ // A message with a data part always resolves to completed|rejected — the
542
+ // bridge only returns "not-a-share" when there is NO data part, which the
543
+ // `messageHasDataPart` gate above excludes. So this is the completed path.
544
+ /* v8 ignore next -- "not-a-share" is unreachable here (gated by messageHasDataPart) @preserve */
545
+ if (bridged.outcome === "completed") {
546
+ verifiedPeerAgentId = bridged.verifiedDid;
547
+ verifiedPeerName = bridged.verifiedDid;
548
+ if (bridged.message) {
549
+ // Authenticated chat: the signed, sealed text IS the turn.
550
+ verifiedShareText = bridged.message.text;
551
+ /* v8 ignore next -- a completed chat always has a friend record: an unknown DID reads as stranger and the message is refused @preserve */
552
+ verifiedPeerName = bridged.friend?.name ?? bridged.verifiedDid;
553
+ verifiedChat = { did: bridged.verifiedDid, friend: bridged.friend, ...(bridged.message.onBehalfOf ? { onBehalfOf: bridged.message.onBehalfOf } : {}) };
554
+ }
555
+ else {
556
+ verifiedShareText = `[a2a] received ${bridged.friendsKind} (${bridged.status}) from ${bridged.verifiedDid}`;
557
+ }
558
+ }
559
+ }
560
+ const text = verifiedShareText ?? textFromMessage(inbound);
561
+ if (!inbound || !text) {
562
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "SendMessage requires a text message"));
563
+ return;
564
+ }
565
+ if (text.length > MAX_A2A_MESSAGE_TEXT_CHARS) {
566
+ writeJson(res, 200, errorResponse(rpc.id, -32602, `SendMessage text exceeds ${MAX_A2A_MESSAGE_TEXT_CHARS} characters`));
567
+ return;
568
+ }
569
+ const senderHint = senderHintFromMessage(req, inbound);
570
+ // The verified DID wins as the turn's peer identity; otherwise the legacy
571
+ // unauthenticated sentinel (text path, behavior-preserved).
572
+ const peerAgentId = verifiedPeerAgentId ?? untrustedTurnPeerExternalId();
573
+ const peerName = verifiedPeerName ?? senderHint.name;
574
+ const continuationToken = accessTokenFromParams(rpc.params);
575
+ const continuationTask = inbound.taskId && continuationToken
576
+ ? taskStore.get(inbound.taskId, accessTokenScope(continuationToken))
577
+ : null;
578
+ if (inbound.taskId && continuationToken && (!continuationTask || !taskAuthorized(continuationTask, continuationToken))) {
579
+ writeJson(res, 200, errorResponse(rpc.id, -32001, "task not found"));
580
+ return;
581
+ }
582
+ if (continuationTask && isTerminalTaskState(continuationTask.status.state)) {
583
+ writeJson(res, 200, errorResponse(rpc.id, -32002, "task is terminal; start a new task"));
584
+ return;
585
+ }
586
+ const contextId = inbound.contextId ?? continuationTask?.contextId ?? "default";
587
+ const taskId = continuationTask?.id ?? (0, node_crypto_1.randomUUID)();
588
+ const accessToken = continuationToken && continuationTask ? continuationToken : (0, node_crypto_1.randomUUID)();
589
+ const tokenScope = accessTokenScope(accessToken);
590
+ const clientTaskId = continuationTask ? taskA2AMetadata(continuationTask).clientTaskId : inbound.taskId;
591
+ let relationshipAuthorization = verifiedChat?.friend
592
+ ? a2aChatRelationship(agentRoot, verifiedChat.friend, taskId)
593
+ : undefined;
594
+ let turnText = text;
595
+ let delegatedCommand;
596
+ // Only the server writes the delegated banner. Any turn that is not about to be admitted as a delegated command
597
+ // (verified or not, including a plain unauthenticated text turn) gets a typed banner marked as the sender's own words.
598
+ if (verifiedChat?.onBehalfOf !== "principal")
599
+ turnText = (0, delegated_command_1.shieldDelegatedBanner)(text);
600
+ if (verifiedChat?.onBehalfOf === "principal") {
601
+ // A delegated command runs with the principal's authority only after the
602
+ // server, never the model, has checked the grant and told the principal.
603
+ let registry;
604
+ try {
605
+ registry = (0, relationship_authorization_1.loadRelationshipCapabilityRegistry)(agentRoot);
606
+ }
607
+ catch {
608
+ registry = undefined;
609
+ }
610
+ /* v8 ignore next -- a completed chat always carries the sender's friend record (see the receipt above) @preserve */
611
+ if (!verifiedChat.friend)
612
+ throw new Error("verified chat has no friend record");
613
+ const admission = await (0, delegated_command_1.admitDelegatedCommand)({ friend: verifiedChat.friend, did: verifiedChat.did, text, commandId: (0, node_crypto_1.randomUUID)(), store: inboundShareDeps.store, registry, options: options.delegation });
614
+ if (!admission.ok) {
615
+ // The code and the "delegated command refused: <reason>" prefix stay: the replay gate and older CLIs match them.
616
+ // Only an active family peer is told why: anyone else gets no_grant whatever the real reason was (a broken trust file, a key mismatch), which stays in the local log and nerves.
617
+ const activeFamily = verifiedChat.friend.trustLevel === "family" && verifiedChat.friend.admissionState === "active";
618
+ const shown = activeFamily ? admission.reason : "no_grant";
619
+ const guidance = (0, delegated_command_1.delegationRefusalGuidance)(shown, { legacyRecordGrant: activeFamily && verifiedChat.friend.delegationGrant !== undefined });
620
+ writeJson(res, 200, errorResponse(rpc.id, -32004, `delegated command refused: ${shown} (${guidance.message}). Nothing ran. Next: ${guidance.next}`, { reason: shown, nothingRan: true, retry: guidance.retry, next: guidance.next }));
621
+ return;
622
+ }
623
+ relationshipAuthorization = admission.relationship;
624
+ turnText = admission.turnText;
625
+ delegatedCommand = admission.context;
626
+ }
627
+ taskStore.put(taskFor({ taskId, accessToken, contextId, inbound, state: "TASK_STATE_WORKING", clientTaskId, previousTask: continuationTask ?? undefined }), tokenScope);
628
+ const turn = await turnRunner({
629
+ agentName: options.agentName,
630
+ peerAgentId,
631
+ peerName,
632
+ sessionKey: contextId,
633
+ message: turnText,
634
+ ...(relationshipAuthorization ? { relationshipAuthorization } : {}),
635
+ ...(delegatedCommand ? { delegatedCommand } : {}),
636
+ });
637
+ let responseParts;
638
+ if (verifiedChat) {
639
+ // A verified chat's reply is sealed to the sender and stored sealed, so neither
640
+ // the wire nor a later GetTask ever carries the plaintext.
641
+ const pinned = inboundShareDeps.pinStore.get(verifiedChat.did);
642
+ /* v8 ignore next 4 -- receiveShare pins the verified sender before it reports a completed chat; refuse rather than reply in plaintext @preserve */
643
+ if (!pinned) {
644
+ writeJson(res, 200, errorResponse(rpc.id, -32003, "A2A chat reply cannot be sealed to the sender"));
645
+ return;
646
+ }
647
+ responseParts = (0, sealed_chat_1.sealChatMessage)({
648
+ sodium: inboundShareDeps.sodium,
649
+ from: options.identity,
650
+ recipientDid: verifiedChat.did,
651
+ recipientEd25519Pub: pinned.ed25519Pub,
652
+ text: turn.response,
653
+ conversationId: contextId,
654
+ }).parts;
655
+ }
656
+ const task = taskFor({ taskId, accessToken, contextId, inbound, state: "TASK_STATE_COMPLETED", response: turn.response, responseParts, clientTaskId, previousTask: continuationTask ?? undefined });
657
+ taskStore.put(task, tokenScope);
658
+ writeJson(res, 200, jsonResponse(rpc.id, publicTask(task, accessToken, responseStyle, true)));
659
+ return;
660
+ }
661
+ if (rpc.method === "GetTask" || rpc.method === "tasks/get") {
662
+ const responseStyle = rpc.method === "tasks/get" ? "legacy" : "latest";
663
+ const taskId = rpc.params && typeof rpc.params === "object"
664
+ ? rpc.params.id
665
+ : undefined;
666
+ if (typeof taskId !== "string" || !taskId.trim()) {
667
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "GetTask requires id"));
668
+ return;
669
+ }
670
+ const accessToken = accessTokenFromParams(rpc.params);
671
+ if (!accessToken) {
672
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "GetTask requires accessToken"));
673
+ return;
674
+ }
675
+ const task = taskStore.get(taskId, accessTokenScope(accessToken));
676
+ writeJson(res, 200, task && taskAuthorized(task, accessToken)
677
+ ? jsonResponse(rpc.id, publicTask(task, accessToken, responseStyle, false))
678
+ : errorResponse(rpc.id, -32001, "task not found"));
679
+ return;
680
+ }
681
+ if (rpc.method === "CancelTask" || rpc.method === "tasks/cancel") {
682
+ const responseStyle = rpc.method === "tasks/cancel" ? "legacy" : "latest";
683
+ const taskId = rpc.params && typeof rpc.params === "object"
684
+ ? rpc.params.id
685
+ : undefined;
686
+ if (typeof taskId !== "string" || !taskId.trim()) {
687
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "CancelTask requires id"));
688
+ return;
689
+ }
690
+ const accessToken = accessTokenFromParams(rpc.params);
691
+ if (!accessToken) {
692
+ writeJson(res, 200, errorResponse(rpc.id, -32602, "CancelTask requires accessToken"));
693
+ return;
694
+ }
695
+ const tokenScope = accessTokenScope(accessToken);
696
+ const task = taskStore.get(taskId, tokenScope);
697
+ if (!task || !taskAuthorized(task, accessToken)) {
698
+ writeJson(res, 200, errorResponse(rpc.id, -32001, "task not found"));
699
+ return;
700
+ }
701
+ const canceled = {
702
+ ...task,
703
+ status: { state: "TASK_STATE_CANCELED", timestamp: new Date().toISOString() },
704
+ };
705
+ taskStore.put(canceled, tokenScope);
706
+ writeJson(res, 200, jsonResponse(rpc.id, publicTask(canceled, accessToken, responseStyle, false)));
707
+ return;
708
+ }
709
+ writeJson(res, 200, errorResponse(rpc.id, -32601, `unknown method: ${rpc.method}`));
710
+ }
711
+ catch (error) {
712
+ const message = error instanceof Error ? error.message : /* v8 ignore next -- defensive non-Error throw branch @preserve */ String(error);
713
+ writeJson(res, 200, errorResponse(rpc.id, -32000, message));
714
+ }
715
+ });
716
+ await new Promise((resolve, reject) => {
717
+ const onError = (error) => {
718
+ server.off("listening", onListening);
719
+ reject(error);
720
+ };
721
+ const onListening = () => {
722
+ server.off("error", onError);
723
+ resolve();
724
+ };
725
+ server.once("error", onError);
726
+ server.once("listening", onListening);
727
+ server.listen(port, host);
728
+ });
729
+ const address = server.address();
730
+ /* v8 ignore next -- server.address() is an address object after successful listen on TCP @preserve */
731
+ const actualPort = typeof address === "object" && address ? address.port : port;
732
+ const localBaseUrl = `http://${host}:${actualPort}`;
733
+ publicBaseUrl = publicBaseUrl ?? localBaseUrl;
734
+ const endpointUrl = new URL(publicBaseUrl);
735
+ endpointUrl.pathname = a2aPath;
736
+ endpointUrl.search = "";
737
+ endpointUrl.hash = "";
738
+ if (options.escalation) {
739
+ await confirmReports();
740
+ confirmTimer = setInterval(() => { void confirmReports(); }, options.escalation.confirmIntervalMs ?? exports.ESCALATION_CONFIRM_INTERVAL_MS);
741
+ confirmTimer.unref();
742
+ }
743
+ (0, runtime_1.emitNervesEvent)({
744
+ component: "channels",
745
+ event: "channel.a2a_server_started",
746
+ message: "A2A sense server started",
747
+ meta: { agentName: options.agentName, url: publicBaseUrl, endpoint: endpointUrl.toString() },
748
+ });
749
+ return {
750
+ server,
751
+ url: publicBaseUrl,
752
+ endpointUrl: endpointUrl.toString(),
753
+ close: () => new Promise((resolve, reject) => {
754
+ if (confirmTimer)
755
+ clearInterval(confirmTimer);
756
+ server.close((error) => {
757
+ if (error) {
758
+ reject(error);
759
+ return;
760
+ }
761
+ (0, runtime_1.emitNervesEvent)({
762
+ component: "channels",
763
+ event: "channel.a2a_server_stopped",
764
+ message: "A2A sense server stopped",
765
+ meta: { agentName: options.agentName },
766
+ });
767
+ resolve();
768
+ });
769
+ }),
770
+ };
771
+ }