@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831

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 (647) 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 +5308 -16
  16. package/deploy/unraid/Dockerfile +54 -0
  17. package/deploy/unraid/README.txt +2983 -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-deployment-target.mjs +710 -0
  34. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  35. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
  36. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  37. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  38. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  39. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  40. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  41. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  42. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
  43. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
  49. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  50. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
  51. package/deploy/unraid/sanctuary.xml +28 -0
  52. package/dist/a2a/card.js +57 -0
  53. package/dist/a2a/client.js +180 -0
  54. package/dist/a2a/config.js +50 -0
  55. package/dist/a2a/delegation-stores.js +56 -0
  56. package/dist/a2a/did-resolution.js +93 -0
  57. package/dist/a2a/identity.js +170 -0
  58. package/dist/a2a/inbound-share.js +107 -0
  59. package/dist/a2a/mission-result-wire.js +196 -0
  60. package/dist/a2a/onboarding.js +115 -0
  61. package/dist/a2a/pin-store.js +132 -0
  62. package/dist/a2a/seen-ledger.js +120 -0
  63. package/dist/a2a/server.js +604 -0
  64. package/dist/a2a/task-store.js +69 -0
  65. package/dist/a2a/transport.js +45 -0
  66. package/dist/a2a/types.js +3 -0
  67. package/dist/arc/attention-types.js +8 -0
  68. package/dist/arc/cares.js +360 -0
  69. package/dist/arc/episodes.js +118 -0
  70. package/dist/arc/evolution.js +490 -0
  71. package/dist/arc/flight-recorder.js +1034 -0
  72. package/dist/arc/intentions.js +134 -0
  73. package/dist/arc/json-store.js +117 -0
  74. package/dist/arc/obligations.js +386 -0
  75. package/dist/arc/packets.js +336 -0
  76. package/dist/arc/presence.js +185 -0
  77. package/dist/arc/task-lifecycle.js +57 -0
  78. package/dist/commerce/store.js +755 -0
  79. package/dist/commerce/types.js +3 -0
  80. package/dist/heart/active-work.js +798 -40
  81. package/dist/heart/agent-entry.js +252 -3
  82. package/dist/heart/approval-files.js +113 -0
  83. package/dist/heart/approval-store.js +960 -0
  84. package/dist/heart/attachments/image-normalize.js +194 -0
  85. package/dist/heart/attachments/materialize.js +97 -0
  86. package/dist/heart/attachments/originals.js +88 -0
  87. package/dist/heart/attachments/render.js +29 -0
  88. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  89. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  90. package/dist/heart/attachments/sources/index.js +18 -0
  91. package/dist/heart/attachments/sources/telegram.js +71 -0
  92. package/dist/heart/attachments/store.js +132 -0
  93. package/dist/heart/attachments/types.js +93 -0
  94. package/dist/heart/auth/auth-flow.js +495 -0
  95. package/dist/heart/autonomy-budget.js +478 -0
  96. package/dist/heart/awaiting/await-alert.js +148 -0
  97. package/dist/heart/awaiting/await-expiry.js +143 -0
  98. package/dist/heart/awaiting/await-loader.js +91 -0
  99. package/dist/heart/awaiting/await-parser.js +149 -0
  100. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  101. package/dist/heart/awaiting/await-scheduler.js +382 -0
  102. package/dist/heart/background-operations.js +281 -0
  103. package/dist/heart/bridges/manager.js +137 -17
  104. package/dist/heart/bridges/store.js +14 -2
  105. package/dist/heart/bundle-state.js +168 -0
  106. package/dist/heart/commitments.js +44 -18
  107. package/dist/heart/config-registry.js +331 -0
  108. package/dist/heart/config.js +174 -131
  109. package/dist/heart/context-loss-gauntlet.js +387 -0
  110. package/dist/heart/context-loss-sentinel.js +1157 -0
  111. package/dist/heart/core.js +2169 -581
  112. package/dist/heart/cross-chat-delivery.js +9 -22
  113. package/dist/heart/daemon/agent-config-check.js +451 -0
  114. package/dist/heart/daemon/agent-discovery.js +185 -3
  115. package/dist/heart/daemon/agent-service.js +542 -0
  116. package/dist/heart/daemon/agentic-repair.js +547 -0
  117. package/dist/heart/daemon/await-private-wake.js +59 -0
  118. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  119. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  120. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  121. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  122. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  123. package/dist/heart/daemon/cadence.js +180 -0
  124. package/dist/heart/daemon/cli-defaults.js +854 -0
  125. package/dist/heart/daemon/cli-desk.js +322 -0
  126. package/dist/heart/daemon/cli-exec.js +8822 -0
  127. package/dist/heart/daemon/cli-help.js +716 -0
  128. package/dist/heart/daemon/cli-parse.js +2771 -0
  129. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  130. package/dist/heart/daemon/cli-render.js +777 -0
  131. package/dist/heart/daemon/cli-types.js +8 -0
  132. package/dist/heart/daemon/connect-bay.js +323 -0
  133. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  134. package/dist/heart/daemon/container-healthcheck.js +112 -0
  135. package/dist/heart/daemon/container-runtime.js +97 -0
  136. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  137. package/dist/heart/daemon/container-spec-auditor.js +229 -0
  138. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  139. package/dist/heart/daemon/daemon-cli.js +29 -2349
  140. package/dist/heart/daemon/daemon-entry.js +930 -11
  141. package/dist/heart/daemon/daemon-health.js +186 -0
  142. package/dist/heart/daemon/daemon-rollup.js +57 -0
  143. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  144. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  145. package/dist/heart/daemon/daemon.js +2084 -105
  146. package/dist/heart/daemon/dns-workflow.js +394 -0
  147. package/dist/heart/daemon/doctor-types.js +8 -0
  148. package/dist/heart/daemon/doctor.js +1755 -0
  149. package/dist/heart/daemon/freshness.js +345 -0
  150. package/dist/heart/daemon/habit-private-wake.js +61 -0
  151. package/dist/heart/daemon/health-monitor.js +142 -11
  152. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  153. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  154. package/dist/heart/daemon/http-health-probe.js +80 -0
  155. package/dist/heart/daemon/human-command-screens.js +234 -0
  156. package/dist/heart/daemon/human-readiness.js +114 -0
  157. package/dist/heart/daemon/inner-status.js +78 -0
  158. package/dist/heart/daemon/interactive-repair.js +394 -0
  159. package/dist/heart/daemon/launchd.js +37 -8
  160. package/dist/heart/daemon/log-tailer.js +79 -10
  161. package/dist/heart/daemon/logs-prune.js +132 -0
  162. package/dist/heart/daemon/mcp-canary.js +524 -0
  163. package/dist/heart/daemon/message-router.js +65 -5
  164. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  165. package/dist/heart/daemon/os-cron-deps.js +135 -0
  166. package/dist/heart/daemon/os-cron.js +22 -14
  167. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  168. package/dist/heart/daemon/ouro-entry.js +3 -1
  169. package/dist/heart/daemon/plugin-cli.js +432 -0
  170. package/dist/heart/daemon/process-manager.js +733 -61
  171. package/dist/heart/daemon/provider-discovery.js +137 -0
  172. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  173. package/dist/heart/daemon/prunable-bundle.js +144 -0
  174. package/dist/heart/daemon/pulse.js +511 -0
  175. package/dist/heart/daemon/readiness-repair.js +365 -0
  176. package/dist/heart/daemon/run-hooks.js +2 -0
  177. package/dist/heart/daemon/runtime-logging.js +47 -14
  178. package/dist/heart/daemon/runtime-metadata.js +2 -30
  179. package/dist/heart/daemon/runtime-mode.js +13 -2
  180. package/dist/heart/daemon/safe-mode.js +161 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  184. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  185. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  186. package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
  187. package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
  188. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  189. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
  190. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  191. package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
  192. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  193. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
  194. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  195. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  196. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  197. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  198. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  199. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  200. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  201. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
  202. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  203. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
  204. package/dist/heart/daemon/sense-manager.js +699 -48
  205. package/dist/heart/daemon/session-id-resolver.js +131 -0
  206. package/dist/heart/daemon/skill-management-installer.js +1 -1
  207. package/dist/heart/daemon/socket-client.js +180 -12
  208. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  209. package/dist/heart/daemon/startup-tui.js +339 -0
  210. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  211. package/dist/heart/daemon/task-scheduler.js +117 -39
  212. package/dist/heart/daemon/terminal-ui.js +499 -0
  213. package/dist/heart/daemon/thoughts.js +138 -54
  214. package/dist/heart/daemon/up-progress.js +366 -0
  215. package/dist/heart/daemon/vault-items.js +56 -0
  216. package/dist/heart/delegation.js +1 -4
  217. package/dist/heart/external-events/router.js +1430 -0
  218. package/dist/heart/frontend-approval-runtime.js +506 -0
  219. package/dist/heart/frontend-journal.js +215 -0
  220. package/dist/heart/frontend-session-service.js +237 -0
  221. package/dist/heart/frontend-socket-client.js +164 -0
  222. package/dist/heart/frontend-socket.js +400 -0
  223. package/dist/heart/habits/habit-cancel.js +810 -0
  224. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  225. package/dist/heart/habits/habit-migration.js +194 -0
  226. package/dist/heart/habits/habit-parser.js +278 -0
  227. package/dist/heart/habits/habit-runtime-state.js +93 -0
  228. package/dist/heart/habits/habit-scheduler.js +653 -0
  229. package/dist/heart/habits/habit-session-summary.js +318 -0
  230. package/dist/heart/habits/habit-session.js +636 -0
  231. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  232. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  233. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  234. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  235. package/dist/heart/identity.js +196 -59
  236. package/dist/heart/kept-notes.js +289 -0
  237. package/dist/heart/kicks.js +1 -1
  238. package/dist/heart/machine-identity.js +161 -0
  239. package/dist/heart/mail-import-discovery.js +356 -0
  240. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  241. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  242. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  243. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  244. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  245. package/dist/heart/mailbox/mailbox-http.js +99 -0
  246. package/dist/heart/mailbox/mailbox-read.js +39 -0
  247. package/dist/heart/mailbox/mailbox-types.js +27 -0
  248. package/dist/heart/mailbox/mailbox-view.js +197 -0
  249. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  250. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  251. package/dist/heart/mailbox/readers/mail.js +375 -0
  252. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  253. package/dist/heart/mailbox/readers/sessions.js +231 -0
  254. package/dist/heart/mailbox/readers/shared.js +111 -0
  255. package/dist/heart/mcp/mcp-server.js +696 -0
  256. package/dist/heart/migrate-config.js +100 -0
  257. package/dist/heart/model-capabilities.js +11 -0
  258. package/dist/heart/orientation-frame.js +345 -0
  259. package/dist/heart/platform.js +81 -0
  260. package/dist/heart/primitives.js +1 -1
  261. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  262. package/dist/heart/private-runtime/index.js +18 -0
  263. package/dist/heart/private-runtime/ledger.js +221 -0
  264. package/dist/heart/private-runtime/policy.js +252 -0
  265. package/dist/heart/private-runtime/types.js +2 -0
  266. package/dist/heart/progress-story.js +1 -1
  267. package/dist/heart/provider-attempt.js +137 -0
  268. package/dist/heart/provider-binding-resolver.js +273 -0
  269. package/dist/heart/provider-credentials.js +449 -0
  270. package/dist/heart/provider-failover.js +311 -0
  271. package/dist/heart/provider-models.js +96 -0
  272. package/dist/heart/provider-ping.js +265 -0
  273. package/dist/heart/provider-readiness-cache.js +119 -0
  274. package/dist/heart/provider-visibility.js +188 -0
  275. package/dist/heart/providers/anthropic-token.js +131 -0
  276. package/dist/heart/providers/anthropic.js +173 -60
  277. package/dist/heart/providers/azure.js +23 -11
  278. package/dist/heart/providers/error-classification.js +127 -0
  279. package/dist/heart/providers/github-copilot.js +34 -38
  280. package/dist/heart/providers/minimax-vlm.js +189 -0
  281. package/dist/heart/providers/minimax.js +26 -8
  282. package/dist/heart/providers/openai-codex-token.js +349 -0
  283. package/dist/heart/providers/openai-codex.js +55 -40
  284. package/dist/heart/providers/openai-compatible.js +177 -0
  285. package/dist/heart/run-ledger.js +247 -0
  286. package/dist/heart/runtime-capability-check.js +170 -0
  287. package/dist/heart/runtime-credentials.js +607 -0
  288. package/dist/heart/runtime-cwd.js +87 -0
  289. package/dist/heart/sense-truth.js +22 -4
  290. package/dist/heart/session-activity.js +92 -24
  291. package/dist/heart/session-events.js +1504 -0
  292. package/dist/heart/session-playback-cli-main.js +5 -0
  293. package/dist/heart/session-playback-cli.js +36 -0
  294. package/dist/heart/session-playback.js +231 -0
  295. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  296. package/dist/heart/session-redaction-repair.js +552 -0
  297. package/dist/heart/session-stats-cli-main.js +5 -0
  298. package/dist/heart/session-stats.js +183 -0
  299. package/dist/heart/session-transcript.js +133 -0
  300. package/dist/heart/start-of-turn-packet.js +372 -0
  301. package/dist/heart/steward-policy.js +618 -0
  302. package/dist/heart/streaming.js +604 -207
  303. package/dist/heart/structured-output.js +196 -0
  304. package/dist/heart/sync-classification.js +176 -0
  305. package/dist/heart/sync.js +449 -0
  306. package/dist/heart/target-resolution.js +11 -7
  307. package/dist/heart/tempo.js +93 -0
  308. package/dist/heart/temporal-view.js +41 -0
  309. package/dist/heart/timeouts.js +101 -0
  310. package/dist/heart/tool-activity-callbacks.js +59 -0
  311. package/dist/heart/tool-approval.js +382 -0
  312. package/dist/heart/tool-description.js +155 -0
  313. package/dist/heart/tool-friction.js +55 -0
  314. package/dist/heart/tool-loop.js +200 -0
  315. package/dist/heart/turn-context.js +482 -0
  316. package/dist/heart/turn-execution-lease.js +30 -0
  317. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  318. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  319. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  320. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  321. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  322. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  323. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  324. package/dist/heart/versioning/update-hooks.js +154 -0
  325. package/dist/heart/versioning/version-intent.js +114 -0
  326. package/dist/heart/work-card.js +380 -0
  327. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  328. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  329. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  330. package/dist/mailbox-ui/index.html +16 -0
  331. package/dist/mailroom/attention.js +167 -0
  332. package/dist/mailroom/autonomy.js +209 -0
  333. package/dist/mailroom/blob-store.js +889 -0
  334. package/dist/mailroom/body-cache.js +61 -0
  335. package/dist/mailroom/cache-sync-cli.js +58 -0
  336. package/dist/mailroom/core.js +803 -0
  337. package/dist/mailroom/entry.js +160 -0
  338. package/dist/mailroom/file-store.js +568 -0
  339. package/dist/mailroom/hosted-cache-sync.js +384 -0
  340. package/dist/mailroom/mbox-import.js +393 -0
  341. package/dist/mailroom/migration.js +164 -0
  342. package/dist/mailroom/outbound.js +380 -0
  343. package/dist/mailroom/policy.js +263 -0
  344. package/dist/mailroom/reader.js +292 -0
  345. package/dist/mailroom/search-cache.js +513 -0
  346. package/dist/mailroom/search-relevance.js +319 -0
  347. package/dist/mailroom/smtp-ingress.js +176 -0
  348. package/dist/mailroom/source-state.js +176 -0
  349. package/dist/mailroom/thread.js +109 -0
  350. package/dist/mailroom/travel-extract.js +89 -0
  351. package/dist/mind/bundle-manifest.js +24 -2
  352. package/dist/mind/context.js +309 -111
  353. package/dist/mind/desk-section.js +362 -0
  354. package/dist/mind/diary-integrity.js +60 -0
  355. package/dist/mind/{memory.js → diary.js} +68 -77
  356. package/dist/mind/embedding-provider.js +60 -0
  357. package/dist/mind/file-state.js +179 -0
  358. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  359. package/dist/mind/obligation-steering.js +199 -3
  360. package/dist/mind/pending.js +36 -10
  361. package/dist/mind/prompt-budget.js +479 -0
  362. package/dist/mind/prompt-refresh.js +3 -2
  363. package/dist/mind/prompt.js +1050 -189
  364. package/dist/mind/provenance-trust.js +26 -0
  365. package/dist/mind/record-paths.js +312 -0
  366. package/dist/mind/scrutiny.js +173 -0
  367. package/dist/mind/session-transaction.js +564 -0
  368. package/dist/nerves/cli-logging.js +7 -1
  369. package/dist/nerves/coverage/audit-rules.js +15 -6
  370. package/dist/nerves/coverage/audit.js +28 -2
  371. package/dist/nerves/coverage/cli.js +1 -1
  372. package/dist/nerves/coverage/contract.js +5 -5
  373. package/dist/nerves/coverage/file-completeness.js +139 -5
  374. package/dist/nerves/coverage/run-artifacts.js +55 -35
  375. package/dist/nerves/coverage/source-scanner.js +4 -4
  376. package/dist/nerves/event-buffer.js +111 -0
  377. package/dist/nerves/index.js +293 -9
  378. package/dist/nerves/observation.js +20 -0
  379. package/dist/nerves/redact.js +79 -0
  380. package/dist/nerves/review/cli-main.js +5 -0
  381. package/dist/nerves/review/cli.js +156 -0
  382. package/dist/nerves/review/core.js +159 -0
  383. package/dist/nerves/runtime.js +17 -1
  384. package/dist/repertoire/ado-client.js +15 -56
  385. package/dist/repertoire/ado-semantic.js +16 -10
  386. package/dist/repertoire/api-client.js +97 -0
  387. package/dist/repertoire/bitwarden-store.js +1045 -0
  388. package/dist/repertoire/bundle-templates.js +71 -0
  389. package/dist/repertoire/bw-installer.js +180 -0
  390. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  391. package/dist/repertoire/coding/context-pack.js +331 -0
  392. package/dist/repertoire/coding/feedback.js +174 -32
  393. package/dist/repertoire/coding/index.js +15 -3
  394. package/dist/repertoire/coding/manager.js +159 -10
  395. package/dist/repertoire/coding/spawner.js +58 -11
  396. package/dist/repertoire/coding/tools.js +221 -15
  397. package/dist/repertoire/coding/workbench-client.js +272 -0
  398. package/dist/repertoire/coding/workbench-manager.js +346 -0
  399. package/dist/repertoire/commerce-errors.js +109 -0
  400. package/dist/repertoire/commerce-self-test.js +156 -0
  401. package/dist/repertoire/credential-access.js +178 -0
  402. package/dist/repertoire/desk/classifier.js +362 -0
  403. package/dist/repertoire/duffel-client.js +185 -0
  404. package/dist/repertoire/github-client.js +14 -55
  405. package/dist/repertoire/graph-client.js +11 -52
  406. package/dist/repertoire/guardrails.js +811 -18
  407. package/dist/repertoire/mcp-client.js +44 -3
  408. package/dist/repertoire/mcp-manager.js +427 -139
  409. package/dist/repertoire/mcp-tools.js +124 -0
  410. package/dist/repertoire/plugin-mcp.js +175 -0
  411. package/dist/repertoire/plugins.js +253 -0
  412. package/dist/repertoire/relationship-authorization.js +322 -0
  413. package/dist/repertoire/shell-sessions.js +134 -0
  414. package/dist/repertoire/skills.js +48 -4
  415. package/dist/repertoire/stripe-client.js +131 -0
  416. package/dist/repertoire/tool-arguments.js +170 -0
  417. package/dist/repertoire/tool-results.js +29 -0
  418. package/dist/repertoire/tools-a2a.js +699 -0
  419. package/dist/repertoire/tools-attachments.js +322 -0
  420. package/dist/repertoire/tools-awaiting.js +575 -0
  421. package/dist/repertoire/tools-base.js +77 -1138
  422. package/dist/repertoire/tools-bluebubbles.js +2 -0
  423. package/dist/repertoire/tools-bridge.js +144 -0
  424. package/dist/repertoire/tools-bundle.js +993 -0
  425. package/dist/repertoire/tools-commerce.js +253 -0
  426. package/dist/repertoire/tools-config.js +186 -0
  427. package/dist/repertoire/tools-continuity.js +575 -0
  428. package/dist/repertoire/tools-credential.js +383 -0
  429. package/dist/repertoire/tools-evolution.js +527 -0
  430. package/dist/repertoire/tools-files.js +344 -0
  431. package/dist/repertoire/tools-flight.js +290 -0
  432. package/dist/repertoire/tools-flow.js +119 -0
  433. package/dist/repertoire/tools-github.js +3 -8
  434. package/dist/repertoire/tools-habits.js +103 -0
  435. package/dist/repertoire/tools-mail.js +1828 -0
  436. package/dist/repertoire/tools-notes.js +485 -0
  437. package/dist/repertoire/tools-obligations.js +182 -0
  438. package/dist/repertoire/tools-orientation.js +31 -0
  439. package/dist/repertoire/tools-record.js +482 -0
  440. package/dist/repertoire/tools-rsvp.js +139 -0
  441. package/dist/repertoire/tools-runtime.js +150 -0
  442. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  443. package/dist/repertoire/tools-session.js +1133 -0
  444. package/dist/repertoire/tools-shell.js +149 -0
  445. package/dist/repertoire/tools-steward-policy.js +119 -0
  446. package/dist/repertoire/tools-stripe.js +224 -0
  447. package/dist/repertoire/tools-surface.js +369 -0
  448. package/dist/repertoire/tools-teams.js +12 -39
  449. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  450. package/dist/repertoire/tools-travel.js +125 -0
  451. package/dist/repertoire/tools-trip.js +982 -0
  452. package/dist/repertoire/tools-unraid.js +531 -0
  453. package/dist/repertoire/tools-user-profile.js +146 -0
  454. package/dist/repertoire/tools-vault.js +40 -0
  455. package/dist/repertoire/tools-voice.js +145 -0
  456. package/dist/repertoire/tools.js +494 -148
  457. package/dist/repertoire/travel-api-client.js +360 -0
  458. package/dist/repertoire/unraid-client.js +155 -0
  459. package/dist/repertoire/unraid-restart.js +339 -0
  460. package/dist/repertoire/user-profile.js +131 -0
  461. package/dist/repertoire/vault-setup.js +246 -0
  462. package/dist/repertoire/vault-unlock.js +628 -0
  463. package/dist/rsvp/aisleplanner-client.js +354 -0
  464. package/dist/rsvp/cli.js +926 -0
  465. package/dist/rsvp/config.js +327 -0
  466. package/dist/rsvp/cutover.js +433 -0
  467. package/dist/rsvp/diagnostics.js +232 -0
  468. package/dist/rsvp/diff-renderer.js +176 -0
  469. package/dist/rsvp/habit-policy.js +110 -0
  470. package/dist/rsvp/habit-stage.js +123 -0
  471. package/dist/rsvp/incident-bundle.js +97 -0
  472. package/dist/rsvp/migration.js +204 -0
  473. package/dist/rsvp/native-habit-runner.js +630 -0
  474. package/dist/rsvp/outbound-state.js +628 -0
  475. package/dist/rsvp/query.js +118 -0
  476. package/dist/rsvp/replay.js +233 -0
  477. package/dist/rsvp/snapshot.js +232 -0
  478. package/dist/rsvp/spend-ledger.js +175 -0
  479. package/dist/scripts/claude-code-hook.js +41 -0
  480. package/dist/scripts/claude-code-stop-hook.js +47 -0
  481. package/dist/senses/a2a-entry.js +115 -0
  482. package/dist/senses/acp-server.js +386 -0
  483. package/dist/senses/attention-queue.js +186 -0
  484. package/dist/senses/await-turn-message.js +58 -0
  485. package/dist/senses/bluebubbles/active-turns.js +216 -0
  486. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  487. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  488. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  489. package/dist/senses/bluebubbles/context-packet.js +207 -0
  490. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  491. package/dist/senses/bluebubbles/entry.js +90 -0
  492. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  493. package/dist/senses/bluebubbles/index.js +3841 -0
  494. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  495. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  496. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  497. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  498. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  499. package/dist/senses/bluebubbles/processed-log.js +133 -0
  500. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  501. package/dist/senses/bluebubbles/replay.js +284 -0
  502. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  503. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  504. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  505. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  506. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  507. package/dist/senses/cli/bracketed-paste.js +82 -0
  508. package/dist/senses/cli/image-paste.js +287 -0
  509. package/dist/senses/cli/image-ref-navigation.js +75 -0
  510. package/dist/senses/cli/ink-app.js +156 -0
  511. package/dist/senses/cli/inline-diff.js +64 -0
  512. package/dist/senses/cli/input-keys.js +174 -0
  513. package/dist/senses/cli/kill-ring.js +86 -0
  514. package/dist/senses/cli/message-list.js +51 -0
  515. package/dist/senses/cli/ouro-tui.js +607 -0
  516. package/dist/senses/cli/spinner-imperative.js +135 -0
  517. package/dist/senses/cli/spinner.js +101 -0
  518. package/dist/senses/cli/status-line.js +60 -0
  519. package/dist/senses/cli/streaming-markdown.js +526 -0
  520. package/dist/senses/cli/tool-display.js +85 -0
  521. package/dist/senses/cli/tool-render.js +85 -0
  522. package/dist/senses/cli/tui-store.js +241 -0
  523. package/dist/senses/cli/virtual-list.js +35 -0
  524. package/dist/senses/cli-entry.js +60 -8
  525. package/dist/senses/cli.js +604 -320
  526. package/dist/senses/commands.js +66 -3
  527. package/dist/senses/context-packet-ledger.js +371 -0
  528. package/dist/senses/context-packets.js +154 -0
  529. package/dist/senses/habit-lifecycle-guard.js +24 -0
  530. package/dist/senses/habit-turn-message.js +160 -0
  531. package/dist/senses/ingress-evidence.js +2 -0
  532. package/dist/senses/mail-entry.js +66 -0
  533. package/dist/senses/mail.js +524 -0
  534. package/dist/senses/pipeline.js +1115 -204
  535. package/dist/senses/private-runtime-worker.js +859 -0
  536. package/dist/senses/private-runtime.js +1517 -0
  537. package/dist/senses/proactive-content-guard.js +51 -0
  538. package/dist/senses/root-host-approval-port.js +345 -0
  539. package/dist/senses/root-host-approval-runtime.js +393 -0
  540. package/dist/senses/sanctuary-authority-resident.js +102 -0
  541. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  542. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  543. package/dist/senses/sanctuary-grounding.js +118 -0
  544. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  545. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  546. package/dist/senses/sanctuary-health-runner.js +100 -0
  547. package/dist/senses/sanctuary-health.js +408 -0
  548. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  549. package/dist/senses/sanctuary-interactive-control.js +410 -0
  550. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  551. package/dist/senses/sanctuary-media-optimization.js +514 -0
  552. package/dist/senses/sanctuary-runtime.js +340 -0
  553. package/dist/senses/sanctuary-sab.js +85 -0
  554. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  555. package/dist/senses/shared-turn.js +772 -0
  556. package/dist/senses/surface-tool.js +109 -0
  557. package/dist/senses/teams-entry.js +60 -8
  558. package/dist/senses/teams.js +519 -218
  559. package/dist/senses/telegram-admission.js +718 -0
  560. package/dist/senses/telegram-approval-runtime.js +793 -0
  561. package/dist/senses/telegram-attachments.js +186 -0
  562. package/dist/senses/telegram-audit-ledger.js +220 -0
  563. package/dist/senses/telegram-authority-transport.js +231 -0
  564. package/dist/senses/telegram-client.js +1749 -0
  565. package/dist/senses/telegram-effect-adapter.js +896 -0
  566. package/dist/senses/telegram-entry.js +83 -0
  567. package/dist/senses/telegram.js +2324 -0
  568. package/dist/senses/trust-gate.js +104 -9
  569. package/dist/senses/voice/audio-playback.js +237 -0
  570. package/dist/senses/voice/audio-routing.js +119 -0
  571. package/dist/senses/voice/elevenlabs.js +202 -0
  572. package/dist/senses/voice/floor-control.js +431 -0
  573. package/dist/senses/voice/floor-controller.js +115 -0
  574. package/dist/senses/voice/golden-path.js +116 -0
  575. package/dist/senses/voice/index.js +29 -0
  576. package/dist/senses/voice/meeting.js +113 -0
  577. package/dist/senses/voice/outbound.js +190 -0
  578. package/dist/senses/voice/phone.js +33 -0
  579. package/dist/senses/voice/playback.js +139 -0
  580. package/dist/senses/voice/realtime-eval.js +496 -0
  581. package/dist/senses/voice/realtime-trace.js +531 -0
  582. package/dist/senses/voice/transcript.js +70 -0
  583. package/dist/senses/voice/turn.js +191 -0
  584. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  585. package/dist/senses/voice/twilio-phone.js +5031 -0
  586. package/dist/senses/voice/types.js +2 -0
  587. package/dist/senses/voice/whisper.js +161 -0
  588. package/dist/senses/voice-entry.js +81 -0
  589. package/dist/senses/voice-realtime-eval-command.js +99 -0
  590. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  591. package/dist/senses/voice-twilio-entry.js +87 -0
  592. package/dist/trips/core.js +138 -0
  593. package/dist/trips/store.js +265 -0
  594. package/dist/util/frontmatter.js +69 -0
  595. package/npm-shrinkwrap.json +8138 -0
  596. package/package.json +72 -13
  597. package/skills/agent-commerce.md +113 -0
  598. package/skills/browser-navigation.md +117 -0
  599. package/skills/commerce-setup-guide.md +116 -0
  600. package/skills/commerce-setup.md +84 -0
  601. package/skills/configure-dev-tools.md +99 -0
  602. package/skills/travel-planning.md +138 -0
  603. package/dist/heart/daemon/auth-flow.js +0 -430
  604. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  605. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  606. package/dist/heart/daemon/update-hooks.js +0 -138
  607. package/dist/heart/obligations.js +0 -191
  608. package/dist/heart/safe-workspace.js +0 -228
  609. package/dist/heart/session-recall.js +0 -116
  610. package/dist/mind/friends/channel.js +0 -84
  611. package/dist/mind/friends/group-context.js +0 -144
  612. package/dist/mind/friends/resolver.js +0 -84
  613. package/dist/mind/friends/store-file.js +0 -190
  614. package/dist/mind/friends/store.js +0 -4
  615. package/dist/mind/friends/tokens.js +0 -26
  616. package/dist/mind/friends/trust-explanation.js +0 -74
  617. package/dist/mind/friends/types.js +0 -29
  618. package/dist/repertoire/tasks/board.js +0 -134
  619. package/dist/repertoire/tasks/index.js +0 -224
  620. package/dist/repertoire/tasks/lifecycle.js +0 -80
  621. package/dist/repertoire/tasks/middleware.js +0 -65
  622. package/dist/repertoire/tasks/parser.js +0 -173
  623. package/dist/repertoire/tasks/scanner.js +0 -132
  624. package/dist/repertoire/tasks/transitions.js +0 -144
  625. package/dist/senses/bluebubbles-entry.js +0 -13
  626. package/dist/senses/bluebubbles.js +0 -1181
  627. package/dist/senses/debug-activity.js +0 -154
  628. package/dist/senses/inner-dialog-worker.js +0 -90
  629. package/dist/senses/inner-dialog.js +0 -525
  630. package/subagents/README.md +0 -7
  631. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  632. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  633. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  634. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  635. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  636. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  637. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  638. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  639. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  640. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  641. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  642. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  643. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  644. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  645. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  646. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  647. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,793 @@
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.telegramApprovalCommitBarrierHooks = telegramApprovalCommitBarrierHooks;
37
+ exports.telegramApprovalDecisionBarrierHooks = telegramApprovalDecisionBarrierHooks;
38
+ exports.approvalContinuationRunAgentOptions = approvalContinuationRunAgentOptions;
39
+ exports.formatTelegramApprovalPrompt = formatTelegramApprovalPrompt;
40
+ exports.executeApprovedTelegramTool = executeApprovedTelegramTool;
41
+ exports.createTelegramApprovalRuntime = createTelegramApprovalRuntime;
42
+ const path = __importStar(require("node:path"));
43
+ const node_crypto_1 = require("node:crypto");
44
+ const friends_1 = require("@ouro.bot/friends");
45
+ const approval_files_1 = require("../heart/approval-files");
46
+ const approval_store_1 = require("../heart/approval-store");
47
+ const tool_approval_1 = require("../heart/tool-approval");
48
+ const core_1 = require("../heart/core");
49
+ const identity_1 = require("../heart/identity");
50
+ const session_events_1 = require("../heart/session-events");
51
+ const sanctuary_acceptance_marker_1 = require("../heart/daemon/sanctuary-acceptance-marker");
52
+ const telegram_1 = require("./telegram");
53
+ const context_1 = require("../mind/context");
54
+ const session_transaction_1 = require("../mind/session-transaction");
55
+ const relationship_authorization_1 = require("../repertoire/relationship-authorization");
56
+ const tools_1 = require("../repertoire/tools");
57
+ const mcp_manager_1 = require("../repertoire/mcp-manager");
58
+ const runtime_1 = require("../nerves/runtime");
59
+ const shared_turn_1 = require("./shared-turn");
60
+ const telegram_client_1 = require("./telegram-client");
61
+ function telegramApprovalCommitBarrierHooks(effectBarrier) {
62
+ return {
63
+ afterJournalPrepare: effectBarrier,
64
+ afterTokenPersist: effectBarrier,
65
+ afterCheckpointWrite: effectBarrier,
66
+ };
67
+ }
68
+ function telegramApprovalDecisionBarrierHooks(effectBarrier) {
69
+ return {
70
+ afterClaim: effectBarrier,
71
+ afterAttempt: effectBarrier,
72
+ afterHandler: effectBarrier,
73
+ };
74
+ }
75
+ function approvalContinuationRunAgentOptions(toolContext, approvalCoordinator) {
76
+ return { toolContext: toolContext, approvalCoordinator };
77
+ }
78
+ function formatTelegramApprovalPrompt(toolName, args) {
79
+ if (toolName === "sanctuary_resume_download_queue")
80
+ return "Resume household downloads? This can spend prepaid download credit. I’ll verify the queue actually resumed.";
81
+ const container = args.container;
82
+ if (toolName === "unraid_restart_container" && typeof container === "string" && container.length > 0 && container.length <= 128 && !container.includes("\n"))
83
+ return `Restart ${container}?`;
84
+ return `Approve ${toolName} with exact arguments ${JSON.stringify(args)}?`;
85
+ }
86
+ async function executeApprovedTelegramTool(name, args, execute, scenarioHandleDigest, approvalId, effectBarrier = () => undefined) {
87
+ if (name === "unraid_restart_container")
88
+ (0, runtime_1.emitNervesEvent)({
89
+ component: "senses",
90
+ event: "senses.telegram_approved_restart_start",
91
+ message: "approved Sanctuary restart execution started",
92
+ meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}) },
93
+ });
94
+ try {
95
+ effectBarrier();
96
+ const outcome = await execute(name, args);
97
+ if (outcome.kind !== "handler_succeeded") {
98
+ if (name === "unraid_restart_container")
99
+ (0, runtime_1.emitNervesEvent)({
100
+ level: "error", component: "senses", event: "senses.telegram_approved_restart_error",
101
+ message: "approved Sanctuary restart did not complete",
102
+ meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}), outcome: outcome.kind },
103
+ });
104
+ return outcome;
105
+ }
106
+ const result = outcome.text;
107
+ if (name === "sanctuary_resume_download_queue") {
108
+ let parsed;
109
+ try {
110
+ parsed = JSON.parse(result);
111
+ }
112
+ catch {
113
+ throw new tool_approval_1.ApprovalExecutionFailedError("approved download resume returned an invalid result");
114
+ }
115
+ const data = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
116
+ const verification = data?.data && typeof data.data === "object" && !Array.isArray(data.data) ? data.data : null;
117
+ const after = verification?.after && typeof verification.after === "object" && !Array.isArray(verification.after) ? verification.after : null;
118
+ if (data?.ok !== true || verification?.verified !== true || after?.paused !== false)
119
+ throw new tool_approval_1.ApprovalExecutionFailedError("approved download resume was not independently verified");
120
+ return outcome;
121
+ }
122
+ if (name !== "unraid_restart_container")
123
+ return outcome;
124
+ let parsed;
125
+ try {
126
+ parsed = JSON.parse(result);
127
+ }
128
+ catch {
129
+ throw new tool_approval_1.ApprovalExecutionFailedError("approved restart returned an invalid result");
130
+ }
131
+ if (!parsed || typeof parsed !== "object" || !("ok" in parsed)) {
132
+ throw new tool_approval_1.ApprovalExecutionFailedError("approved restart returned an invalid result");
133
+ }
134
+ if (parsed.ok !== true) {
135
+ const error = parsed.error;
136
+ const message = error && typeof error === "object" && typeof error.message === "string"
137
+ ? error.message.slice(0, 240)
138
+ : "approved restart failed";
139
+ throw new tool_approval_1.ApprovalExecutionFailedError(message);
140
+ }
141
+ const data = parsed.data;
142
+ const container = data && typeof data === "object" ? data.container : null;
143
+ const validSuccess = data !== null
144
+ && typeof data === "object"
145
+ && container !== null
146
+ && typeof container === "object"
147
+ && typeof container.id === "string"
148
+ && container.id.length > 0
149
+ && typeof container.name === "string"
150
+ && container.name.length > 0
151
+ && typeof data.beforeState === "string"
152
+ && typeof data.afterState === "string"
153
+ && data.observedRestart === true
154
+ && data.degraded === false;
155
+ if (!validSuccess) {
156
+ throw new tool_approval_1.ApprovalExecutionFailedError("approved restart returned an invalid result");
157
+ }
158
+ (0, runtime_1.emitNervesEvent)({
159
+ component: "senses",
160
+ event: "senses.telegram_approved_restart_end",
161
+ message: "approved Sanctuary restart execution completed",
162
+ meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}), observedRestart: true },
163
+ });
164
+ return outcome;
165
+ }
166
+ catch (error) {
167
+ if (name === "unraid_restart_container")
168
+ (0, runtime_1.emitNervesEvent)({
169
+ level: "error",
170
+ component: "senses",
171
+ event: "senses.telegram_approved_restart_error",
172
+ message: "approved Sanctuary restart execution failed",
173
+ meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), ...(approvalId ? { approvalId } : {}), reason: error instanceof Error ? error.message.slice(0, 240) : "unknown" },
174
+ });
175
+ throw error;
176
+ }
177
+ }
178
+ function opaqueTelegramMessageBinding(subject, messageId) {
179
+ return `tgm_${(0, node_crypto_1.createHmac)("sha256", subject).update(`message:${messageId}`, "utf8").digest("base64url")}`;
180
+ }
181
+ function createTelegramApprovalRuntime(options) {
182
+ const effectBarrier = options.effectBarrier ?? (() => undefined);
183
+ (0, runtime_1.emitNervesEvent)({
184
+ component: "senses",
185
+ event: "senses.telegram_approval_runtime_create",
186
+ message: "creating durable Telegram approval runtime",
187
+ meta: { agentName: options.agentName },
188
+ });
189
+ const now = options.dependencies?.now ?? Date.now;
190
+ const acceptanceMarker = options.dependencies?.acceptanceMarker ?? (() => (0, sanctuary_acceptance_marker_1.readSanctuaryAcceptanceMarker)(options.agentName));
191
+ const provider = options.dependencies?.runProvider ?? core_1.runAgent;
192
+ const resolveTool = options.dependencies?.resolveTool ?? tools_1.resolveToolDefinition;
193
+ const agentRoot = options.dependencies?.agentRoot ?? (0, identity_1.getAgentRoot)(options.agentName);
194
+ const owner = Object.freeze({ agentName: options.agentName, agentRoot });
195
+ const currentOptions = async (record, phase) => {
196
+ try {
197
+ if (!options.resolveLiveToolContext)
198
+ throw new Error("current owner authority producer is unavailable");
199
+ let context = await options.resolveLiveToolContext(record);
200
+ const relationship = context.relationshipAuthorization;
201
+ if (context.agentName !== owner.agentName || context.agentRoot !== owner.agentRoot
202
+ || relationship?.profileId !== "sanctuary-owner" || relationship.actor?.trustLevel !== "family"
203
+ || context.context?.friend.trustLevel !== "family" || context.context.friend.id !== relationship.actor.friendId
204
+ || context.currentSession?.friendId !== relationship.actor.friendId
205
+ || context.currentSession.key !== record.sessionKey || context.currentSession.sessionPath !== record.sessionPath) {
206
+ throw new Error("current approval owner coordinates are not exact");
207
+ }
208
+ if (record.toolName === "unraid_restart_container") {
209
+ const restartOwner = await resolveRestartOwnerContext(record, context);
210
+ if (restartOwner.allowed) {
211
+ context = restartOwner.context;
212
+ }
213
+ else {
214
+ const { reason } = restartOwner;
215
+ (0, runtime_1.emitNervesEvent)({
216
+ level: "warn", component: "senses", event: "senses.telegram_approval_owner_denied",
217
+ message: "restart approval owner revalidation failed",
218
+ meta: { approvalId: record.approvalId, reason, phase },
219
+ });
220
+ if (phase === "decision")
221
+ return null;
222
+ context = {
223
+ ...context,
224
+ relationshipAuthorization: { authorizedContextScopes: [], advertisedToolNames: [], authorizeTool: () => ({ allowed: false, reason }) },
225
+ };
226
+ }
227
+ }
228
+ const runtime = await (options.dependencies?.getProviderRuntime ?? core_1.getProviderRuntime)("human", owner);
229
+ const mcpManager = await (options.dependencies?.getSharedMcpManager ?? mcp_manager_1.getSharedMcpManager)(owner) ?? undefined;
230
+ const selectCurrentTools = () => (0, tools_1.selectToolsForChannel)((0, friends_1.getChannelCapabilities)("telegram"), context.context?.friend.toolPreferences, context.context, runtime.capabilities, mcpManager, runtime.model, context);
231
+ return {
232
+ providerRuntimeOverride: runtime, mcpManager,
233
+ toolContext: { ...context, toolSelection: selectCurrentTools(), selectCurrentTools },
234
+ };
235
+ }
236
+ catch (error) {
237
+ (0, runtime_1.emitNervesEvent)({
238
+ level: "warn", component: "senses", event: "senses.telegram_approval_authority_unavailable",
239
+ message: "current approval authority could not be reconstructed; execution remains disabled",
240
+ meta: { approvalId: record.approvalId, category: error instanceof Error ? error.name : "unknown" },
241
+ });
242
+ return null;
243
+ }
244
+ };
245
+ const invocationContext = (current, definition, restartApproval) => ({
246
+ ...current.toolContext,
247
+ toolSelection: Object.freeze({ ordinary: Object.freeze([definition]), engine: Object.freeze([]) }),
248
+ ...(restartApproval ? { restartApproval } : {}),
249
+ });
250
+ const stateRoot = path.join(agentRoot, "state", "approvals");
251
+ const store = (0, approval_store_1.openApprovalStore)({ databasePath: path.join(stateRoot, "approvals.sqlite"), now: () => new Date(now()) });
252
+ const checkpoints = new approval_files_1.FileApprovalCheckpointStore(path.join(stateRoot, "checkpoints.json"));
253
+ const tokens = new approval_files_1.FileApprovalTokenStore(path.join(stateRoot, "tokens.json"));
254
+ const pendingStore = new telegram_client_1.FileTelegramPendingApprovalStore(path.join(stateRoot, "telegram-pending.json"));
255
+ let transport;
256
+ const ownerSessionMatches = (binding, sessionPath) => {
257
+ if (binding.sessionKey !== `telegram:${options.subject}`
258
+ || sessionPath !== (0, shared_turn_1.getSenseSessionPath)(options.agentName, binding.friendId, "telegram", binding.sessionKey, agentRoot))
259
+ return false;
260
+ const envelope = (0, session_events_1.loadSessionEnvelopeFile)(sessionPath);
261
+ const latestUser = envelope && (0, session_events_1.selectEffectiveSessionEvents)(envelope.events).findLast((event) => event.role === "user");
262
+ return latestUser?.id === binding.sessionEventId && latestUser.relations.references.includes(binding.requestId);
263
+ };
264
+ const resolveRestartOwnerContext = async (record, currentContext) => {
265
+ const resolve = options.resolveOwnerRelationship;
266
+ const binding = record.ownerBinding && Object.freeze({ ...record.ownerBinding });
267
+ if (!binding || !resolve || (options.toolContext.agentRoot ?? agentRoot) !== agentRoot || record.sessionKey !== binding.sessionKey) {
268
+ return { allowed: false, reason: "restart approval owner binding is unavailable" };
269
+ }
270
+ try {
271
+ if (!ownerSessionMatches(binding, record.sessionPath))
272
+ return { allowed: false, reason: "restart approval owner session changed" };
273
+ const relationship = await resolve(binding);
274
+ const context = {
275
+ ...currentContext,
276
+ relationshipAuthorization: {
277
+ ...relationship,
278
+ requestId: binding.requestId,
279
+ authorizeTool: async (name, args) => {
280
+ const current = await resolve(binding);
281
+ if (!ownerSessionMatches(binding, record.sessionPath))
282
+ return { allowed: false, reason: "restart approval owner session changed" };
283
+ return current.authorizeTool(name, args);
284
+ },
285
+ },
286
+ };
287
+ const authorization = await (0, relationship_authorization_1.authorizeRestartApprovalRequester)(context, record.arguments, binding);
288
+ return authorization.allowed ? { allowed: true, context } : authorization;
289
+ }
290
+ catch {
291
+ return { allowed: false, reason: "restart approval owner authorization is unavailable" };
292
+ }
293
+ };
294
+ const commitAcceptanceEvidence = options.dependencies?.commitAcceptanceEvidence ?? (async (event, meta) => {
295
+ if (event === "telegram.callback_settled") {
296
+ await (0, runtime_1.emitNervesEventDurable)({
297
+ component: "senses",
298
+ event: "telegram.callback_settled",
299
+ message: "Telegram approval acceptance evidence durably recorded",
300
+ meta,
301
+ });
302
+ }
303
+ else if (event === "telegram.callback_recovery_settled") {
304
+ await (0, runtime_1.emitNervesEventDurable)({
305
+ component: "senses",
306
+ event: "telegram.callback_recovery_settled",
307
+ message: "Telegram approval acceptance evidence durably recorded",
308
+ meta,
309
+ });
310
+ }
311
+ else {
312
+ throw new Error("Telegram durable acceptance settlement event is unsupported");
313
+ }
314
+ });
315
+ const coordinator = (context) => ({
316
+ propose: async (request) => {
317
+ if (request.toolCall.type !== "function")
318
+ throw new Error("approval requires a function tool call");
319
+ effectBarrier();
320
+ let ownerBinding;
321
+ if (request.toolCall.function.name === "unraid_restart_container") {
322
+ const live = request.liveToolContext;
323
+ const authorization = await (0, relationship_authorization_1.authorizeRoutineActionRequester)(live, request.arguments);
324
+ if (!authorization.allowed || authorization.requester.kind !== "owner"
325
+ || live?.agentRoot !== agentRoot || live.currentSession?.sessionPath !== context.sessionPath) {
326
+ throw new Error("restart approval requires a current owner request");
327
+ }
328
+ const requester = authorization.requester;
329
+ ownerBinding = {
330
+ friendId: requester.friendId, requestId: requester.requestId, sessionEventId: requester.sessionEventId,
331
+ sessionKey: requester.origin.key, profileVersion: authorization.profileVersion,
332
+ };
333
+ if (!ownerSessionMatches(ownerBinding, context.sessionPath))
334
+ throw new Error("restart approval owner session changed");
335
+ const policy = await (0, tools_1.approvalPolicyForInvocation)("unraid_restart_container", request.arguments, live);
336
+ if (policy.kind !== "required")
337
+ throw new Error("restart approval no longer has owner fallback");
338
+ }
339
+ const scenarioHandleDigest = acceptanceMarker()?.scenarioHandleDigest;
340
+ const committed = (0, tool_approval_1.commitApprovalProposal)({
341
+ approvalStore: store,
342
+ checkpointStore: checkpoints,
343
+ tokenStore: tokens,
344
+ proposal: {
345
+ toolCallId: request.toolCall.id,
346
+ toolName: request.toolCall.function.name,
347
+ arguments: request.arguments,
348
+ schemaDigest: request.schemaDigest,
349
+ toolDigest: request.toolDigest,
350
+ policyDigest: request.policyDigest,
351
+ policyId: request.policyId,
352
+ sessionKey: `telegram:${options.subject}`,
353
+ sessionPath: context.sessionPath,
354
+ baseSessionRevision: context.baseSessionRevision,
355
+ checkpointDigest: "0".repeat(64),
356
+ requesterId: options.subject,
357
+ transport: "telegram",
358
+ transportUserId: options.subject,
359
+ transportChatId: options.subject,
360
+ expiresAt: new Date(now() + 300_000).toISOString(),
361
+ frozenAssistantMessage: request.frozenAssistantMessage,
362
+ ...(ownerBinding ? { ownerBinding } : {}),
363
+ ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}),
364
+ },
365
+ preCallMessages: request.preCallMessages,
366
+ hooks: telegramApprovalCommitBarrierHooks(effectBarrier),
367
+ });
368
+ const prompt = formatTelegramApprovalPrompt(request.toolCall.function.name, request.arguments);
369
+ effectBarrier();
370
+ const actionDigest = (0, node_crypto_1.createHash)("sha256").update(JSON.stringify({ toolName: committed.record.toolName, argumentDigest: committed.record.argumentDigest })).digest("hex");
371
+ const targetDigest = (0, node_crypto_1.createHash)("sha256").update(JSON.stringify({ container: committed.record.arguments.container })).digest("hex");
372
+ const sent = await transport.sendApproval({
373
+ approvalId: committed.record.approvalId,
374
+ decisionToken: committed.decisionToken,
375
+ prompt,
376
+ ...(scenarioHandleDigest ? { acceptanceBinding: {
377
+ scenarioHandleDigest,
378
+ actionDigest,
379
+ targetDigest,
380
+ checkpointDigest: committed.record.checkpointDigest,
381
+ suspendedSessionRevisionDigest: (0, node_crypto_1.createHash)("sha256").update(committed.record.suspendedSessionRevision, "utf8").digest("hex"),
382
+ } } : {}),
383
+ });
384
+ effectBarrier();
385
+ store.bindPrompt({
386
+ approvalId: committed.record.approvalId,
387
+ transport: "telegram",
388
+ transportChatId: options.subject,
389
+ transportMessageId: opaqueTelegramMessageBinding(options.subject, sent.messageId),
390
+ expiresAt: new Date(sent.expiresAt).toISOString(),
391
+ });
392
+ (0, runtime_1.emitNervesEvent)({
393
+ component: "senses",
394
+ event: "senses.telegram_approval_proposed",
395
+ message: "Telegram approval proposal was durably bound",
396
+ meta: { ...(scenarioHandleDigest ? { scenarioHandleDigest } : {}), toolName: request.toolCall.function.name },
397
+ });
398
+ return {
399
+ approvalId: committed.record.approvalId,
400
+ checkpointDigest: committed.record.checkpointDigest,
401
+ suspendedSessionRevision: committed.record.suspendedSessionRevision,
402
+ };
403
+ },
404
+ });
405
+ const terminalOutcome = (record) => {
406
+ const accepted = record.state === "succeeded";
407
+ return {
408
+ accepted,
409
+ terminalText: accepted
410
+ ? "✅ Approved — action completed"
411
+ : record.state === "denied"
412
+ ? "❌ Denied — no action taken"
413
+ : record.state === "attempted_indeterminate"
414
+ ? "⚠️ Action outcome is indeterminate after restart — it was not retried"
415
+ : "⚠️ Approval did not complete",
416
+ };
417
+ };
418
+ const continueTerminalRecord = (record, acceptanceBinding) => {
419
+ return (0, session_transaction_1.withSessionTurnLease)(record.sessionPath, async (lease) => {
420
+ const checkpoint = checkpoints.read(record.approvalId);
421
+ if (!checkpoint)
422
+ return { accepted: false, terminalText: "⚠️ Approval checkpoint is unavailable" };
423
+ const continuationOwnerId = `telegram-continuation-${(0, node_crypto_1.randomUUID)()}`;
424
+ let continuationEpoch = 0;
425
+ let continuationCausalEventId;
426
+ let continuationAuthorized = false;
427
+ let controlNotice;
428
+ const continuationCoordinator = {
429
+ propose: (request) => coordinator({
430
+ sessionPath: record.sessionPath,
431
+ baseSessionRevision: (0, session_transaction_1.readSessionTransaction)(record.sessionPath, lease).revision,
432
+ }).propose(request),
433
+ };
434
+ effectBarrier();
435
+ await (0, core_1.resumeApprovalContinuation)({
436
+ record,
437
+ checkpoint,
438
+ currentSessionRevision: (0, session_transaction_1.readSessionTransaction)(record.sessionPath, lease).revision,
439
+ sessionMessages: checkpoint.preCallMessages,
440
+ callbacks: {},
441
+ channel: "telegram",
442
+ claimContinuation: () => {
443
+ effectBarrier();
444
+ const claim = store.claimContinuation({ approvalId: record.approvalId, ownerId: continuationOwnerId });
445
+ continuationEpoch = claim.record.continuationEpoch;
446
+ return claim;
447
+ },
448
+ markContinuationMaterialized: () => { effectBarrier(); store.markContinuationMaterialized({ approvalId: record.approvalId, ownerId: continuationOwnerId, epoch: continuationEpoch }); },
449
+ markContinuationAttempted: () => { effectBarrier(); store.markContinuationAttempted({ approvalId: record.approvalId, ownerId: continuationOwnerId, epoch: continuationEpoch }); },
450
+ completeContinuation: () => { effectBarrier(); store.completeContinuation({ approvalId: record.approvalId, ownerId: continuationOwnerId, epoch: continuationEpoch }); },
451
+ runAgent: provider,
452
+ revalidate: async () => {
453
+ const current = await currentOptions(record, "continuation");
454
+ continuationAuthorized = current !== null;
455
+ return current ? { ...current, ...approvalContinuationRunAgentOptions(current.toolContext, continuationCoordinator) } : null;
456
+ },
457
+ persist: (messages, result) => {
458
+ effectBarrier();
459
+ const existingEventIds = new Set((0, session_events_1.loadSessionEnvelopeFile)(record.sessionPath)?.events.map((event) => event.id) ?? []);
460
+ const events = (0, context_1.saveSession)(record.sessionPath, messages, result?.usage, undefined, lease);
461
+ continuationCausalEventId = result
462
+ ? [...events].reverse().find((event) => event.role === "assistant" && !existingEventIds.has(event.id))?.id
463
+ : undefined;
464
+ },
465
+ deliver: async (text) => {
466
+ effectBarrier();
467
+ if (!continuationAuthorized) {
468
+ controlNotice = text;
469
+ (0, runtime_1.emitNervesEvent)({
470
+ component: "senses", event: "senses.telegram_approval_control_only",
471
+ message: "approval result will use its existing terminal control instead of an unauthorized Butler message",
472
+ meta: { approvalId: record.approvalId, state: record.state },
473
+ });
474
+ return;
475
+ }
476
+ const messageIds = await options.effects.sendText({ idempotencyKey: `approval:${record.approvalId}:continuation:${(0, node_crypto_1.createHash)("sha256").update(text).digest("hex")}`, chatId: options.authorizedChatId, text, authorClass: "butler", ...(continuationCausalEventId ? { causalEventId: continuationCausalEventId } : {}) });
477
+ effectBarrier();
478
+ if (acceptanceBinding) {
479
+ const unsigned = {
480
+ approvalId: record.approvalId,
481
+ ...acceptanceBinding,
482
+ deliveredAt: now(),
483
+ resultDigest: (0, node_crypto_1.createHash)("sha256").update(JSON.stringify({ state: record.state, result: record.result })).digest("hex"),
484
+ deliveryDigest: (0, node_crypto_1.createHash)("sha256").update(text, "utf8").digest("hex"),
485
+ deliveryMessageIdDigest: (0, node_crypto_1.createHash)("sha256").update(JSON.stringify(messageIds ?? [])).digest("hex"),
486
+ };
487
+ (0, runtime_1.emitNervesEvent)({
488
+ component: "senses",
489
+ event: "senses.telegram_approval_continuation_delivered",
490
+ message: "Telegram approval continuation result was delivered",
491
+ meta: { ...unsigned, evidenceMac: (0, telegram_1.sanctuaryTelegramApprovalEvidenceMac)(options.identityKey, "senses.telegram_approval_continuation_delivered", unsigned) },
492
+ });
493
+ }
494
+ },
495
+ });
496
+ return { ...terminalOutcome(record), ...(controlNotice ? { terminalText: controlNotice } : {}) };
497
+ });
498
+ };
499
+ transport = (0, telegram_client_1.createTelegramApprovalTransport)({
500
+ api: options.api,
501
+ effects: options.effects,
502
+ expectedUserId: options.authorizedUserId,
503
+ expectedChatId: options.authorizedChatId,
504
+ pendingStore,
505
+ createOpaqueHandle: () => (0, node_crypto_1.randomBytes)(12).toString("base64url"),
506
+ acceptanceEventMeta: () => {
507
+ const scenarioHandleDigest = acceptanceMarker()?.scenarioHandleDigest;
508
+ const meta = scenarioHandleDigest ? { scenarioHandleDigest } : {};
509
+ return meta;
510
+ },
511
+ effectBarrier,
512
+ signAcceptanceEvidence: (event, meta) => (0, telegram_1.sanctuaryTelegramApprovalEvidenceMac)(options.identityKey, event, meta),
513
+ commitAcceptanceEvidence,
514
+ onSettlementComplete: async (approvalId) => { tokens.remove(approvalId); },
515
+ acceptanceMessageIdDigest: (messageId) => (0, node_crypto_1.createHash)("sha256").update(opaqueTelegramMessageBinding(options.subject, messageId), "utf8").digest("hex"),
516
+ now,
517
+ resolveDecisionToken: async (approvalId) => tokens.get(approvalId) ?? "",
518
+ onExpire: async (approvalId) => {
519
+ effectBarrier();
520
+ store.expire({ approvalId });
521
+ effectBarrier();
522
+ tokens.remove(approvalId);
523
+ },
524
+ onDecision: async (decision) => {
525
+ effectBarrier();
526
+ const decisionScenarioDigest = acceptanceMarker()?.scenarioHandleDigest;
527
+ const existing = store.read(decision.approvalId);
528
+ if (!existing)
529
+ return { accepted: false, terminalText: "⚠️ Approval is no longer valid" };
530
+ let record;
531
+ if (existing.state === "claimed") {
532
+ effectBarrier();
533
+ record = (0, tool_approval_1.recoverClaimedApproval)({ approvalStore: store, approvalId: existing.approvalId, reason: "decision interrupted before action attempt; action was not executed" });
534
+ }
535
+ else if (existing.state === "attempted") {
536
+ effectBarrier();
537
+ record = (0, tool_approval_1.recoverAttemptedApproval)({ approvalStore: store, approvalId: existing.approvalId });
538
+ }
539
+ else if (existing.state === "proposed") {
540
+ const ownerId = `telegram-decision-${(0, node_crypto_1.randomUUID)()}`;
541
+ let restartApproval;
542
+ let definition;
543
+ record = await (0, session_transaction_1.withSessionTurnLease)(existing.sessionPath, async (lease) => (0, tool_approval_1.executeApprovalDecision)({
544
+ approvalStore: store,
545
+ checkpointStore: checkpoints,
546
+ decision: {
547
+ ...decision,
548
+ requesterId: options.subject,
549
+ transportUserId: options.subject,
550
+ transportChatId: options.subject,
551
+ transportMessageId: opaqueTelegramMessageBinding(options.subject, decision.transportMessageId),
552
+ sessionKey: existing.sessionKey,
553
+ },
554
+ ownerId,
555
+ currentSessionRevision: () => (0, session_transaction_1.readSessionTransaction)(existing.sessionPath, lease).revision,
556
+ resolveTool: async (name) => {
557
+ const current = await currentOptions(existing, "decision");
558
+ definition = current ? resolveTool(name, current.toolContext.toolSelection) : undefined;
559
+ return definition;
560
+ },
561
+ resolveApprovalPolicy: async (name, args) => {
562
+ const current = await currentOptions(existing, "decision");
563
+ return current ? (0, tools_1.approvalPolicyForInvocation)(name, args, current.toolContext) : { kind: "not_required" };
564
+ },
565
+ liveGuard: async (context) => {
566
+ if (existing.toolName !== "unraid_restart_container")
567
+ return { ok: true };
568
+ const current = await currentOptions(existing, "decision");
569
+ if (!current || !existing.ownerBinding)
570
+ return { ok: false, reason: "restart approval owner binding is unavailable" };
571
+ const restartToolContext = current.toolContext;
572
+ const authorization = await (0, relationship_authorization_1.authorizeRestartApprovalRequester)(restartToolContext, context.arguments, existing.ownerBinding);
573
+ if (!authorization.allowed)
574
+ return { ok: false, reason: authorization.reason };
575
+ try {
576
+ const listed = await restartToolContext.sanctuary?.listContainers();
577
+ if (!listed || typeof listed !== "object" || !("ok" in listed) || listed.ok !== true
578
+ || !("data" in listed) || !listed.data || typeof listed.data !== "object"
579
+ || !("truncated" in listed.data) || listed.data.truncated !== false
580
+ || !("containers" in listed.data) || !Array.isArray(listed.data.containers)) {
581
+ return { ok: false, reason: "restart approval inventory is invalid" };
582
+ }
583
+ const matches = listed.data.containers.filter((target) => target?.name === context.arguments.container);
584
+ const target = matches[0];
585
+ if (matches.length !== 1 || typeof target?.id !== "string" || !target.id.trim() || target.id !== target.id.trim() || target.degraded !== false) {
586
+ return { ok: false, reason: "restart approval target is not exact" };
587
+ }
588
+ restartApproval = Object.freeze({
589
+ approvalId: existing.approvalId, agentRoot, sessionPath: existing.sessionPath,
590
+ ownerBinding: Object.freeze({ ...existing.ownerBinding }),
591
+ argumentDigest: existing.argumentDigest,
592
+ target: Object.freeze({ id: target.id, name: String(context.arguments.container) }),
593
+ });
594
+ return { ok: true };
595
+ }
596
+ catch {
597
+ return { ok: false, reason: "restart approval target is unavailable" };
598
+ }
599
+ },
600
+ liveRisk: async () => ({ ok: true }),
601
+ preflight: async (context) => {
602
+ const current = await currentOptions(existing, "decision");
603
+ if (!current)
604
+ return { ok: false, reason: "current tool authority is unavailable" };
605
+ const result = await (0, tools_1.preflightToolCall)(context.record.toolName, context.arguments, invocationContext(current, context.definition, restartApproval));
606
+ return result.kind === "ready" ? { ok: true } : { ok: false, reason: result.text };
607
+ },
608
+ hooks: telegramApprovalDecisionBarrierHooks(effectBarrier),
609
+ execute: async (name, args) => {
610
+ if (name === "unraid_restart_container" && !restartApproval)
611
+ return { kind: "rejected_before_handler", text: "restart approval was not revalidated" };
612
+ const current = await currentOptions(existing, "decision");
613
+ if (!current || !definition)
614
+ return { kind: "rejected_before_handler", text: "current approved tool authority is unavailable" };
615
+ const approvedToolContext = invocationContext(current, definition, restartApproval);
616
+ const execute = () => executeApprovedTelegramTool(name, args, (toolName, toolArgs) => (0, tools_1.executeTool)(toolName, toolArgs, approvedToolContext, options.dependencies?.executeTool), decisionScenarioDigest, existing.approvalId, effectBarrier);
617
+ return decisionScenarioDigest
618
+ ? (0, sanctuary_acceptance_marker_1.runWithSanctuaryAcceptanceApproval)({ approvalId: existing.approvalId, argumentDigest: existing.argumentDigest }, execute)
619
+ : execute();
620
+ },
621
+ }));
622
+ }
623
+ else if (["succeeded", "failed", "attempted_indeterminate", "denied", "expired", "drifted", "session_head_changed", "abandoned_before_attempt"].includes(existing.state)) {
624
+ record = existing;
625
+ }
626
+ else {
627
+ return { accepted: false, terminalText: "⚠️ Approval is not recoverable" };
628
+ }
629
+ (0, runtime_1.emitNervesEvent)({
630
+ component: "senses",
631
+ event: "senses.telegram_approval_terminal",
632
+ message: "Telegram approval reached a terminal decision state",
633
+ meta: { state: record.state, ...(decisionScenarioDigest ? { scenarioHandleDigest: decisionScenarioDigest } : {}) },
634
+ });
635
+ return continueTerminalRecord(record, decision.acceptanceBinding);
636
+ },
637
+ });
638
+ const recover = async () => {
639
+ let failureCount = 0;
640
+ let fencedFailure;
641
+ for (const pending of transport.listPendingDeliveries()) {
642
+ let persistedState;
643
+ try {
644
+ persistedState = (0, telegram_client_1.classifyTelegramPersistedApprovalState)(pending);
645
+ }
646
+ catch (error) {
647
+ failureCount += 1;
648
+ fencedFailure ??= error;
649
+ continue;
650
+ }
651
+ const mustFailClosed = persistedState === "decision_attempt" || persistedState === "action_terminal";
652
+ try {
653
+ const existing = store.read(pending.approvalId);
654
+ if (!existing) {
655
+ if (mustFailClosed)
656
+ throw new Error("Telegram fenced approval journal is unavailable");
657
+ const orphanRecovery = await transport.terminalizeOrphaned(pending.approvalId, "⚠️ Approval record is unavailable — the action outcome is unknown and will not be retried");
658
+ (0, runtime_1.emitNervesEvent)({
659
+ component: "senses",
660
+ event: "senses.telegram_approval_orphan_recovered",
661
+ message: "orphaned Telegram approval transport state was removed",
662
+ meta: {
663
+ agentName: options.agentName,
664
+ recovery: "missing_journal",
665
+ terminalEditSucceeded: orphanRecovery.terminalEditSucceeded,
666
+ },
667
+ });
668
+ continue;
669
+ }
670
+ if (mustFailClosed) {
671
+ await transport.recoverDecisionAttempt(pending.approvalId);
672
+ continue;
673
+ }
674
+ if (persistedState === "expiry_observed") {
675
+ await transport.reconcileExpired();
676
+ continue;
677
+ }
678
+ if (persistedState === "delivery_interruption") {
679
+ await transport.terminalizeRecovered(pending.approvalId, pending.terminal.terminalText);
680
+ continue;
681
+ }
682
+ const deliveryState = pending.deliveryState ?? "bound";
683
+ if (existing.state === "awaiting_prompt_binding" && deliveryState !== "bound") {
684
+ effectBarrier();
685
+ const record = store.abandonPromptBinding({
686
+ approvalId: existing.approvalId,
687
+ reason: deliveryState === "pending"
688
+ ? "approval prompt was interrupted before delivery; action was not executed"
689
+ : "approval prompt delivery was indeterminate; action was not executed",
690
+ });
691
+ const outcome = await continueTerminalRecord(record);
692
+ await transport.terminalizeRecovered(record.approvalId, outcome.terminalText);
693
+ continue;
694
+ }
695
+ if (existing.state === "awaiting_prompt_binding" && deliveryState === "bound" && pending.messageId) {
696
+ effectBarrier();
697
+ store.bindPrompt({
698
+ approvalId: existing.approvalId,
699
+ transport: "telegram",
700
+ transportChatId: options.subject,
701
+ transportMessageId: opaqueTelegramMessageBinding(options.subject, pending.messageId),
702
+ });
703
+ continue;
704
+ }
705
+ if (existing.state === "proposed" || existing.state === "preparing" || existing.state === "awaiting_prompt_binding")
706
+ continue;
707
+ if (existing.state === "expired" && !pending.terminal) {
708
+ await transport.reconcileExpired();
709
+ continue;
710
+ }
711
+ let record = existing;
712
+ if (record.state === "claimed") {
713
+ effectBarrier();
714
+ record = (0, tool_approval_1.recoverClaimedApproval)({ approvalStore: store, approvalId: record.approvalId, reason: "decision interrupted before action attempt; action was not executed" });
715
+ }
716
+ else if (record.state === "attempted") {
717
+ effectBarrier();
718
+ record = (0, tool_approval_1.recoverAttemptedApproval)({ approvalStore: store, approvalId: record.approvalId });
719
+ }
720
+ const outcome = await continueTerminalRecord(record);
721
+ await transport.terminalizeRecovered(record.approvalId, outcome.terminalText);
722
+ }
723
+ catch (error) {
724
+ failureCount += 1;
725
+ if (mustFailClosed)
726
+ fencedFailure ??= error;
727
+ }
728
+ }
729
+ if (failureCount > 0) {
730
+ (0, runtime_1.emitNervesEvent)({
731
+ level: "error",
732
+ component: "senses",
733
+ event: "senses.telegram_approval_recovery_error",
734
+ message: "Telegram approval startup recovery completed with isolated failures",
735
+ meta: { failureCount },
736
+ });
737
+ }
738
+ if (fencedFailure !== undefined)
739
+ throw fencedFailure;
740
+ };
741
+ const legacySubjects = () => (store.listTelegramIdentitySubjects?.() ?? [])
742
+ .filter((candidate) => candidate !== options.subject);
743
+ const migrateIdentity = (subjects) => {
744
+ for (const legacySubject of subjects) {
745
+ effectBarrier();
746
+ store.migrateTelegramIdentity?.({
747
+ legacyUserId: legacySubject,
748
+ legacyChatId: legacySubject,
749
+ subject: options.subject,
750
+ });
751
+ }
752
+ effectBarrier();
753
+ store.migrateTelegramIdentity?.({
754
+ legacyUserId: options.authorizedUserId,
755
+ legacyChatId: options.authorizedChatId,
756
+ subject: options.subject,
757
+ });
758
+ };
759
+ const isPendingTerminalControl = async (input) => {
760
+ if (input.authorClass !== "control")
761
+ return false;
762
+ const effect = input.effect;
763
+ for (const pending of transport.listPendingDeliveries()) {
764
+ const record = store.read(pending.approvalId);
765
+ if (!record || !pending.messageId || record.transport !== "telegram"
766
+ || record.requesterId !== options.subject || record.transportUserId !== options.subject
767
+ || record.transportChatId !== options.subject || record.sessionKey !== `telegram:${options.subject}`
768
+ || record.transportMessageId !== opaqueTelegramMessageBinding(options.subject, pending.messageId)
769
+ || !["succeeded", "failed", "attempted_indeterminate", "denied", "expired", "drifted", "session_head_changed", "abandoned_before_attempt"].includes(record.state)
770
+ || (pending.terminal && pending.terminal.accepted !== (record.state === "succeeded")))
771
+ continue;
772
+ let matches = false;
773
+ if (effect.kind === "callback_ack") {
774
+ const digest = (0, node_crypto_1.createHash)("sha256").update(effect.callbackQueryId).digest("hex");
775
+ matches = Boolean(pending.terminal && effect.text === undefined && effect.showAlert !== true
776
+ && pending.decisionAttempt?.queryIdDigest === digest && input.idempotencyKey === `approval-callback:${digest}`);
777
+ }
778
+ else if (effect.kind === "edit") {
779
+ const terminalText = pending.terminal?.terminalText
780
+ ?? (record.state === "expired" && pending.expiryObservation?.deadlineAt === pending.expiresAt
781
+ && pending.expiryObservation.observedAt >= pending.expiresAt ? telegram_client_1.TELEGRAM_APPROVAL_EXPIRED_TEXT : undefined);
782
+ matches = terminalText !== undefined && effect.text === terminalText && effect.messageId === Number(pending.messageId)
783
+ && input.idempotencyKey === `approval:${pending.approvalId}:edit:${(0, node_crypto_1.createHash)("sha256").update(terminalText).digest("hex")}`;
784
+ }
785
+ if (!matches)
786
+ continue;
787
+ await transport.validatePendingTerminalControl(pending.approvalId);
788
+ return true;
789
+ }
790
+ return false;
791
+ };
792
+ return { transport, coordinator, legacySubjects, migrateIdentity, recover, isPendingTerminalControl, close: () => store.close() };
793
+ }