@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,186 @@
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.MAX_TELEGRAM_ATTACHMENT_BYTES = void 0;
37
+ exports.ingestTelegramAttachments = ingestTelegramAttachments;
38
+ const fs = __importStar(require("node:fs/promises"));
39
+ const path = __importStar(require("node:path"));
40
+ const node_crypto_1 = require("node:crypto");
41
+ const store_1 = require("../heart/attachments/store");
42
+ const store_2 = require("../heart/attachments/store");
43
+ const originals_1 = require("../heart/attachments/originals");
44
+ const originals_2 = require("../heart/attachments/originals");
45
+ const telegram_1 = require("../heart/attachments/sources/telegram");
46
+ const runtime_1 = require("../nerves/runtime");
47
+ exports.MAX_TELEGRAM_ATTACHMENT_BYTES = 20_000_000;
48
+ const MAX_TELEGRAM_ATTACHMENTS_PER_MESSAGE = 8;
49
+ const SAFE_FILE_PATH = /^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._/-]{1,512}$/u;
50
+ async function readBounded(response, limit) {
51
+ const advertised = Number(response.headers.get("content-length"));
52
+ if (Number.isFinite(advertised) && advertised > limit)
53
+ throw new Error("advertised size exceeds limit");
54
+ if (!response.body)
55
+ throw new Error("empty response body");
56
+ const chunks = [];
57
+ let total = 0;
58
+ const reader = response.body.getReader();
59
+ try {
60
+ for (;;) {
61
+ const { done, value } = await reader.read();
62
+ if (done)
63
+ break;
64
+ total += value.byteLength;
65
+ if (total > limit)
66
+ throw new Error("download exceeds limit");
67
+ chunks.push(value);
68
+ }
69
+ }
70
+ finally {
71
+ await reader.cancel().catch(() => undefined);
72
+ }
73
+ return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)), total);
74
+ }
75
+ async function atomicWrite(filePath, buffer) {
76
+ const directory = path.dirname(filePath);
77
+ await fs.mkdir(directory, { recursive: true, mode: 0o700 });
78
+ const temporary = `${filePath}.${(0, node_crypto_1.randomUUID)()}.tmp`;
79
+ let handle;
80
+ try {
81
+ handle = await fs.open(temporary, "wx", 0o600);
82
+ await handle.writeFile(buffer);
83
+ await handle.sync();
84
+ await handle.close();
85
+ handle = undefined;
86
+ await fs.rename(temporary, filePath);
87
+ const directoryHandle = await fs.open(directory, "r");
88
+ try {
89
+ await directoryHandle.sync();
90
+ }
91
+ finally {
92
+ await directoryHandle.close();
93
+ }
94
+ }
95
+ finally {
96
+ await handle?.close().catch(() => undefined);
97
+ await fs.unlink(temporary).catch((error) => { if (error.code !== "ENOENT")
98
+ throw error; });
99
+ }
100
+ }
101
+ async function ingestTelegramAttachments(input) {
102
+ const fetchImpl = input.fetch ?? globalThis.fetch;
103
+ const unique = [...new Map(input.attachments.map((attachment) => [attachment.fileId, attachment])).values()]
104
+ .slice(0, MAX_TELEGRAM_ATTACHMENTS_PER_MESSAGE);
105
+ const attachments = [];
106
+ const notices = [];
107
+ for (const candidate of unique) {
108
+ try {
109
+ if (!/^[A-Za-z0-9_-]{1,512}$/u.test(candidate.fileId))
110
+ throw new Error("invalid file id");
111
+ if (candidate.byteCount !== undefined && (!Number.isSafeInteger(candidate.byteCount) || candidate.byteCount < 0 || candidate.byteCount > exports.MAX_TELEGRAM_ATTACHMENT_BYTES))
112
+ throw new Error("advertised size exceeds limit");
113
+ const cached = (0, store_2.getRecentAttachment)(input.agentName, `attachment:telegram:${candidate.fileId}`, input.agentRoot);
114
+ if (cached?.source === "telegram") {
115
+ const localPath = cached.sourceData.localPath;
116
+ if (typeof localPath === "string") {
117
+ await (0, originals_2.ensureReadableFile)(localPath);
118
+ attachments.push(cached);
119
+ continue;
120
+ }
121
+ }
122
+ const recoverable = (0, telegram_1.buildTelegramAttachmentRecord)({
123
+ fileId: candidate.fileId,
124
+ displayName: candidate.displayName,
125
+ mimeType: candidate.mimeType,
126
+ byteCount: candidate.byteCount,
127
+ localPath: path.resolve(input.agentRoot, "state", "attachments", ".pending", candidate.fileId),
128
+ });
129
+ const recoverablePath = (0, originals_1.originalStoragePath)(input.agentRoot, recoverable, recoverable.mimeType);
130
+ try {
131
+ const stat = await fs.lstat(recoverablePath);
132
+ if (!stat.isFile() || stat.size > exports.MAX_TELEGRAM_ATTACHMENT_BYTES)
133
+ throw new Error("persisted attachment is invalid");
134
+ const recovered = (0, store_1.cacheRecentAttachment)(input.agentName, (0, telegram_1.buildTelegramAttachmentRecord)({
135
+ fileId: candidate.fileId,
136
+ displayName: candidate.displayName,
137
+ mimeType: candidate.mimeType,
138
+ byteCount: stat.size,
139
+ localPath: recoverablePath,
140
+ }), input.agentRoot);
141
+ attachments.push(recovered);
142
+ continue;
143
+ }
144
+ catch (error) {
145
+ if (error.code !== "ENOENT")
146
+ throw error;
147
+ }
148
+ const remote = await input.api.request("getFile", { file_id: candidate.fileId });
149
+ if (typeof remote.file_path !== "string" || !SAFE_FILE_PATH.test(remote.file_path))
150
+ throw new Error("invalid remote path");
151
+ if (remote.file_size !== undefined && (!Number.isSafeInteger(remote.file_size) || remote.file_size < 0 || remote.file_size > exports.MAX_TELEGRAM_ATTACHMENT_BYTES))
152
+ throw new Error("advertised size exceeds limit");
153
+ const response = input.downloadFile
154
+ ? await input.downloadFile(remote.file_path)
155
+ : input.botToken
156
+ ? await fetchImpl(`https://api.telegram.org/file/bot${input.botToken}/${remote.file_path}`, { signal: AbortSignal.timeout(30_000) })
157
+ : (() => { throw new Error("attachment transport is unavailable"); })();
158
+ if (!response.ok)
159
+ throw new Error(`download failed with HTTP ${response.status}`);
160
+ const buffer = await readBounded(response, exports.MAX_TELEGRAM_ATTACHMENT_BYTES);
161
+ const provisional = (0, telegram_1.buildTelegramAttachmentRecord)({
162
+ fileId: candidate.fileId,
163
+ displayName: candidate.displayName,
164
+ mimeType: candidate.mimeType ?? response.headers.get("content-type") ?? undefined,
165
+ byteCount: buffer.length,
166
+ localPath: path.resolve(input.agentRoot, "state", "attachments", ".pending", candidate.fileId),
167
+ });
168
+ const localPath = (0, originals_1.originalStoragePath)(input.agentRoot, provisional, provisional.mimeType);
169
+ await atomicWrite(localPath, buffer);
170
+ const record = (0, store_1.cacheRecentAttachment)(input.agentName, (0, telegram_1.buildTelegramAttachmentRecord)({
171
+ fileId: candidate.fileId,
172
+ displayName: candidate.displayName,
173
+ mimeType: provisional.mimeType,
174
+ byteCount: buffer.length,
175
+ localPath,
176
+ }), input.agentRoot);
177
+ attachments.push(record);
178
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.telegram_attachment_ingested", message: "Telegram attachment entered the shared attachment store", meta: { kind: record.kind, byteCount: buffer.length } });
179
+ }
180
+ catch (error) {
181
+ notices.push(`attachment unavailable: ${candidate.displayName}`);
182
+ (0, runtime_1.emitNervesEvent)({ level: "warn", component: "senses", event: "senses.telegram_attachment_ingest_error", message: "Telegram attachment ingestion failed", meta: { kind: candidate.kind, reason: error instanceof Error ? error.name : "unknown" } });
183
+ }
184
+ }
185
+ return { attachments, notices };
186
+ }
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH = exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH = void 0;
7
+ exports.verifyTelegramAuditLedger = verifyTelegramAuditLedger;
8
+ exports.createTelegramAuditLedger = createTelegramAuditLedger;
9
+ const node_crypto_1 = require("node:crypto");
10
+ const node_fs_1 = require("node:fs");
11
+ const node_path_1 = __importDefault(require("node:path"));
12
+ const redact_1 = require("../nerves/redact");
13
+ const runtime_1 = require("../nerves/runtime");
14
+ const SCHEMA = "sanctuary-telegram-audit-chain-v1";
15
+ const GENESIS_MAC = "0".repeat(64);
16
+ const SHA256 = /^[0-9a-f]{64}$/u;
17
+ const MAX_BYTES = 32 * 1024 * 1024;
18
+ const MAX_ROWS = 100_000;
19
+ const MAX_ROW_BYTES = 64 * 1024;
20
+ const LEVELS = new Set(["debug", "info", "warn", "error"]);
21
+ const ROW_KEYS = ["component", "event", "level", "message", "meta", "previousMac", "rowMac", "schemaVersion", "sequence", "trace_id", "ts"].sort();
22
+ const HEAD_KEYS = ["headMac", "lastMac", "recordCount", "schemaVersion"].sort();
23
+ exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH = node_path_1.default.join("state", "acceptance", "telegram-audit-chain.ndjson");
24
+ exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH = node_path_1.default.join("state", "acceptance", "telegram-audit-chain.head.json");
25
+ function canonicalJson(value) {
26
+ if (Array.isArray(value))
27
+ return `[${value.map(canonicalJson).join(",")}]`;
28
+ if (value && typeof value === "object") {
29
+ const record = value;
30
+ return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
31
+ }
32
+ const rendered = JSON.stringify(value);
33
+ if (rendered === undefined)
34
+ throw new Error("Telegram audit ledger contains an unsupported value");
35
+ return rendered;
36
+ }
37
+ function rowMac(identityKey, row) {
38
+ return (0, node_crypto_1.createHmac)("sha256", identityKey).update(`ouroboros.telegram.audit-row.v1\0${canonicalJson(row)}`, "utf8").digest("hex");
39
+ }
40
+ function headMac(identityKey, recordCount, lastMac) {
41
+ return (0, node_crypto_1.createHmac)("sha256", identityKey).update(`ouroboros.telegram.audit-head.v1\0${recordCount}\0${lastMac}`, "utf8").digest("hex");
42
+ }
43
+ function canonicalIso(value) {
44
+ return typeof value === "string" && value.length <= 30 && Number.isFinite(Date.parse(value)) && new Date(Date.parse(value)).toISOString() === value;
45
+ }
46
+ function object(value, label) {
47
+ if (!value || typeof value !== "object" || Array.isArray(value))
48
+ throw new Error(`${label} is invalid`);
49
+ return value;
50
+ }
51
+ function parseJson(raw, label) {
52
+ try {
53
+ return JSON.parse(raw);
54
+ }
55
+ catch (error) {
56
+ throw new Error(`${label} JSON is invalid`, { cause: error });
57
+ }
58
+ }
59
+ function containsPrivateMaterial(raw, privateValues) {
60
+ return privateValues.some((value) => value.length >= 5 && raw.includes(value))
61
+ || /\b\d{5,16}:[A-Za-z0-9_-]{20,}\b/u.test(raw)
62
+ || /"(?:authorized_?user_?id|authorized_?chat_?id|transport_?user_?id|transport_?chat_?id|user_?id|chat_?id|update_?id|message_?id)"\s*:\s*"?\d{1,20}"?/iu.test(raw);
63
+ }
64
+ function parseHead(raw, identityKey) {
65
+ if (Buffer.byteLength(raw) > 4 * 1024)
66
+ throw new Error("Telegram audit head exceeds its bound");
67
+ const value = object(parseJson(raw, "Telegram audit head"), "Telegram audit head");
68
+ if (JSON.stringify(Object.keys(value).sort()) !== JSON.stringify(HEAD_KEYS)
69
+ || value.schemaVersion !== SCHEMA
70
+ || !Number.isSafeInteger(value.recordCount) || Number(value.recordCount) < 0 || Number(value.recordCount) > MAX_ROWS
71
+ || typeof value.lastMac !== "string" || !SHA256.test(value.lastMac)
72
+ || typeof value.headMac !== "string" || !SHA256.test(value.headMac)
73
+ || value.headMac !== headMac(identityKey, Number(value.recordCount), value.lastMac))
74
+ throw new Error("Telegram audit head MAC is invalid");
75
+ return value;
76
+ }
77
+ function verifyTelegramAuditLedger(options) {
78
+ if (Buffer.byteLength(options.ledgerRaw) > MAX_BYTES)
79
+ throw new Error("Telegram audit ledger exceeds its bound");
80
+ const lines = options.ledgerRaw.split("\n").filter(Boolean);
81
+ if (lines.length > MAX_ROWS || lines.some((line) => Buffer.byteLength(line) > MAX_ROW_BYTES))
82
+ throw new Error("Telegram audit ledger exceeds its bound");
83
+ const head = parseHead(options.headRaw, options.identityKey);
84
+ let previousMac = GENESIS_MAC;
85
+ const events = lines.map((line, index) => {
86
+ if (containsPrivateMaterial(line, options.privateValues ?? []))
87
+ throw new Error("Telegram audit ledger contains private material");
88
+ const value = object(parseJson(line, "Telegram audit ledger row"), "Telegram audit ledger row");
89
+ if (JSON.stringify(Object.keys(value).sort()) !== JSON.stringify(ROW_KEYS)
90
+ || value.schemaVersion !== SCHEMA || value.sequence !== index + 1 || value.previousMac !== previousMac
91
+ || !canonicalIso(value.ts) || typeof value.level !== "string" || !LEVELS.has(value.level)
92
+ || typeof value.event !== "string" || value.event.length < 1 || value.event.length > 256
93
+ || typeof value.component !== "string" || value.component.length < 1 || value.component.length > 128
94
+ || typeof value.trace_id !== "string" || value.trace_id.length < 1 || value.trace_id.length > 256
95
+ || typeof value.message !== "string" || value.message.length > 4_096
96
+ || !value.meta || typeof value.meta !== "object" || Array.isArray(value.meta)
97
+ || typeof value.rowMac !== "string" || !SHA256.test(value.rowMac))
98
+ throw new Error("Telegram audit ledger row is invalid");
99
+ const unsigned = Object.fromEntries(Object.entries(value).filter(([key]) => key !== "rowMac"));
100
+ if (value.rowMac !== rowMac(options.identityKey, unsigned))
101
+ throw new Error("Telegram audit ledger row MAC is invalid");
102
+ previousMac = value.rowMac;
103
+ return { event: value.event, at: Date.parse(value.ts), meta: value.meta };
104
+ });
105
+ if (head.recordCount !== lines.length || head.lastMac !== previousMac)
106
+ throw new Error("Telegram audit head does not match the append-only ledger");
107
+ return events;
108
+ }
109
+ function writeHead(filePath, directory, head) {
110
+ const temporary = `${filePath}.tmp-${process.pid}-${(0, node_crypto_1.randomUUID)()}`;
111
+ (0, node_fs_1.writeFileSync)(temporary, `${JSON.stringify(head)}\n`, { flag: "wx", mode: 0o600 });
112
+ const file = (0, node_fs_1.openSync)(temporary, "r");
113
+ try {
114
+ (0, node_fs_1.fsyncSync)(file);
115
+ }
116
+ finally {
117
+ (0, node_fs_1.closeSync)(file);
118
+ }
119
+ (0, node_fs_1.renameSync)(temporary, filePath);
120
+ const directoryHandle = (0, node_fs_1.openSync)(directory, "r");
121
+ try {
122
+ (0, node_fs_1.fsyncSync)(directoryHandle);
123
+ }
124
+ finally {
125
+ (0, node_fs_1.closeSync)(directoryHandle);
126
+ }
127
+ }
128
+ function createTelegramAuditLedger(options) {
129
+ const directory = node_path_1.default.join(options.root, "state", "acceptance");
130
+ const ledgerPath = node_path_1.default.join(options.root, exports.TELEGRAM_ACCEPTANCE_AUDIT_RELATIVE_PATH);
131
+ const headPath = node_path_1.default.join(options.root, exports.TELEGRAM_ACCEPTANCE_AUDIT_HEAD_RELATIVE_PATH);
132
+ (0, node_fs_1.mkdirSync)(directory, { recursive: true, mode: 0o700 });
133
+ if ((0, node_fs_1.existsSync)(ledgerPath) !== (0, node_fs_1.existsSync)(headPath))
134
+ throw new Error("Telegram audit ledger/head presence mismatch");
135
+ if (!(0, node_fs_1.existsSync)(ledgerPath)) {
136
+ (0, node_fs_1.writeFileSync)(ledgerPath, "", { flag: "wx", mode: 0o600 });
137
+ writeHead(headPath, directory, { schemaVersion: SCHEMA, recordCount: 0, lastMac: GENESIS_MAC, headMac: headMac(options.identityKey, 0, GENESIS_MAC) });
138
+ }
139
+ let records = verifyTelegramAuditLedger({ ledgerRaw: (0, node_fs_1.readFileSync)(ledgerPath, "utf8"), headRaw: (0, node_fs_1.readFileSync)(headPath, "utf8"), identityKey: options.identityKey, privateValues: options.privateValues });
140
+ let currentHead = parseHead((0, node_fs_1.readFileSync)(headPath, "utf8"), options.identityKey);
141
+ const maxBytes = options._maxBytes ?? MAX_BYTES;
142
+ let failure;
143
+ (0, runtime_1.emitNervesEvent)({
144
+ component: "senses",
145
+ event: "senses.telegram_audit_ledger_ready",
146
+ message: "Telegram acceptance audit ledger is verified",
147
+ meta: { recordCount: currentHead.recordCount },
148
+ });
149
+ return {
150
+ ledgerPath,
151
+ headPath,
152
+ append(event) {
153
+ if (failure)
154
+ throw failure;
155
+ try {
156
+ const original = JSON.stringify(event);
157
+ if (containsPrivateMaterial(original, options.privateValues ?? []))
158
+ throw new Error("Telegram audit event contains private material");
159
+ const redacted = JSON.parse((0, redact_1.redactString)(JSON.stringify((0, redact_1.redactLogEntry)(event))));
160
+ const unsigned = {
161
+ schemaVersion: SCHEMA,
162
+ sequence: currentHead.recordCount + 1,
163
+ previousMac: currentHead.lastMac,
164
+ ts: redacted.ts,
165
+ level: redacted.level,
166
+ event: redacted.event,
167
+ component: redacted.component,
168
+ trace_id: redacted.trace_id,
169
+ message: redacted.message,
170
+ meta: redacted.meta,
171
+ };
172
+ const row = { ...unsigned, rowMac: rowMac(options.identityKey, unsigned) };
173
+ const serialized = JSON.stringify(row);
174
+ if (Buffer.byteLength(serialized) > MAX_ROW_BYTES || currentHead.recordCount >= MAX_ROWS
175
+ || Buffer.byteLength((0, node_fs_1.readFileSync)(ledgerPath)) + Buffer.byteLength(serialized) + 1 > maxBytes)
176
+ throw new Error("Telegram audit ledger exceeds its bound");
177
+ (0, node_fs_1.appendFileSync)(ledgerPath, `${serialized}\n`, { encoding: "utf8", mode: 0o600 });
178
+ const ledgerHandle = (0, node_fs_1.openSync)(ledgerPath, "r");
179
+ try {
180
+ (0, node_fs_1.fsyncSync)(ledgerHandle);
181
+ }
182
+ finally {
183
+ (0, node_fs_1.closeSync)(ledgerHandle);
184
+ }
185
+ currentHead = {
186
+ schemaVersion: SCHEMA,
187
+ recordCount: row.sequence,
188
+ lastMac: row.rowMac,
189
+ headMac: headMac(options.identityKey, row.sequence, row.rowMac),
190
+ };
191
+ writeHead(headPath, directory, currentHead);
192
+ records = [...records, { event: row.event, at: Date.parse(row.ts), meta: row.meta }];
193
+ }
194
+ catch (error) {
195
+ failure = error instanceof Error ? error : new Error(String(error));
196
+ throw failure;
197
+ }
198
+ },
199
+ poison(error) {
200
+ failure ??= error;
201
+ throw failure;
202
+ },
203
+ assertHealthy() {
204
+ if (failure)
205
+ throw failure;
206
+ records = verifyTelegramAuditLedger({ ledgerRaw: (0, node_fs_1.readFileSync)(ledgerPath, "utf8"), headRaw: (0, node_fs_1.readFileSync)(headPath, "utf8"), identityKey: options.identityKey, privateValues: options.privateValues });
207
+ currentHead = parseHead((0, node_fs_1.readFileSync)(headPath, "utf8"), options.identityKey);
208
+ },
209
+ assertCapacity(additionalRows = 1) {
210
+ if (!Number.isSafeInteger(additionalRows) || additionalRows < 1)
211
+ throw new Error("Telegram audit capacity reservation is invalid");
212
+ if (failure)
213
+ throw failure;
214
+ if (currentHead.recordCount + additionalRows > MAX_ROWS
215
+ || Buffer.byteLength((0, node_fs_1.readFileSync)(ledgerPath)) + additionalRows * (MAX_ROW_BYTES + 1) > maxBytes) {
216
+ throw new Error("Telegram audit ledger lacks reserved capacity");
217
+ }
218
+ },
219
+ };
220
+ }
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSanctuaryTelegramAuthorityTransport = createSanctuaryTelegramAuthorityTransport;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const runtime_1 = require("../nerves/runtime");
6
+ const sanctuary_authority_codec_1 = require("../heart/daemon/sanctuary-authority-codec");
7
+ const root_host_approval_port_1 = require("./root-host-approval-port");
8
+ function isObject(value) {
9
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10
+ }
11
+ function validPollBody(body) {
12
+ return Object.keys(body).sort().join(",") === "allowed_updates,offset,timeout"
13
+ && Number.isSafeInteger(body.offset)
14
+ && body.offset >= 0
15
+ && body.timeout === 50
16
+ && Array.isArray(body.allowed_updates)
17
+ && body.allowed_updates.length === 2
18
+ && body.allowed_updates[0] === "message"
19
+ && body.allowed_updates[1] === "callback_query";
20
+ }
21
+ function rawUpdateDigest(update) {
22
+ return `tgu_${(0, node_crypto_1.createHash)("sha256")
23
+ .update(`ouroboros.telegram.update.v1\0${JSON.stringify(update)}`, "utf8")
24
+ .digest("base64url")}`;
25
+ }
26
+ function exactKeys(value, keys) {
27
+ const actual = Object.keys(value).sort();
28
+ const expected = [...keys].sort();
29
+ return actual.length === expected.length && actual.every((key, index) => key === expected[index]);
30
+ }
31
+ function canonicalTime(value) {
32
+ if (typeof value !== "string")
33
+ return false;
34
+ const instant = new Date(value);
35
+ return !Number.isNaN(instant.getTime()) && instant.toISOString() === value;
36
+ }
37
+ function verifyObservation(artifact, update, verification) {
38
+ let payload;
39
+ try {
40
+ payload = (0, sanctuary_authority_codec_1.verifyAuthorityPayload)({
41
+ artifact,
42
+ expectedDomain: "ouro.sanctuary.telegram-observation.v1",
43
+ expectedKeyId: verification.expectedKeyId,
44
+ publicKey: verification.publicKey,
45
+ });
46
+ }
47
+ catch (error) {
48
+ throw new Error("Sanctuary Telegram authority poll response is invalid", { cause: error });
49
+ }
50
+ if (!isObject(payload)
51
+ || !exactKeys(payload, [
52
+ "targetHost", "botId", "updateId", "updateClass", "userId", "chatId", "ownerEligible",
53
+ "messageId", "callbackQueryId", "rawUpdateDigest", "observedAt", "settlement", "nonce", "publicKeyDigest",
54
+ ...(Object.hasOwn(payload, "deliveryUpdateDigest") ? ["deliveryUpdateDigest"] : []),
55
+ ])
56
+ || payload.targetHost !== verification.expectedTargetHost
57
+ || payload.botId !== verification.expectedBotId
58
+ || payload.publicKeyDigest !== verification.expectedPublicKeyDigest
59
+ || payload.updateId !== update.update_id
60
+ || !["message", "callback"].includes(String(payload.updateClass))
61
+ || typeof payload.userId !== "string"
62
+ || typeof payload.chatId !== "string"
63
+ || typeof payload.ownerEligible !== "boolean"
64
+ || (payload.messageId !== null && typeof payload.messageId !== "string")
65
+ || (payload.callbackQueryId !== null && typeof payload.callbackQueryId !== "string")
66
+ || typeof payload.rawUpdateDigest !== "string"
67
+ || !/^tgu_[A-Za-z0-9_-]{43}$/u.test(payload.rawUpdateDigest)
68
+ || (Object.hasOwn(payload, "deliveryUpdateDigest") && typeof payload.deliveryUpdateDigest !== "string")
69
+ || (payload.deliveryUpdateDigest ?? payload.rawUpdateDigest) !== rawUpdateDigest(update)
70
+ || !canonicalTime(payload.observedAt)
71
+ || payload.settlement !== "pending"
72
+ || typeof payload.nonce !== "string"
73
+ || !/^[A-Za-z0-9_-]{43}$/u.test(payload.nonce)) {
74
+ throw new Error("Sanctuary Telegram authority observation payload is invalid");
75
+ }
76
+ const callback = update.callback_query;
77
+ const message = update.message;
78
+ if ((!callback && !message) || (callback && message) || (callback && (!callback.message || !callback.from)) || (message && !message.from)) {
79
+ throw new Error("Sanctuary Telegram authority observation update is unsupported");
80
+ }
81
+ const updateClass = callback ? "callback" : "message";
82
+ const userId = String(callback ? callback.from.id : message.from.id);
83
+ const chatId = String(callback ? callback.message.chat.id : message.chat.id);
84
+ const messageId = String(callback ? callback.message.message_id : message.message_id);
85
+ const callbackQueryId = callback ? callback.id : null;
86
+ if (payload.updateClass !== updateClass
87
+ || payload.userId !== userId
88
+ || payload.chatId !== chatId
89
+ || payload.messageId !== messageId
90
+ || payload.callbackQueryId !== callbackQueryId
91
+ || payload.ownerEligible !== (userId === verification.expectedOwnerUserId && chatId === verification.expectedOwnerChatId)) {
92
+ throw new Error("Sanctuary Telegram authority observation coordinates changed");
93
+ }
94
+ return Object.freeze({
95
+ schemaVersion: 1,
96
+ observationDigest: (0, sanctuary_authority_codec_1.authorityArtifactDigest)(artifact.domain, payload),
97
+ targetHost: payload.targetHost,
98
+ botId: payload.botId,
99
+ updateId: payload.updateId,
100
+ updateClass: payload.updateClass,
101
+ userId: payload.userId,
102
+ chatId: payload.chatId,
103
+ ownerEligible: payload.ownerEligible,
104
+ messageId: payload.messageId,
105
+ callbackQueryId: payload.callbackQueryId,
106
+ rawUpdateDigest: payload.rawUpdateDigest,
107
+ ...(payload.deliveryUpdateDigest ? { deliveryUpdateDigest: payload.deliveryUpdateDigest } : {}),
108
+ observedAt: payload.observedAt,
109
+ keyId: artifact.keyId,
110
+ publicKeyDigest: payload.publicKeyDigest,
111
+ });
112
+ }
113
+ function createSanctuaryTelegramAuthorityTransport(client, verification) {
114
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.sanctuary_authority_transport_created", message: "Tokenless Sanctuary Telegram authority transport created" });
115
+ verification = Object.freeze({ ...verification });
116
+ const observations = new Map();
117
+ const metadata = new Map();
118
+ const callbacks = new Map();
119
+ let currentObservation = null;
120
+ let stopped = false;
121
+ const api = {
122
+ async request(method, body, signal) {
123
+ if (signal?.aborted)
124
+ throw signal.reason;
125
+ if (stopped)
126
+ throw new Error("Sanctuary Telegram authority transport is stopped");
127
+ if (method !== "getUpdates") {
128
+ return await client.request("telegram.request", {
129
+ method,
130
+ body,
131
+ ...(currentObservation ? {
132
+ observation: {
133
+ updateId: currentObservation.payload.updateId,
134
+ observationDigest: (0, sanctuary_authority_codec_1.authorityArtifactDigest)(currentObservation.domain, currentObservation.payload),
135
+ },
136
+ } : {}),
137
+ });
138
+ }
139
+ if (!validPollBody(body))
140
+ throw new Error("Sanctuary Telegram authority poll request is invalid");
141
+ const result = await client.request("telegram.poll", {});
142
+ if (result === null)
143
+ return [];
144
+ if (!isObject(result)
145
+ || !isObject(result.observation)
146
+ || !isObject(result.observation.payload)
147
+ || !isObject(result.update)
148
+ || !Number.isSafeInteger(result.update.update_id)
149
+ || result.observation.payload.updateId !== result.update.update_id) {
150
+ throw new Error("Sanctuary Telegram authority poll response is invalid");
151
+ }
152
+ const update = result.update;
153
+ const observation = result.observation;
154
+ const verifiedMetadata = verifyObservation(observation, update, verification);
155
+ const existing = observations.get(update.update_id);
156
+ if (existing
157
+ && (0, sanctuary_authority_codec_1.authorityArtifactDigest)(existing.domain, existing.payload)
158
+ !== (0, sanctuary_authority_codec_1.authorityArtifactDigest)(observation.domain, observation.payload)) {
159
+ throw new Error("Sanctuary Telegram authority observation changed during redelivery");
160
+ }
161
+ observations.set(update.update_id, observation);
162
+ metadata.set(update.update_id, verifiedMetadata);
163
+ callbacks.set(update.update_id, result.hostCallback);
164
+ currentObservation = observation;
165
+ return [update];
166
+ },
167
+ stop() {
168
+ if (stopped)
169
+ return;
170
+ stopped = true;
171
+ client.close();
172
+ },
173
+ };
174
+ const transport = {
175
+ api,
176
+ async downloadFile(filePath) {
177
+ const result = await client.request("telegram.file", { filePath });
178
+ if (!isObject(result)
179
+ || typeof result.bodyBase64 !== "string"
180
+ || (result.contentType !== undefined && typeof result.contentType !== "string")) {
181
+ throw new Error("Sanctuary Telegram authority file response is invalid");
182
+ }
183
+ const body = Buffer.from(result.bodyBase64, "base64");
184
+ if (body.toString("base64") !== result.bodyBase64 || body.length > 20_000_000) {
185
+ throw new Error("Sanctuary Telegram authority file response is invalid");
186
+ }
187
+ return new Response(body, {
188
+ headers: result.contentType ? { "content-type": result.contentType } : undefined,
189
+ });
190
+ },
191
+ async admitChat(input) {
192
+ await client.request("telegram.chat.admit", input);
193
+ },
194
+ async revokeChat(input) {
195
+ await client.request("telegram.chat.revoke", input);
196
+ },
197
+ metadataForUpdate(update) {
198
+ const value = metadata.get(update.update_id);
199
+ if (!value)
200
+ return null;
201
+ if ((value.deliveryUpdateDigest ?? value.rawUpdateDigest) !== rawUpdateDigest(update)) {
202
+ throw new Error("Sanctuary Telegram authority update changed after verification");
203
+ }
204
+ return value;
205
+ },
206
+ async settleTransport(update, outcome) {
207
+ const observation = observations.get(update.update_id);
208
+ if (!observation)
209
+ throw new Error("Sanctuary Telegram authority observation is unavailable for settlement");
210
+ await client.request("telegram.settle", {
211
+ updateId: update.update_id,
212
+ observationDigest: (0, sanctuary_authority_codec_1.authorityArtifactDigest)(observation.domain, observation.payload),
213
+ outcome,
214
+ });
215
+ observations.delete(update.update_id);
216
+ metadata.delete(update.update_id);
217
+ callbacks.delete(update.update_id);
218
+ if (currentObservation?.payload.updateId === update.update_id)
219
+ currentObservation = null;
220
+ },
221
+ };
222
+ transport.hostApproval = (0, root_host_approval_port_1.createRootHostApprovalPort)(client, verification, {
223
+ current: () => currentObservation ? metadata.get(currentObservation.payload.updateId) : null,
224
+ lookup: (update) => {
225
+ const value = transport.metadataForUpdate(update);
226
+ return value ? { metadata: value, hostCallback: callbacks.get(update.update_id) } : null;
227
+ },
228
+ stopped: () => stopped,
229
+ });
230
+ return transport;
231
+ }