@ouro.bot/cli 0.1.0-alpha.48 → 0.1.0-alpha.480

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 (358) hide show
  1. package/README.md +132 -19
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +3061 -0
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +857 -0
  16. package/dist/heart/agent-entry.js +58 -3
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +426 -0
  28. package/dist/heart/background-operations.js +234 -0
  29. package/dist/heart/bridges/manager.js +358 -0
  30. package/dist/heart/bridges/state-machine.js +135 -0
  31. package/dist/heart/bridges/store.js +123 -0
  32. package/dist/heart/bundle-state.js +168 -0
  33. package/dist/heart/commitments.js +111 -0
  34. package/dist/heart/config-registry.js +304 -0
  35. package/dist/heart/config.js +110 -128
  36. package/dist/heart/core.js +745 -227
  37. package/dist/heart/cross-chat-delivery.js +131 -0
  38. package/dist/heart/daemon/agent-config-check.js +490 -0
  39. package/dist/heart/daemon/agent-discovery.js +79 -3
  40. package/dist/heart/daemon/agent-service.js +360 -0
  41. package/dist/heart/daemon/agentic-repair.js +216 -0
  42. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  43. package/dist/heart/daemon/cadence.js +70 -0
  44. package/dist/heart/daemon/cli-defaults.js +640 -0
  45. package/dist/heart/daemon/cli-exec.js +6933 -0
  46. package/dist/heart/daemon/cli-help.js +487 -0
  47. package/dist/heart/daemon/cli-parse.js +1527 -0
  48. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  49. package/dist/heart/daemon/cli-render.js +561 -0
  50. package/dist/heart/daemon/cli-types.js +8 -0
  51. package/dist/heart/daemon/connect-bay.js +323 -0
  52. package/dist/heart/daemon/daemon-cli.js +29 -1616
  53. package/dist/heart/daemon/daemon-entry.js +345 -3
  54. package/dist/heart/daemon/daemon-health.js +141 -0
  55. package/dist/heart/daemon/daemon-runtime-sync.js +190 -12
  56. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  57. package/dist/heart/daemon/daemon.js +677 -58
  58. package/dist/heart/daemon/dns-workflow.js +394 -0
  59. package/dist/heart/daemon/doctor-types.js +8 -0
  60. package/dist/heart/daemon/doctor.js +486 -0
  61. package/dist/heart/daemon/health-monitor.js +92 -1
  62. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  63. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  64. package/dist/heart/daemon/http-health-probe.js +80 -0
  65. package/dist/heart/daemon/human-command-screens.js +234 -0
  66. package/dist/heart/daemon/human-readiness.js +114 -0
  67. package/dist/heart/daemon/inner-status.js +89 -0
  68. package/dist/heart/daemon/interactive-repair.js +394 -0
  69. package/dist/heart/daemon/launchd.js +25 -5
  70. package/dist/heart/daemon/log-tailer.js +82 -12
  71. package/dist/heart/daemon/logs-prune.js +110 -0
  72. package/dist/heart/daemon/message-router.js +2 -2
  73. package/dist/heart/daemon/os-cron-deps.js +134 -0
  74. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  75. package/dist/heart/daemon/ouro-entry.js +3 -1
  76. package/dist/heart/daemon/process-manager.js +214 -0
  77. package/dist/heart/daemon/provider-discovery.js +137 -0
  78. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  79. package/dist/heart/daemon/pulse.js +475 -0
  80. package/dist/heart/daemon/readiness-repair.js +365 -0
  81. package/dist/heart/daemon/run-hooks.js +2 -0
  82. package/dist/heart/daemon/runtime-logging.js +67 -16
  83. package/dist/heart/daemon/runtime-metadata.js +73 -0
  84. package/dist/heart/daemon/runtime-mode.js +67 -0
  85. package/dist/heart/daemon/safe-mode.js +161 -0
  86. package/dist/heart/daemon/sense-manager.js +178 -37
  87. package/dist/heart/daemon/session-id-resolver.js +131 -0
  88. package/dist/heart/daemon/skill-management-installer.js +94 -0
  89. package/dist/heart/daemon/socket-client.js +109 -4
  90. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  91. package/dist/heart/daemon/startup-tui.js +264 -0
  92. package/dist/heart/daemon/task-scheduler.js +3 -25
  93. package/dist/heart/daemon/terminal-ui.js +499 -0
  94. package/dist/heart/daemon/thoughts.js +149 -10
  95. package/dist/heart/daemon/up-progress.js +366 -0
  96. package/dist/heart/daemon/vault-items.js +56 -0
  97. package/dist/heart/delegation.js +62 -0
  98. package/dist/heart/habits/habit-migration.js +189 -0
  99. package/dist/heart/habits/habit-parser.js +140 -0
  100. package/dist/heart/habits/habit-runtime-state.js +100 -0
  101. package/dist/heart/habits/habit-scheduler.js +372 -0
  102. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  103. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  104. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  105. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  106. package/dist/heart/identity.js +201 -66
  107. package/dist/heart/kept-notes.js +357 -0
  108. package/dist/heart/kicks.js +1 -1
  109. package/dist/heart/machine-identity.js +161 -0
  110. package/dist/heart/mcp/mcp-server.js +653 -0
  111. package/dist/heart/migrate-config.js +100 -0
  112. package/dist/heart/model-capabilities.js +59 -0
  113. package/dist/heart/outlook/outlook-http-hooks.js +66 -0
  114. package/dist/heart/outlook/outlook-http-response.js +7 -0
  115. package/dist/heart/outlook/outlook-http-routes.js +244 -0
  116. package/dist/heart/outlook/outlook-http-static.js +99 -0
  117. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  118. package/dist/heart/outlook/outlook-http.js +99 -0
  119. package/dist/heart/outlook/outlook-read.js +31 -0
  120. package/dist/heart/outlook/outlook-types.js +27 -0
  121. package/dist/heart/outlook/outlook-view.js +195 -0
  122. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  123. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  124. package/dist/heart/outlook/readers/mail.js +362 -0
  125. package/dist/heart/outlook/readers/runtime-readers.js +644 -0
  126. package/dist/heart/outlook/readers/sessions.js +232 -0
  127. package/dist/heart/outlook/readers/shared.js +111 -0
  128. package/dist/heart/platform.js +81 -0
  129. package/dist/heart/progress-story.js +42 -0
  130. package/dist/heart/provider-attempt.js +134 -0
  131. package/dist/heart/provider-binding-resolver.js +255 -0
  132. package/dist/heart/provider-credentials.js +424 -0
  133. package/dist/heart/provider-failover.js +266 -0
  134. package/dist/heart/provider-models.js +81 -0
  135. package/dist/heart/provider-ping.js +262 -0
  136. package/dist/heart/provider-state.js +216 -0
  137. package/dist/heart/provider-visibility.js +188 -0
  138. package/dist/heart/providers/anthropic-token.js +131 -0
  139. package/dist/heart/providers/anthropic.js +193 -55
  140. package/dist/heart/providers/azure.js +103 -12
  141. package/dist/heart/providers/error-classification.js +63 -0
  142. package/dist/heart/providers/github-copilot.js +145 -0
  143. package/dist/heart/providers/minimax-vlm.js +189 -0
  144. package/dist/heart/providers/minimax.js +29 -7
  145. package/dist/heart/providers/openai-codex.js +62 -38
  146. package/dist/heart/runtime-capability-check.js +170 -0
  147. package/dist/heart/runtime-credentials.js +260 -0
  148. package/dist/heart/sense-truth.js +11 -4
  149. package/dist/heart/session-activity.js +190 -0
  150. package/dist/heart/session-events.js +855 -0
  151. package/dist/heart/session-transcript.js +167 -0
  152. package/dist/heart/start-of-turn-packet.js +345 -0
  153. package/dist/heart/streaming.js +36 -27
  154. package/dist/heart/sync.js +332 -0
  155. package/dist/heart/target-resolution.js +127 -0
  156. package/dist/heart/tempo.js +93 -0
  157. package/dist/heart/temporal-view.js +41 -0
  158. package/dist/heart/tool-activity-callbacks.js +36 -0
  159. package/dist/heart/tool-description.js +135 -0
  160. package/dist/heart/tool-friction.js +55 -0
  161. package/dist/heart/tool-loop.js +200 -0
  162. package/dist/heart/turn-context.js +361 -0
  163. package/dist/heart/turn-coordinator.js +24 -1
  164. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  165. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  166. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  167. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  168. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  169. package/dist/heart/{daemon → versioning}/update-checker.js +5 -1
  170. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  171. package/dist/mailroom/attention.js +167 -0
  172. package/dist/mailroom/autonomy.js +209 -0
  173. package/dist/mailroom/blob-store.js +558 -0
  174. package/dist/mailroom/core.js +658 -0
  175. package/dist/mailroom/entry.js +160 -0
  176. package/dist/mailroom/file-store.js +400 -0
  177. package/dist/mailroom/mbox-import.js +341 -0
  178. package/dist/mailroom/outbound.js +380 -0
  179. package/dist/mailroom/policy.js +263 -0
  180. package/dist/mailroom/reader.js +197 -0
  181. package/dist/mailroom/smtp-ingress.js +176 -0
  182. package/dist/mailroom/source-state.js +176 -0
  183. package/dist/mailroom/travel-extract.js +89 -0
  184. package/dist/mind/bundle-manifest.js +7 -1
  185. package/dist/mind/context.js +132 -93
  186. package/dist/mind/diary-integrity.js +60 -0
  187. package/dist/mind/{memory.js → diary.js} +74 -93
  188. package/dist/mind/embedding-provider.js +60 -0
  189. package/dist/mind/file-state.js +179 -0
  190. package/dist/mind/friends/channel.js +30 -0
  191. package/dist/mind/friends/group-context.js +144 -0
  192. package/dist/mind/friends/resolver.js +38 -1
  193. package/dist/mind/friends/store-file.js +39 -3
  194. package/dist/mind/friends/trust-explanation.js +74 -0
  195. package/dist/mind/friends/types.js +2 -2
  196. package/dist/mind/journal-index.js +161 -0
  197. package/dist/mind/note-search.js +268 -0
  198. package/dist/mind/obligation-steering.js +221 -0
  199. package/dist/mind/pending.js +66 -7
  200. package/dist/mind/prompt-refresh.js +3 -2
  201. package/dist/mind/prompt.js +978 -169
  202. package/dist/mind/provenance-trust.js +26 -0
  203. package/dist/mind/scrutiny.js +173 -0
  204. package/dist/nerves/cli-logging.js +7 -1
  205. package/dist/nerves/coverage/audit-rules.js +15 -6
  206. package/dist/nerves/coverage/audit.js +28 -2
  207. package/dist/nerves/coverage/cli.js +1 -1
  208. package/dist/nerves/coverage/contract.js +5 -5
  209. package/dist/nerves/coverage/file-completeness.js +84 -5
  210. package/dist/nerves/coverage/run-artifacts.js +1 -1
  211. package/dist/nerves/event-buffer.js +111 -0
  212. package/dist/nerves/index.js +224 -4
  213. package/dist/nerves/observation.js +20 -0
  214. package/dist/nerves/redact.js +79 -0
  215. package/dist/nerves/runtime.js +5 -1
  216. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  217. package/dist/outlook-ui/assets/index-CPfhbn13.js +61 -0
  218. package/dist/outlook-ui/index.html +15 -0
  219. package/dist/repertoire/ado-client.js +15 -56
  220. package/dist/repertoire/ado-semantic.js +11 -10
  221. package/dist/repertoire/api-client.js +97 -0
  222. package/dist/repertoire/bitwarden-store.js +774 -0
  223. package/dist/repertoire/bundle-templates.js +72 -0
  224. package/dist/repertoire/bw-installer.js +180 -0
  225. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  226. package/dist/repertoire/coding/context-pack.js +330 -0
  227. package/dist/repertoire/coding/feedback.js +197 -30
  228. package/dist/repertoire/coding/manager.js +158 -9
  229. package/dist/repertoire/coding/spawner.js +55 -9
  230. package/dist/repertoire/coding/tools.js +170 -7
  231. package/dist/repertoire/commerce-errors.js +109 -0
  232. package/dist/repertoire/commerce-self-test.js +156 -0
  233. package/dist/repertoire/credential-access.js +111 -0
  234. package/dist/repertoire/duffel-client.js +185 -0
  235. package/dist/repertoire/github-client.js +14 -55
  236. package/dist/repertoire/graph-client.js +11 -52
  237. package/dist/repertoire/guardrails.js +396 -0
  238. package/dist/repertoire/mcp-client.js +255 -0
  239. package/dist/repertoire/mcp-manager.js +305 -0
  240. package/dist/repertoire/mcp-tools.js +63 -0
  241. package/dist/repertoire/shell-sessions.js +133 -0
  242. package/dist/repertoire/skills.js +15 -24
  243. package/dist/repertoire/stripe-client.js +131 -0
  244. package/dist/repertoire/tasks/board.js +43 -5
  245. package/dist/repertoire/tasks/fix.js +182 -0
  246. package/dist/repertoire/tasks/index.js +37 -4
  247. package/dist/repertoire/tasks/lifecycle.js +2 -2
  248. package/dist/repertoire/tasks/parser.js +3 -2
  249. package/dist/repertoire/tasks/scanner.js +194 -37
  250. package/dist/repertoire/tasks/transitions.js +16 -78
  251. package/dist/repertoire/tool-results.js +29 -0
  252. package/dist/repertoire/tools-attachments.js +317 -0
  253. package/dist/repertoire/tools-base.js +44 -740
  254. package/dist/repertoire/tools-bluebubbles.js +1 -0
  255. package/dist/repertoire/tools-bridge.js +141 -0
  256. package/dist/repertoire/tools-bundle.js +984 -0
  257. package/dist/repertoire/tools-config.js +185 -0
  258. package/dist/repertoire/tools-continuity.js +248 -0
  259. package/dist/repertoire/tools-credential.js +381 -0
  260. package/dist/repertoire/tools-files.js +342 -0
  261. package/dist/repertoire/tools-flight.js +224 -0
  262. package/dist/repertoire/tools-flow.js +105 -0
  263. package/dist/repertoire/tools-github.js +1 -7
  264. package/dist/repertoire/tools-mail.js +896 -0
  265. package/dist/repertoire/tools-notes.js +376 -0
  266. package/dist/repertoire/tools-session.js +746 -0
  267. package/dist/repertoire/tools-shell.js +120 -0
  268. package/dist/repertoire/tools-stripe.js +180 -0
  269. package/dist/repertoire/tools-surface.js +243 -0
  270. package/dist/repertoire/tools-teams.js +9 -39
  271. package/dist/repertoire/tools-travel.js +125 -0
  272. package/dist/repertoire/tools-user-profile.js +144 -0
  273. package/dist/repertoire/tools-vault.js +40 -0
  274. package/dist/repertoire/tools.js +144 -113
  275. package/dist/repertoire/travel-api-client.js +360 -0
  276. package/dist/repertoire/user-profile.js +131 -0
  277. package/dist/repertoire/vault-setup.js +246 -0
  278. package/dist/repertoire/vault-unlock.js +561 -0
  279. package/dist/scripts/claude-code-hook.js +41 -0
  280. package/dist/scripts/claude-code-stop-hook.js +47 -0
  281. package/dist/senses/attention-queue.js +116 -0
  282. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  283. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  284. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  285. package/dist/senses/bluebubbles/entry.js +73 -0
  286. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +7 -3
  287. package/dist/senses/{bluebubbles.js → bluebubbles/index.js} +705 -116
  288. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  289. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  290. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  291. package/dist/senses/bluebubbles/replay.js +129 -0
  292. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
  293. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  294. package/dist/senses/cli/bracketed-paste.js +82 -0
  295. package/dist/senses/cli/image-paste.js +287 -0
  296. package/dist/senses/cli/image-ref-navigation.js +75 -0
  297. package/dist/senses/cli/ink-app.js +156 -0
  298. package/dist/senses/cli/inline-diff.js +64 -0
  299. package/dist/senses/cli/input-keys.js +174 -0
  300. package/dist/senses/cli/kill-ring.js +86 -0
  301. package/dist/senses/cli/message-list.js +51 -0
  302. package/dist/senses/cli/ouro-tui.js +605 -0
  303. package/dist/senses/cli/spinner-imperative.js +135 -0
  304. package/dist/senses/cli/spinner.js +101 -0
  305. package/dist/senses/cli/status-line.js +60 -0
  306. package/dist/senses/cli/streaming-markdown.js +526 -0
  307. package/dist/senses/cli/tool-display.js +83 -0
  308. package/dist/senses/cli/tool-render.js +85 -0
  309. package/dist/senses/cli/tui-store.js +240 -0
  310. package/dist/senses/cli/virtual-list.js +35 -0
  311. package/dist/senses/cli-entry.js +60 -8
  312. package/dist/senses/cli-layout.js +187 -0
  313. package/dist/senses/cli.js +516 -211
  314. package/dist/senses/commands.js +66 -3
  315. package/dist/senses/habit-turn-message.js +108 -0
  316. package/dist/senses/inner-dialog-worker.js +97 -17
  317. package/dist/senses/inner-dialog.js +404 -14
  318. package/dist/senses/mail-entry.js +66 -0
  319. package/dist/senses/mail.js +232 -0
  320. package/dist/senses/pipeline.js +533 -72
  321. package/dist/senses/proactive-content-guard.js +51 -0
  322. package/dist/senses/shared-turn.js +205 -0
  323. package/dist/senses/surface-tool.js +68 -0
  324. package/dist/senses/teams-entry.js +60 -8
  325. package/dist/senses/teams.js +413 -163
  326. package/dist/senses/trust-gate.js +5 -5
  327. package/package.json +37 -7
  328. package/skills/agent-commerce.md +106 -0
  329. package/skills/browser-navigation.md +117 -0
  330. package/skills/commerce-setup-guide.md +116 -0
  331. package/skills/commerce-setup.md +84 -0
  332. package/skills/configure-dev-tools.md +101 -0
  333. package/skills/travel-planning.md +138 -0
  334. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  335. package/dist/heart/daemon/subagent-installer.js +0 -166
  336. package/dist/mind/associative-recall.js +0 -209
  337. package/dist/senses/bluebubbles-entry.js +0 -13
  338. package/dist/senses/debug-activity.js +0 -127
  339. package/subagents/README.md +0 -86
  340. package/subagents/work-doer.md +0 -237
  341. package/subagents/work-merger.md +0 -618
  342. package/subagents/work-planner.md +0 -390
  343. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  344. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  345. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  346. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  347. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  348. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  349. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  350. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  351. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  352. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  353. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  354. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  355. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  356. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  357. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  358. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,558 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AzureBlobMailroomStore = void 0;
4
+ exports.decryptBlobMessages = decryptBlobMessages;
5
+ const runtime_1 = require("../nerves/runtime");
6
+ const core_1 = require("./core");
7
+ const MESSAGE_INDEX_PREFIX = "message-index";
8
+ const MESSAGE_INDEX_SORT_MAX_MS = 9_999_999_999_999;
9
+ const MESSAGE_INDEX_SORT_WIDTH = 13;
10
+ const MESSAGE_INDEX_NO_SOURCE = "~";
11
+ const DEFAULT_BLOB_OPERATION_TIMEOUT_MS = 20_000;
12
+ const DEFAULT_MESSAGE_FETCH_CONCURRENCY = 20;
13
+ const DEFAULT_MESSAGE_INDEX_BACKFILL_CONCURRENCY = 8;
14
+ const MESSAGE_LIST_SCAN_CONCURRENCY = 32;
15
+ function compareNewestFirst(left, right) {
16
+ return Date.parse(right.receivedAt) - Date.parse(left.receivedAt);
17
+ }
18
+ function compareCandidatesNewestFirst(left, right) {
19
+ return Date.parse(right.lastSeenAt) - Date.parse(left.lastSeenAt);
20
+ }
21
+ function blobText(value) {
22
+ return Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf-8");
23
+ }
24
+ function positiveInteger(value, fallback) {
25
+ if (typeof value !== "number" || !Number.isFinite(value))
26
+ return fallback;
27
+ const normalized = Math.floor(value);
28
+ return normalized > 0 ? normalized : fallback;
29
+ }
30
+ function blobClientName(blob) {
31
+ return typeof blob.name === "string" && blob.name.trim().length > 0 ? blob.name : "<unknown-blob>";
32
+ }
33
+ function timeoutSignal(timeoutMs) {
34
+ if (typeof AbortSignal.timeout === "function") {
35
+ return {
36
+ signal: AbortSignal.timeout(timeoutMs),
37
+ dispose() {
38
+ return undefined;
39
+ },
40
+ };
41
+ }
42
+ const controller = new AbortController();
43
+ const timer = setTimeout(() => controller.abort(new Error(`The operation timed out after ${timeoutMs}ms`)), timeoutMs);
44
+ return {
45
+ signal: controller.signal,
46
+ dispose() {
47
+ clearTimeout(timer);
48
+ },
49
+ };
50
+ }
51
+ async function withBlobOperationTimeout(timeoutMs, operation) {
52
+ const timeout = timeoutSignal(timeoutMs);
53
+ try {
54
+ return await operation(timeout.signal);
55
+ }
56
+ finally {
57
+ timeout.dispose();
58
+ }
59
+ }
60
+ function normalizeBlobOperationError(action, blob, timeoutMs, error) {
61
+ const message = error instanceof Error ? error.message : String(error);
62
+ if ((error instanceof Error && error.name === "AbortError") || message.toLowerCase().includes("aborted")) {
63
+ return new Error(`${action} ${blobClientName(blob)} timed out after ${timeoutMs}ms`);
64
+ }
65
+ return new Error(`${action} ${blobClientName(blob)} failed: ${message}`);
66
+ }
67
+ async function downloadJson(blob, timeoutMs) {
68
+ if (!await blob.exists())
69
+ return null;
70
+ try {
71
+ const buffer = await withBlobOperationTimeout(timeoutMs, (abortSignal) => {
72
+ return blob.downloadToBuffer(undefined, undefined, { abortSignal });
73
+ });
74
+ return JSON.parse(buffer.toString("utf-8"));
75
+ }
76
+ catch (error) {
77
+ throw normalizeBlobOperationError("download", blob, timeoutMs, error);
78
+ }
79
+ }
80
+ async function uploadJson(blob, value, timeoutMs) {
81
+ try {
82
+ await withBlobOperationTimeout(timeoutMs, (abortSignal) => {
83
+ return blob.uploadData(blobText(value), { abortSignal });
84
+ });
85
+ }
86
+ catch (error) {
87
+ throw normalizeBlobOperationError("upload", blob, timeoutMs, error);
88
+ }
89
+ }
90
+ async function mapWithConcurrency(items, concurrency, worker) {
91
+ if (items.length === 0)
92
+ return [];
93
+ const results = new Array(items.length);
94
+ let nextIndex = 0;
95
+ const workerLoop = async () => {
96
+ while (true) {
97
+ const current = nextIndex;
98
+ nextIndex += 1;
99
+ if (current >= items.length)
100
+ return;
101
+ results[current] = await worker(items[current], current);
102
+ }
103
+ };
104
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, async () => workerLoop()));
105
+ return results;
106
+ }
107
+ function encodeSourceToken(source) {
108
+ return source ? encodeURIComponent(source.toLowerCase()) : MESSAGE_INDEX_NO_SOURCE;
109
+ }
110
+ function decodeSourceToken(token) {
111
+ return token === MESSAGE_INDEX_NO_SOURCE ? undefined : decodeURIComponent(token);
112
+ }
113
+ function parseSortMs(receivedAt) {
114
+ const parsed = Date.parse(receivedAt);
115
+ if (!Number.isFinite(parsed))
116
+ return 0;
117
+ return Math.max(0, Math.min(MESSAGE_INDEX_SORT_MAX_MS, parsed));
118
+ }
119
+ function messageIndexPrefix(agentId) {
120
+ return `${MESSAGE_INDEX_PREFIX}/${agentId}/`;
121
+ }
122
+ function messageIndexBlobName(message) {
123
+ const sortKey = String(MESSAGE_INDEX_SORT_MAX_MS - parseSortMs(message.receivedAt)).padStart(MESSAGE_INDEX_SORT_WIDTH, "0");
124
+ return `${messageIndexPrefix(message.agentId)}${sortKey}__${message.compartmentKind}__${message.placement}__${encodeSourceToken(message.source)}__${message.id}.json`;
125
+ }
126
+ function messageIndexRecord(message) {
127
+ return {
128
+ schemaVersion: 1,
129
+ id: message.id,
130
+ agentId: message.agentId,
131
+ compartmentKind: message.compartmentKind,
132
+ placement: message.placement,
133
+ ...(message.source ? { source: message.source } : {}),
134
+ receivedAt: message.receivedAt,
135
+ };
136
+ }
137
+ function parseMessageIndexBlobName(name) {
138
+ if (!name.startsWith(`${MESSAGE_INDEX_PREFIX}/`) || !name.endsWith(".json"))
139
+ return null;
140
+ const parts = name.split("/");
141
+ if (parts.length !== 3)
142
+ return null;
143
+ const agentId = parts[1];
144
+ const stem = parts[2].slice(0, -5);
145
+ const [sortKey, compartmentKind, placement, sourceToken, ...idParts] = stem.split("__");
146
+ if (!sortKey || !compartmentKind || !placement || !sourceToken || idParts.length === 0)
147
+ return null;
148
+ if (compartmentKind !== "native" && compartmentKind !== "delegated")
149
+ return null;
150
+ const receivedAtMs = MESSAGE_INDEX_SORT_MAX_MS - Number.parseInt(sortKey, 10);
151
+ return {
152
+ schemaVersion: 1,
153
+ id: idParts.join("__"),
154
+ agentId,
155
+ compartmentKind,
156
+ placement: placement,
157
+ ...(decodeSourceToken(sourceToken) ? { source: decodeSourceToken(sourceToken) } : {}),
158
+ receivedAt: Number.isFinite(receivedAtMs) ? new Date(receivedAtMs).toISOString() : new Date(0).toISOString(),
159
+ };
160
+ }
161
+ function sourceMatchesFilter(source, filter) {
162
+ if (!filter)
163
+ return true;
164
+ if (!source)
165
+ return false;
166
+ return source.toLowerCase() === filter.toLowerCase();
167
+ }
168
+ function messageMatchesFilters(message, filters) {
169
+ return message.agentId === filters.agentId &&
170
+ (filters.placement ? message.placement === filters.placement : true) &&
171
+ (filters.compartmentKind ? message.compartmentKind === filters.compartmentKind : true) &&
172
+ sourceMatchesFilter(message.source, filters.source);
173
+ }
174
+ class AzureBlobMailroomStore {
175
+ serviceClient;
176
+ containerName;
177
+ blobOperationTimeoutMs;
178
+ messageFetchConcurrency;
179
+ backfillConcurrency;
180
+ containerReady = null;
181
+ constructor(options) {
182
+ this.serviceClient = options.serviceClient;
183
+ this.containerName = options.containerName;
184
+ this.blobOperationTimeoutMs = positiveInteger(options.blobOperationTimeoutMs, DEFAULT_BLOB_OPERATION_TIMEOUT_MS);
185
+ this.messageFetchConcurrency = positiveInteger(options.messageFetchConcurrency, DEFAULT_MESSAGE_FETCH_CONCURRENCY);
186
+ this.backfillConcurrency = positiveInteger(options.backfillConcurrency, DEFAULT_MESSAGE_INDEX_BACKFILL_CONCURRENCY);
187
+ (0, runtime_1.emitNervesEvent)({
188
+ component: "senses",
189
+ event: "senses.mail_blob_store_init",
190
+ message: "azure blob mailroom store initialized",
191
+ meta: { containerName: this.containerName },
192
+ });
193
+ }
194
+ get container() {
195
+ return this.serviceClient.getContainerClient(this.containerName);
196
+ }
197
+ async ensureContainer() {
198
+ if (!this.containerReady) {
199
+ this.containerReady = this.container.createIfNotExists().then(() => undefined);
200
+ }
201
+ await this.containerReady;
202
+ }
203
+ messageBlob(id) {
204
+ return this.container.getBlockBlobClient(`messages/${id}.json`);
205
+ }
206
+ messageIndexBlob(name) {
207
+ return this.container.getBlockBlobClient(name);
208
+ }
209
+ candidateBlob(id) {
210
+ return this.container.getBlockBlobClient(`candidates/${id}.json`);
211
+ }
212
+ rawBlob(objectName) {
213
+ return this.container.getBlockBlobClient(objectName);
214
+ }
215
+ decisionsBlob(agentId) {
216
+ return this.container.getBlockBlobClient(`decisions/${agentId}.json`);
217
+ }
218
+ accessLogBlob(agentId) {
219
+ return this.container.getBlockBlobClient(`access-log/${agentId}.jsonl`);
220
+ }
221
+ outboundBlob(id) {
222
+ return this.container.getBlockBlobClient(`outbound/${id}.json`);
223
+ }
224
+ async putMessageIndex(message) {
225
+ await uploadJson(this.messageIndexBlob(messageIndexBlobName(message)), messageIndexRecord(message), this.blobOperationTimeoutMs);
226
+ }
227
+ async removeMessageIndex(message) {
228
+ await this.messageIndexBlob(messageIndexBlobName(message)).deleteIfExists();
229
+ }
230
+ async listMessagesLegacy(filters) {
231
+ const messageBlobNames = [];
232
+ for await (const item of this.container.listBlobsFlat({ prefix: "messages/" })) {
233
+ messageBlobNames.push(item.name);
234
+ }
235
+ const matches = [];
236
+ const limit = filters.limit ?? 20;
237
+ let nextIndex = 0;
238
+ const worker = async () => {
239
+ while (nextIndex < messageBlobNames.length) {
240
+ const current = messageBlobNames[nextIndex];
241
+ nextIndex += 1;
242
+ const message = await downloadJson(this.container.getBlockBlobClient(current), this.blobOperationTimeoutMs);
243
+ if (!message || !messageMatchesFilters(message, filters))
244
+ continue;
245
+ matches.push(message);
246
+ matches.sort(compareNewestFirst);
247
+ if (matches.length > limit)
248
+ matches.length = limit;
249
+ }
250
+ };
251
+ await Promise.all(Array.from({ length: Math.min(MESSAGE_LIST_SCAN_CONCURRENCY, Math.max(messageBlobNames.length, 1)) }, async () => worker()));
252
+ return matches.sort(compareNewestFirst).slice(0, limit);
253
+ }
254
+ async listMessagesFromIndexes(filters) {
255
+ const messageIds = [];
256
+ let sawIndex = false;
257
+ for await (const item of this.container.listBlobsFlat({ prefix: messageIndexPrefix(filters.agentId) })) {
258
+ sawIndex = true;
259
+ const parsed = parseMessageIndexBlobName(item.name);
260
+ if (!parsed || !messageMatchesFilters(parsed, filters))
261
+ continue;
262
+ messageIds.push(parsed.id);
263
+ if (messageIds.length >= (filters.limit ?? 20))
264
+ break;
265
+ }
266
+ if (!sawIndex)
267
+ return null;
268
+ return (await mapWithConcurrency(messageIds, this.messageFetchConcurrency, async (id) => {
269
+ return downloadJson(this.messageBlob(id), this.blobOperationTimeoutMs);
270
+ }))
271
+ .filter((message) => message !== null)
272
+ .filter((message) => messageMatchesFilters(message, filters))
273
+ .sort(compareNewestFirst)
274
+ .slice(0, filters.limit ?? 20);
275
+ }
276
+ async backfillMessageIndexes(agentId, onProgress) {
277
+ await this.ensureContainer();
278
+ const messageBlobNames = [];
279
+ for await (const item of this.container.listBlobsFlat({ prefix: "messages/" })) {
280
+ messageBlobNames.push(item.name);
281
+ }
282
+ let indexed = 0;
283
+ const failures = [];
284
+ let scanned = 0;
285
+ let nextIndex = 0;
286
+ const worker = async () => {
287
+ while (nextIndex < messageBlobNames.length) {
288
+ const current = messageBlobNames[nextIndex];
289
+ nextIndex += 1;
290
+ try {
291
+ const message = await downloadJson(this.container.getBlockBlobClient(current), this.blobOperationTimeoutMs);
292
+ if (!message)
293
+ continue;
294
+ if (agentId && message.agentId !== agentId)
295
+ continue;
296
+ await uploadJson(this.messageIndexBlob(messageIndexBlobName(message)), messageIndexRecord(message), this.blobOperationTimeoutMs);
297
+ indexed += 1;
298
+ }
299
+ catch (error) {
300
+ failures.push(error instanceof Error ? error.message : String(error));
301
+ }
302
+ finally {
303
+ scanned += 1;
304
+ onProgress?.({ scanned, indexed, failures: failures.length, total: messageBlobNames.length });
305
+ }
306
+ }
307
+ };
308
+ await Promise.all(Array.from({ length: Math.min(this.backfillConcurrency, Math.max(messageBlobNames.length, 1)) }, async () => worker()));
309
+ if (failures.length > 0) {
310
+ const sample = failures.slice(0, 3).join("; ");
311
+ throw new Error(`hosted message index backfill incomplete after indexing ${indexed} message(s); ${failures.length} blob operation(s) failed. first failure(s): ${sample}. rerun the command to retry remaining messages.`);
312
+ }
313
+ (0, runtime_1.emitNervesEvent)({
314
+ component: "senses",
315
+ event: "senses.mail_blob_index_backfilled",
316
+ message: "azure blob mailroom message indexes backfilled",
317
+ meta: { agentId: agentId ?? null, indexed },
318
+ });
319
+ return indexed;
320
+ }
321
+ async putRawMessage(input) {
322
+ await this.ensureContainer();
323
+ const { message, rawPayload, candidate } = await (0, core_1.buildStoredMailMessage)(input);
324
+ const existing = await downloadJson(this.messageBlob(message.id), this.blobOperationTimeoutMs);
325
+ if (existing) {
326
+ await this.putMessageIndex(existing);
327
+ (0, runtime_1.emitNervesEvent)({
328
+ component: "senses",
329
+ event: "senses.mail_blob_store_dedupe",
330
+ message: "azure blob mailroom store deduped existing message",
331
+ meta: { id: message.id, agentId: message.agentId },
332
+ });
333
+ return { created: false, message: existing };
334
+ }
335
+ await this.rawBlob(message.rawObject).uploadData(blobText(rawPayload));
336
+ await this.messageBlob(message.id).uploadData(blobText(message));
337
+ await this.putMessageIndex(message);
338
+ if (candidate) {
339
+ await this.candidateBlob(candidate.id).uploadData(blobText(candidate));
340
+ }
341
+ (0, runtime_1.emitNervesEvent)({
342
+ component: "senses",
343
+ event: "senses.mail_blob_store_message_written",
344
+ message: "azure blob mailroom store wrote message",
345
+ meta: { id: message.id, agentId: message.agentId, candidate: candidate !== undefined },
346
+ });
347
+ return { created: true, message };
348
+ }
349
+ async getMessage(id) {
350
+ await this.ensureContainer();
351
+ const message = await downloadJson(this.messageBlob(id), this.blobOperationTimeoutMs);
352
+ (0, runtime_1.emitNervesEvent)({
353
+ component: "senses",
354
+ event: "senses.mail_blob_store_message_read",
355
+ message: "azure blob mailroom store read message",
356
+ meta: { id, found: message !== null },
357
+ });
358
+ return message;
359
+ }
360
+ async listMessages(filters) {
361
+ await this.ensureContainer();
362
+ let filtered = await this.listMessagesFromIndexes(filters);
363
+ let source = "index";
364
+ if (filtered === null) {
365
+ filtered = await this.listMessagesLegacy(filters);
366
+ source = "legacy";
367
+ }
368
+ (0, runtime_1.emitNervesEvent)({
369
+ component: "senses",
370
+ event: "senses.mail_blob_store_messages_listed",
371
+ message: "azure blob mailroom store listed messages",
372
+ meta: { agentId: filters.agentId, count: filtered.length, source },
373
+ });
374
+ return filtered;
375
+ }
376
+ async updateMessagePlacement(id, placement) {
377
+ await this.ensureContainer();
378
+ const blob = this.messageBlob(id);
379
+ const message = await downloadJson(blob, this.blobOperationTimeoutMs);
380
+ if (!message) {
381
+ (0, runtime_1.emitNervesEvent)({
382
+ component: "senses",
383
+ event: "senses.mail_blob_store_message_placement_updated",
384
+ message: "azure blob mailroom store message placement update missed",
385
+ meta: { id, placement, found: false },
386
+ });
387
+ return null;
388
+ }
389
+ const updated = { ...message, placement };
390
+ await blob.uploadData(blobText(updated));
391
+ await this.removeMessageIndex(message);
392
+ await this.putMessageIndex(updated);
393
+ (0, runtime_1.emitNervesEvent)({
394
+ component: "senses",
395
+ event: "senses.mail_blob_store_message_placement_updated",
396
+ message: "azure blob mailroom store updated message placement",
397
+ meta: { id, placement, found: true },
398
+ });
399
+ return updated;
400
+ }
401
+ async readRawPayload(objectName) {
402
+ await this.ensureContainer();
403
+ const payload = await downloadJson(this.rawBlob(objectName), this.blobOperationTimeoutMs);
404
+ (0, runtime_1.emitNervesEvent)({
405
+ component: "senses",
406
+ event: "senses.mail_blob_store_raw_read",
407
+ message: "azure blob mailroom store read raw payload",
408
+ meta: { objectName, found: payload !== null },
409
+ });
410
+ return payload;
411
+ }
412
+ async putScreenerCandidate(candidate) {
413
+ await this.ensureContainer();
414
+ await this.candidateBlob(candidate.id).uploadData(blobText(candidate));
415
+ (0, runtime_1.emitNervesEvent)({
416
+ component: "senses",
417
+ event: "senses.mail_blob_screener_candidate_written",
418
+ message: "azure blob mail screener candidate written",
419
+ meta: { id: candidate.id, agentId: candidate.agentId, status: candidate.status },
420
+ });
421
+ return candidate;
422
+ }
423
+ async updateScreenerCandidate(candidate) {
424
+ return this.putScreenerCandidate(candidate);
425
+ }
426
+ async listScreenerCandidates(filters) {
427
+ await this.ensureContainer();
428
+ const candidates = [];
429
+ for await (const item of this.container.listBlobsFlat({ prefix: "candidates/" })) {
430
+ const candidate = await downloadJson(this.container.getBlockBlobClient(item.name), this.blobOperationTimeoutMs);
431
+ if (candidate)
432
+ candidates.push(candidate);
433
+ }
434
+ const filtered = candidates
435
+ .filter((candidate) => candidate.agentId === filters.agentId)
436
+ .filter((candidate) => filters.status ? candidate.status === filters.status : true)
437
+ .filter((candidate) => filters.placement ? candidate.placement === filters.placement : true)
438
+ .sort(compareCandidatesNewestFirst)
439
+ .slice(0, filters.limit ?? 50);
440
+ (0, runtime_1.emitNervesEvent)({
441
+ component: "senses",
442
+ event: "senses.mail_blob_screener_candidates_listed",
443
+ message: "azure blob mail screener candidates listed",
444
+ meta: { agentId: filters.agentId, count: filtered.length },
445
+ });
446
+ return filtered;
447
+ }
448
+ async recordMailDecision(entry) {
449
+ await this.ensureContainer();
450
+ const complete = {
451
+ schemaVersion: 1,
452
+ ...entry,
453
+ id: entry.id ?? `decision_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
454
+ createdAt: entry.createdAt ?? new Date().toISOString(),
455
+ };
456
+ const blob = this.decisionsBlob(entry.agentId);
457
+ const existing = await downloadJson(blob, this.blobOperationTimeoutMs).catch(() => null);
458
+ const entries = Array.isArray(existing) ? existing : [];
459
+ entries.push(complete);
460
+ await blob.uploadData(blobText(entries));
461
+ (0, runtime_1.emitNervesEvent)({
462
+ component: "senses",
463
+ event: "senses.mail_blob_decision_recorded",
464
+ message: "azure blob mail decision recorded",
465
+ meta: { agentId: entry.agentId, messageId: entry.messageId, action: entry.action },
466
+ });
467
+ return complete;
468
+ }
469
+ async listMailDecisions(agentId) {
470
+ await this.ensureContainer();
471
+ const entries = await downloadJson(this.decisionsBlob(agentId), this.blobOperationTimeoutMs);
472
+ const safeEntries = Array.isArray(entries) ? entries : [];
473
+ (0, runtime_1.emitNervesEvent)({
474
+ component: "senses",
475
+ event: "senses.mail_blob_decisions_listed",
476
+ message: "azure blob mail decisions listed",
477
+ meta: { agentId, count: safeEntries.length },
478
+ });
479
+ return safeEntries;
480
+ }
481
+ async upsertMailOutbound(record) {
482
+ await this.ensureContainer();
483
+ await this.outboundBlob(record.id).uploadData(blobText(record));
484
+ (0, runtime_1.emitNervesEvent)({
485
+ component: "senses",
486
+ event: "senses.mail_blob_outbound_record_written",
487
+ message: "azure blob mail outbound record written",
488
+ meta: { agentId: record.agentId, id: record.id, status: record.status },
489
+ });
490
+ return record;
491
+ }
492
+ async getMailOutbound(id) {
493
+ await this.ensureContainer();
494
+ const record = await downloadJson(this.outboundBlob(id), this.blobOperationTimeoutMs);
495
+ (0, runtime_1.emitNervesEvent)({
496
+ component: "senses",
497
+ event: "senses.mail_blob_outbound_record_read",
498
+ message: "azure blob mail outbound record read",
499
+ meta: { id, found: record !== null },
500
+ });
501
+ return record;
502
+ }
503
+ async listMailOutbound(agentId) {
504
+ await this.ensureContainer();
505
+ const records = [];
506
+ for await (const item of this.container.listBlobsFlat({ prefix: "outbound/" })) {
507
+ const record = await downloadJson(this.container.getBlockBlobClient(item.name), this.blobOperationTimeoutMs);
508
+ if (record)
509
+ records.push(record);
510
+ }
511
+ const filtered = records
512
+ .filter((record) => record.agentId === agentId)
513
+ .sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
514
+ (0, runtime_1.emitNervesEvent)({
515
+ component: "senses",
516
+ event: "senses.mail_blob_outbound_records_listed",
517
+ message: "azure blob mail outbound records listed",
518
+ meta: { agentId, count: filtered.length },
519
+ });
520
+ return filtered;
521
+ }
522
+ async recordAccess(entry) {
523
+ await this.ensureContainer();
524
+ const complete = {
525
+ ...entry,
526
+ id: `access_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
527
+ accessedAt: new Date().toISOString(),
528
+ };
529
+ const blob = this.accessLogBlob(entry.agentId);
530
+ const existing = await downloadJson(blob, this.blobOperationTimeoutMs).catch(() => null);
531
+ const entries = Array.isArray(existing) ? existing : [];
532
+ entries.push(complete);
533
+ await blob.uploadData(blobText(entries));
534
+ (0, runtime_1.emitNervesEvent)({
535
+ component: "senses",
536
+ event: "senses.mail_blob_access_recorded",
537
+ message: "azure blob mail access recorded",
538
+ meta: { agentId: entry.agentId, messageId: entry.messageId ?? null, tool: entry.tool },
539
+ });
540
+ return complete;
541
+ }
542
+ async listAccessLog(agentId) {
543
+ await this.ensureContainer();
544
+ const entries = await downloadJson(this.accessLogBlob(agentId), this.blobOperationTimeoutMs);
545
+ const safeEntries = Array.isArray(entries) ? entries : [];
546
+ (0, runtime_1.emitNervesEvent)({
547
+ component: "senses",
548
+ event: "senses.mail_blob_access_log_listed",
549
+ message: "azure blob mail access log listed",
550
+ meta: { agentId, count: safeEntries.length },
551
+ });
552
+ return safeEntries;
553
+ }
554
+ }
555
+ exports.AzureBlobMailroomStore = AzureBlobMailroomStore;
556
+ function decryptBlobMessages(messages, privateKeys) {
557
+ return messages.map((message) => (0, core_1.decryptStoredMailMessage)(message, privateKeys));
558
+ }