@ouro.bot/cli 0.1.0-alpha.60 → 0.1.0-alpha.601

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 (420) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +3863 -0
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +140 -0
  15. package/dist/arc/episodes.js +117 -0
  16. package/dist/arc/intentions.js +133 -0
  17. package/dist/arc/json-store.js +117 -0
  18. package/dist/arc/obligations.js +254 -0
  19. package/dist/arc/packets.js +193 -0
  20. package/dist/arc/presence.js +185 -0
  21. package/dist/arc/task-lifecycle.js +65 -0
  22. package/dist/heart/active-work.js +837 -26
  23. package/dist/heart/agent-entry.js +69 -3
  24. package/dist/heart/attachments/image-normalize.js +194 -0
  25. package/dist/heart/attachments/materialize.js +97 -0
  26. package/dist/heart/attachments/originals.js +88 -0
  27. package/dist/heart/attachments/render.js +29 -0
  28. package/dist/heart/attachments/sources/adapter.js +2 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/awaiting/await-alert.js +146 -0
  36. package/dist/heart/awaiting/await-expiry.js +108 -0
  37. package/dist/heart/awaiting/await-loader.js +91 -0
  38. package/dist/heart/awaiting/await-parser.js +141 -0
  39. package/dist/heart/awaiting/await-runtime-state.js +97 -0
  40. package/dist/heart/awaiting/await-scheduler.js +377 -0
  41. package/dist/heart/background-operations.js +281 -0
  42. package/dist/heart/bundle-state.js +168 -0
  43. package/dist/heart/commitments.js +142 -0
  44. package/dist/heart/config-registry.js +322 -0
  45. package/dist/heart/config.js +114 -119
  46. package/dist/heart/core.js +909 -246
  47. package/dist/heart/cross-chat-delivery.js +3 -18
  48. package/dist/heart/daemon/agent-config-check.js +419 -0
  49. package/dist/heart/daemon/agent-discovery.js +102 -3
  50. package/dist/heart/daemon/agent-service.js +522 -0
  51. package/dist/heart/daemon/agentic-repair.js +547 -0
  52. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  53. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  54. package/dist/heart/daemon/cadence.js +70 -0
  55. package/dist/heart/daemon/cli-defaults.js +776 -0
  56. package/dist/heart/daemon/cli-exec.js +7571 -0
  57. package/dist/heart/daemon/cli-help.js +498 -0
  58. package/dist/heart/daemon/cli-parse.js +1599 -0
  59. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  60. package/dist/heart/daemon/cli-render.js +763 -0
  61. package/dist/heart/daemon/cli-types.js +8 -0
  62. package/dist/heart/daemon/connect-bay.js +323 -0
  63. package/dist/heart/daemon/daemon-cli.js +29 -1703
  64. package/dist/heart/daemon/daemon-entry.js +485 -2
  65. package/dist/heart/daemon/daemon-health.js +176 -0
  66. package/dist/heart/daemon/daemon-rollup.js +57 -0
  67. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  68. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  69. package/dist/heart/daemon/daemon.js +842 -69
  70. package/dist/heart/daemon/dns-workflow.js +394 -0
  71. package/dist/heart/daemon/doctor-types.js +8 -0
  72. package/dist/heart/daemon/doctor.js +873 -0
  73. package/dist/heart/daemon/health-monitor.js +122 -1
  74. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  75. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  76. package/dist/heart/daemon/http-health-probe.js +80 -0
  77. package/dist/heart/daemon/human-command-screens.js +234 -0
  78. package/dist/heart/daemon/human-readiness.js +114 -0
  79. package/dist/heart/daemon/inner-status.js +89 -0
  80. package/dist/heart/daemon/interactive-repair.js +394 -0
  81. package/dist/heart/daemon/launchd.js +37 -8
  82. package/dist/heart/daemon/log-tailer.js +78 -9
  83. package/dist/heart/daemon/logs-prune.js +110 -0
  84. package/dist/heart/daemon/mcp-canary.js +297 -0
  85. package/dist/heart/daemon/os-cron-deps.js +135 -0
  86. package/dist/heart/daemon/os-cron.js +14 -12
  87. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  88. package/dist/heart/daemon/ouro-entry.js +3 -1
  89. package/dist/heart/daemon/process-manager.js +375 -33
  90. package/dist/heart/daemon/provider-discovery.js +137 -0
  91. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  92. package/dist/heart/daemon/pulse.js +475 -0
  93. package/dist/heart/daemon/readiness-repair.js +365 -0
  94. package/dist/heart/daemon/run-hooks.js +2 -0
  95. package/dist/heart/daemon/runtime-logging.js +10 -2
  96. package/dist/heart/daemon/runtime-metadata.js +2 -30
  97. package/dist/heart/daemon/safe-mode.js +161 -0
  98. package/dist/heart/daemon/sense-manager.js +462 -38
  99. package/dist/heart/daemon/session-id-resolver.js +131 -0
  100. package/dist/heart/daemon/skill-management-installer.js +94 -0
  101. package/dist/heart/daemon/socket-client.js +158 -11
  102. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  103. package/dist/heart/daemon/startup-tui.js +330 -0
  104. package/dist/heart/daemon/task-scheduler.js +3 -25
  105. package/dist/heart/daemon/terminal-ui.js +499 -0
  106. package/dist/heart/daemon/thoughts.js +162 -17
  107. package/dist/heart/daemon/up-progress.js +366 -0
  108. package/dist/heart/daemon/vault-items.js +56 -0
  109. package/dist/heart/delegation.js +1 -1
  110. package/dist/heart/habits/habit-migration.js +189 -0
  111. package/dist/heart/habits/habit-parser.js +140 -0
  112. package/dist/heart/habits/habit-runtime-state.js +100 -0
  113. package/dist/heart/habits/habit-scheduler.js +372 -0
  114. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  115. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  116. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  117. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  118. package/dist/heart/identity.js +166 -55
  119. package/dist/heart/kept-notes.js +357 -0
  120. package/dist/heart/kicks.js +1 -1
  121. package/dist/heart/machine-identity.js +161 -0
  122. package/dist/heart/mail-import-discovery.js +353 -0
  123. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  124. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  125. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  126. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  127. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  128. package/dist/heart/mailbox/mailbox-http.js +99 -0
  129. package/dist/heart/mailbox/mailbox-read.js +31 -0
  130. package/dist/heart/mailbox/mailbox-types.js +27 -0
  131. package/dist/heart/mailbox/mailbox-view.js +195 -0
  132. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  133. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  134. package/dist/heart/mailbox/readers/mail.js +375 -0
  135. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  136. package/dist/heart/mailbox/readers/sessions.js +232 -0
  137. package/dist/heart/mailbox/readers/shared.js +111 -0
  138. package/dist/heart/mcp/mcp-server.js +656 -0
  139. package/dist/heart/migrate-config.js +100 -0
  140. package/dist/heart/model-capabilities.js +19 -0
  141. package/dist/heart/platform.js +81 -0
  142. package/dist/heart/provider-attempt.js +134 -0
  143. package/dist/heart/provider-binding-resolver.js +267 -0
  144. package/dist/heart/provider-credentials.js +425 -0
  145. package/dist/heart/provider-failover.js +301 -0
  146. package/dist/heart/provider-models.js +81 -0
  147. package/dist/heart/provider-ping.js +262 -0
  148. package/dist/heart/provider-readiness-cache.js +40 -0
  149. package/dist/heart/provider-visibility.js +188 -0
  150. package/dist/heart/providers/anthropic-token.js +131 -0
  151. package/dist/heart/providers/anthropic.js +139 -52
  152. package/dist/heart/providers/azure.js +23 -11
  153. package/dist/heart/providers/error-classification.js +127 -0
  154. package/dist/heart/providers/github-copilot.js +145 -0
  155. package/dist/heart/providers/minimax-vlm.js +189 -0
  156. package/dist/heart/providers/minimax.js +26 -8
  157. package/dist/heart/providers/openai-codex.js +55 -40
  158. package/dist/heart/runtime-capability-check.js +170 -0
  159. package/dist/heart/runtime-credentials.js +367 -0
  160. package/dist/heart/runtime-cwd.js +87 -0
  161. package/dist/heart/sense-truth.js +13 -4
  162. package/dist/heart/session-activity.js +43 -22
  163. package/dist/heart/session-events.js +1149 -0
  164. package/dist/heart/session-playback-cli-main.js +5 -0
  165. package/dist/heart/session-playback-cli.js +36 -0
  166. package/dist/heart/session-playback.js +231 -0
  167. package/dist/heart/session-stats-cli-main.js +5 -0
  168. package/dist/heart/session-stats.js +182 -0
  169. package/dist/heart/session-transcript.js +243 -0
  170. package/dist/heart/start-of-turn-packet.js +345 -0
  171. package/dist/heart/streaming.js +44 -27
  172. package/dist/heart/sync-classification.js +176 -0
  173. package/dist/heart/sync.js +449 -0
  174. package/dist/heart/target-resolution.js +9 -5
  175. package/dist/heart/tempo.js +93 -0
  176. package/dist/heart/temporal-view.js +41 -0
  177. package/dist/heart/timeouts.js +101 -0
  178. package/dist/heart/tool-activity-callbacks.js +59 -0
  179. package/dist/heart/tool-description.js +143 -0
  180. package/dist/heart/tool-friction.js +55 -0
  181. package/dist/heart/tool-loop.js +200 -0
  182. package/dist/heart/turn-context.js +421 -0
  183. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  184. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  185. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  186. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  187. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  188. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  189. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  190. package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
  191. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  192. package/dist/mailbox-ui/index.html +15 -0
  193. package/dist/mailroom/attention.js +167 -0
  194. package/dist/mailroom/autonomy.js +209 -0
  195. package/dist/mailroom/blob-store.js +712 -0
  196. package/dist/mailroom/body-cache.js +61 -0
  197. package/dist/mailroom/core.js +788 -0
  198. package/dist/mailroom/entry.js +160 -0
  199. package/dist/mailroom/file-store.js +460 -0
  200. package/dist/mailroom/mbox-import.js +393 -0
  201. package/dist/mailroom/migration.js +164 -0
  202. package/dist/mailroom/outbound.js +380 -0
  203. package/dist/mailroom/policy.js +263 -0
  204. package/dist/mailroom/reader.js +233 -0
  205. package/dist/mailroom/search-cache.js +268 -0
  206. package/dist/mailroom/search-relevance.js +319 -0
  207. package/dist/mailroom/smtp-ingress.js +176 -0
  208. package/dist/mailroom/source-state.js +176 -0
  209. package/dist/mailroom/thread.js +109 -0
  210. package/dist/mailroom/travel-extract.js +89 -0
  211. package/dist/mind/bundle-manifest.js +7 -1
  212. package/dist/mind/context.js +165 -101
  213. package/dist/mind/diary-integrity.js +60 -0
  214. package/dist/mind/{memory.js → diary.js} +62 -75
  215. package/dist/mind/embedding-provider.js +60 -0
  216. package/dist/mind/file-state.js +179 -0
  217. package/dist/mind/friends/channel.js +39 -0
  218. package/dist/mind/friends/resolver.js +54 -2
  219. package/dist/mind/friends/store-file.js +39 -3
  220. package/dist/mind/friends/types.js +2 -2
  221. package/dist/mind/journal-index.js +161 -0
  222. package/dist/mind/note-search.js +268 -0
  223. package/dist/mind/obligation-steering.js +221 -0
  224. package/dist/mind/pending.js +4 -0
  225. package/dist/mind/prompt-refresh.js +3 -2
  226. package/dist/mind/prompt.js +1050 -135
  227. package/dist/mind/provenance-trust.js +26 -0
  228. package/dist/mind/scrutiny.js +173 -0
  229. package/dist/nerves/cli-logging.js +7 -1
  230. package/dist/nerves/coverage/audit-rules.js +15 -6
  231. package/dist/nerves/coverage/audit.js +28 -2
  232. package/dist/nerves/coverage/cli.js +1 -1
  233. package/dist/nerves/coverage/contract.js +5 -5
  234. package/dist/nerves/coverage/file-completeness.js +129 -5
  235. package/dist/nerves/event-buffer.js +111 -0
  236. package/dist/nerves/index.js +224 -4
  237. package/dist/nerves/observation.js +20 -0
  238. package/dist/nerves/redact.js +79 -0
  239. package/dist/nerves/review/cli-main.js +5 -0
  240. package/dist/nerves/review/cli.js +156 -0
  241. package/dist/nerves/review/core.js +152 -0
  242. package/dist/nerves/runtime.js +5 -1
  243. package/dist/repertoire/ado-client.js +15 -56
  244. package/dist/repertoire/ado-semantic.js +11 -10
  245. package/dist/repertoire/api-client.js +97 -0
  246. package/dist/repertoire/bitwarden-store.js +997 -0
  247. package/dist/repertoire/bundle-templates.js +72 -0
  248. package/dist/repertoire/bw-installer.js +180 -0
  249. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  250. package/dist/repertoire/coding/context-pack.js +330 -0
  251. package/dist/repertoire/coding/feedback.js +197 -30
  252. package/dist/repertoire/coding/manager.js +158 -9
  253. package/dist/repertoire/coding/spawner.js +55 -9
  254. package/dist/repertoire/coding/tools.js +170 -7
  255. package/dist/repertoire/commerce-errors.js +109 -0
  256. package/dist/repertoire/commerce-self-test.js +156 -0
  257. package/dist/repertoire/credential-access.js +178 -0
  258. package/dist/repertoire/duffel-client.js +185 -0
  259. package/dist/repertoire/github-client.js +14 -55
  260. package/dist/repertoire/graph-client.js +11 -52
  261. package/dist/repertoire/guardrails.js +396 -0
  262. package/dist/repertoire/mcp-client.js +295 -0
  263. package/dist/repertoire/mcp-manager.js +362 -0
  264. package/dist/repertoire/mcp-tools.js +63 -0
  265. package/dist/repertoire/shell-sessions.js +133 -0
  266. package/dist/repertoire/skills.js +15 -24
  267. package/dist/repertoire/stripe-client.js +131 -0
  268. package/dist/repertoire/tasks/board.js +31 -5
  269. package/dist/repertoire/tasks/fix.js +182 -0
  270. package/dist/repertoire/tasks/index.js +16 -4
  271. package/dist/repertoire/tasks/lifecycle.js +2 -2
  272. package/dist/repertoire/tasks/parser.js +3 -2
  273. package/dist/repertoire/tasks/scanner.js +194 -37
  274. package/dist/repertoire/tasks/transitions.js +16 -78
  275. package/dist/repertoire/tool-results.js +29 -0
  276. package/dist/repertoire/tools-attachments.js +317 -0
  277. package/dist/repertoire/tools-awaiting.js +360 -0
  278. package/dist/repertoire/tools-base.js +53 -1082
  279. package/dist/repertoire/tools-bluebubbles.js +1 -0
  280. package/dist/repertoire/tools-bridge.js +142 -0
  281. package/dist/repertoire/tools-bundle.js +984 -0
  282. package/dist/repertoire/tools-config.js +185 -0
  283. package/dist/repertoire/tools-continuity.js +248 -0
  284. package/dist/repertoire/tools-credential.js +381 -0
  285. package/dist/repertoire/tools-files.js +342 -0
  286. package/dist/repertoire/tools-flight.js +224 -0
  287. package/dist/repertoire/tools-flow.js +119 -0
  288. package/dist/repertoire/tools-github.js +1 -7
  289. package/dist/repertoire/tools-mail.js +1916 -0
  290. package/dist/repertoire/tools-notes.js +421 -0
  291. package/dist/repertoire/tools-obligations.js +142 -0
  292. package/dist/repertoire/tools-runtime.js +61 -0
  293. package/dist/repertoire/tools-session.js +809 -0
  294. package/dist/repertoire/tools-shell.js +120 -0
  295. package/dist/repertoire/tools-stripe.js +180 -0
  296. package/dist/repertoire/tools-surface.js +345 -0
  297. package/dist/repertoire/tools-teams.js +9 -39
  298. package/dist/repertoire/tools-travel.js +125 -0
  299. package/dist/repertoire/tools-trip.js +604 -0
  300. package/dist/repertoire/tools-user-profile.js +144 -0
  301. package/dist/repertoire/tools-vault.js +40 -0
  302. package/dist/repertoire/tools-voice.js +144 -0
  303. package/dist/repertoire/tools.js +115 -103
  304. package/dist/repertoire/travel-api-client.js +360 -0
  305. package/dist/repertoire/user-profile.js +131 -0
  306. package/dist/repertoire/vault-setup.js +246 -0
  307. package/dist/repertoire/vault-unlock.js +594 -0
  308. package/dist/scripts/claude-code-hook.js +41 -0
  309. package/dist/scripts/claude-code-stop-hook.js +47 -0
  310. package/dist/senses/attention-queue.js +116 -0
  311. package/dist/senses/await-turn-message.js +58 -0
  312. package/dist/senses/bluebubbles/active-turns.js +216 -0
  313. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  314. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  315. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  316. package/dist/senses/bluebubbles/entry.js +77 -0
  317. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  318. package/dist/senses/bluebubbles/index.js +2548 -0
  319. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  320. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  321. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  322. package/dist/senses/bluebubbles/processed-log.js +133 -0
  323. package/dist/senses/bluebubbles/replay.js +137 -0
  324. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  325. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  326. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  327. package/dist/senses/cli/bracketed-paste.js +82 -0
  328. package/dist/senses/cli/image-paste.js +287 -0
  329. package/dist/senses/cli/image-ref-navigation.js +75 -0
  330. package/dist/senses/cli/ink-app.js +156 -0
  331. package/dist/senses/cli/inline-diff.js +64 -0
  332. package/dist/senses/cli/input-keys.js +174 -0
  333. package/dist/senses/cli/kill-ring.js +86 -0
  334. package/dist/senses/cli/message-list.js +51 -0
  335. package/dist/senses/cli/ouro-tui.js +607 -0
  336. package/dist/senses/cli/spinner-imperative.js +135 -0
  337. package/dist/senses/cli/spinner.js +101 -0
  338. package/dist/senses/cli/status-line.js +60 -0
  339. package/dist/senses/cli/streaming-markdown.js +526 -0
  340. package/dist/senses/cli/tool-display.js +85 -0
  341. package/dist/senses/cli/tool-render.js +85 -0
  342. package/dist/senses/cli/tui-store.js +240 -0
  343. package/dist/senses/cli/virtual-list.js +35 -0
  344. package/dist/senses/cli-entry.js +60 -8
  345. package/dist/senses/cli-layout.js +100 -0
  346. package/dist/senses/cli.js +516 -204
  347. package/dist/senses/commands.js +66 -3
  348. package/dist/senses/habit-turn-message.js +108 -0
  349. package/dist/senses/inner-dialog-worker.js +185 -21
  350. package/dist/senses/inner-dialog.js +372 -27
  351. package/dist/senses/mail-entry.js +66 -0
  352. package/dist/senses/mail.js +379 -0
  353. package/dist/senses/pipeline.js +654 -181
  354. package/dist/senses/proactive-content-guard.js +51 -0
  355. package/dist/senses/shared-turn.js +392 -0
  356. package/dist/senses/surface-tool.js +70 -0
  357. package/dist/senses/teams-entry.js +60 -8
  358. package/dist/senses/teams.js +387 -98
  359. package/dist/senses/trust-gate.js +100 -5
  360. package/dist/senses/voice/audio-playback.js +237 -0
  361. package/dist/senses/voice/audio-routing.js +119 -0
  362. package/dist/senses/voice/elevenlabs.js +202 -0
  363. package/dist/senses/voice/floor-control.js +431 -0
  364. package/dist/senses/voice/floor-controller.js +115 -0
  365. package/dist/senses/voice/golden-path.js +116 -0
  366. package/dist/senses/voice/index.js +29 -0
  367. package/dist/senses/voice/meeting.js +113 -0
  368. package/dist/senses/voice/outbound.js +190 -0
  369. package/dist/senses/voice/phone.js +33 -0
  370. package/dist/senses/voice/playback.js +139 -0
  371. package/dist/senses/voice/realtime-eval.js +496 -0
  372. package/dist/senses/voice/realtime-trace.js +531 -0
  373. package/dist/senses/voice/transcript.js +70 -0
  374. package/dist/senses/voice/turn.js +191 -0
  375. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  376. package/dist/senses/voice/twilio-phone.js +5077 -0
  377. package/dist/senses/voice/types.js +2 -0
  378. package/dist/senses/voice/whisper.js +161 -0
  379. package/dist/senses/voice-entry.js +81 -0
  380. package/dist/senses/voice-realtime-eval-command.js +99 -0
  381. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  382. package/dist/senses/voice-twilio-entry.js +87 -0
  383. package/dist/trips/core.js +138 -0
  384. package/dist/trips/store.js +265 -0
  385. package/package.json +41 -7
  386. package/skills/agent-commerce.md +106 -0
  387. package/skills/browser-navigation.md +117 -0
  388. package/skills/commerce-setup-guide.md +116 -0
  389. package/skills/commerce-setup.md +84 -0
  390. package/skills/configure-dev-tools.md +99 -0
  391. package/skills/travel-planning.md +138 -0
  392. package/dist/heart/daemon/auth-flow.js +0 -351
  393. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  394. package/dist/heart/daemon/subagent-installer.js +0 -166
  395. package/dist/heart/safe-workspace.js +0 -228
  396. package/dist/heart/session-recall.js +0 -116
  397. package/dist/mind/associative-recall.js +0 -209
  398. package/dist/senses/bluebubbles-entry.js +0 -13
  399. package/dist/senses/bluebubbles.js +0 -1177
  400. package/dist/senses/debug-activity.js +0 -148
  401. package/subagents/README.md +0 -86
  402. package/subagents/work-doer.md +0 -237
  403. package/subagents/work-merger.md +0 -618
  404. package/subagents/work-planner.md +0 -390
  405. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  406. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  407. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  408. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  409. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  410. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  411. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  412. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  413. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  414. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  415. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  416. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  417. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  418. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  419. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  420. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,393 @@
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.splitMboxMessages = splitMboxMessages;
37
+ exports.importMboxToStore = importMboxToStore;
38
+ exports.importMboxFileToStore = importMboxFileToStore;
39
+ exports.cacheMatchingMailSearchDocumentsFromMboxFile = cacheMatchingMailSearchDocumentsFromMboxFile;
40
+ const fs = __importStar(require("node:fs"));
41
+ const runtime_1 = require("../nerves/runtime");
42
+ const core_1 = require("./core");
43
+ const search_cache_1 = require("./search-cache");
44
+ const search_relevance_1 = require("./search-relevance");
45
+ function splitMboxMessages(rawMbox) {
46
+ const text = rawMbox.toString("utf-8");
47
+ const separators = [...text.matchAll(/^From [^\r\n]*(?:\r?\n)/gm)];
48
+ if (separators.length === 0) {
49
+ const trimmed = text.trim();
50
+ return trimmed ? [Buffer.from(text, "utf-8")] : [];
51
+ }
52
+ const messages = separators
53
+ .map((match, index) => {
54
+ const start = match.index + match[0].length;
55
+ const end = index + 1 < separators.length ? separators[index + 1].index : text.length;
56
+ return text.slice(start, end).replace(/\r?\n$/, "");
57
+ })
58
+ .filter((message) => message.trim().length > 0)
59
+ .map((message) => Buffer.from(message, "utf-8"));
60
+ (0, runtime_1.emitNervesEvent)({
61
+ component: "senses",
62
+ event: "senses.mail_mbox_split",
63
+ message: "mbox payload split into messages",
64
+ meta: { messages: messages.length },
65
+ });
66
+ return messages;
67
+ }
68
+ function trimTrailingLineEnding(message) {
69
+ if (message.length >= 2 && message[message.length - 2] === 0x0d && message[message.length - 1] === 0x0a) {
70
+ return message.subarray(0, -2);
71
+ }
72
+ if (message.length >= 1 && message[message.length - 1] === 0x0a) {
73
+ return message.subarray(0, -1);
74
+ }
75
+ return message;
76
+ }
77
+ function isSeparatorLine(line) {
78
+ return line.length >= 5 &&
79
+ line[0] === 0x46 &&
80
+ line[1] === 0x72 &&
81
+ line[2] === 0x6f &&
82
+ line[3] === 0x6d &&
83
+ line[4] === 0x20;
84
+ }
85
+ async function* streamMboxMessagesFromFile(filePath) {
86
+ const stream = fs.createReadStream(filePath);
87
+ let pending = Buffer.alloc(0);
88
+ let currentParts = [];
89
+ const flushCurrent = () => {
90
+ if (currentParts.length === 0)
91
+ return null;
92
+ const message = trimTrailingLineEnding(Buffer.concat(currentParts));
93
+ currentParts = [];
94
+ return message;
95
+ };
96
+ for await (const chunk of stream) {
97
+ pending = pending.length > 0 ? Buffer.concat([pending, chunk]) : Buffer.from(chunk);
98
+ let newlineIndex = pending.indexOf(0x0a);
99
+ while (newlineIndex >= 0) {
100
+ const line = pending.subarray(0, newlineIndex + 1);
101
+ pending = pending.subarray(newlineIndex + 1);
102
+ if (isSeparatorLine(line)) {
103
+ const message = flushCurrent();
104
+ if (message && message.length > 0)
105
+ yield message;
106
+ }
107
+ else {
108
+ currentParts.push(Buffer.from(line));
109
+ }
110
+ newlineIndex = pending.indexOf(0x0a);
111
+ }
112
+ }
113
+ if (pending.length > 0) {
114
+ if (isSeparatorLine(pending)) {
115
+ const message = flushCurrent();
116
+ if (message && message.length > 0)
117
+ yield message;
118
+ }
119
+ else {
120
+ currentParts.push(Buffer.from(pending));
121
+ }
122
+ }
123
+ const finalMessage = flushCurrent();
124
+ if (finalMessage && finalMessage.length > 0)
125
+ yield finalMessage;
126
+ }
127
+ function findSourceGrant(input) {
128
+ const ownerEmail = input.ownerEmail ? (0, core_1.normalizeMailAddress)(input.ownerEmail) : undefined;
129
+ const source = input.source?.trim().toLowerCase();
130
+ const grants = input.registry.sourceGrants.filter((grant) => {
131
+ if (!grant.enabled || grant.agentId !== input.agentId)
132
+ return false;
133
+ if (ownerEmail && (0, core_1.normalizeMailAddress)(grant.ownerEmail) !== ownerEmail)
134
+ return false;
135
+ if (source && grant.source.toLowerCase() !== source)
136
+ return false;
137
+ return true;
138
+ });
139
+ if (grants.length === 0) {
140
+ throw new Error(`No enabled Mailroom source grant found for ${input.agentId}${ownerEmail ? ` owner ${ownerEmail}` : ""}${source ? ` source ${source}` : ""}`);
141
+ }
142
+ if (grants.length > 1 && !ownerEmail && !source) {
143
+ throw new Error(`Multiple source grants found for ${input.agentId}; pass --owner-email or --source to choose one`);
144
+ }
145
+ return grants[0];
146
+ }
147
+ function parseMboxMessage(rawMessage, grant) {
148
+ const mailFrom = extractHeaderAddress(rawMessage, "from");
149
+ const messageDate = extractHeaderDate(rawMessage, "date");
150
+ return {
151
+ rawMessage,
152
+ envelope: {
153
+ mailFrom: mailFrom ? (0, core_1.normalizeMailAddress)(mailFrom) : "",
154
+ rcptTo: [(0, core_1.normalizeMailAddress)(grant.aliasAddress)],
155
+ remoteAddress: "mbox-import",
156
+ },
157
+ ...(messageDate ? { messageDate } : {}),
158
+ };
159
+ }
160
+ function latestMessageDate(messages) {
161
+ const timestamps = messages
162
+ .map((message) => message.messageDate?.getTime())
163
+ .filter((timestamp) => typeof timestamp === "number" && Number.isFinite(timestamp));
164
+ if (timestamps.length === 0)
165
+ return null;
166
+ return new Date(Math.max(...timestamps)).toISOString();
167
+ }
168
+ function readHeaderBlock(rawMessage) {
169
+ const crlfBoundary = rawMessage.indexOf("\r\n\r\n");
170
+ if (crlfBoundary >= 0) {
171
+ return rawMessage.subarray(0, crlfBoundary).toString("utf-8");
172
+ }
173
+ const lfBoundary = rawMessage.indexOf("\n\n");
174
+ if (lfBoundary >= 0) {
175
+ return rawMessage.subarray(0, lfBoundary).toString("utf-8");
176
+ }
177
+ return rawMessage.toString("utf-8");
178
+ }
179
+ function extractHeaderValue(rawMessage, headerName) {
180
+ const target = `${headerName.toLowerCase()}:`;
181
+ let currentHeader = "";
182
+ const unfoldedHeaders = [];
183
+ for (const line of readHeaderBlock(rawMessage).split(/\r?\n/)) {
184
+ if (/^[ \t]/.test(line) && currentHeader) {
185
+ currentHeader += ` ${line.trim()}`;
186
+ continue;
187
+ }
188
+ if (currentHeader)
189
+ unfoldedHeaders.push(currentHeader);
190
+ currentHeader = line;
191
+ }
192
+ if (currentHeader)
193
+ unfoldedHeaders.push(currentHeader);
194
+ const match = unfoldedHeaders.find((line) => line.toLowerCase().startsWith(target));
195
+ return match ? match.slice(target.length).trim() : "";
196
+ }
197
+ function extractHeaderAddress(rawMessage, headerName) {
198
+ const value = extractHeaderValue(rawMessage, headerName);
199
+ if (!value)
200
+ return "";
201
+ const bracketed = value.match(/<([^>]+)>/);
202
+ if (bracketed?.[1])
203
+ return bracketed[1];
204
+ const plain = value.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i);
205
+ return plain?.[0] ?? "";
206
+ }
207
+ function extractHeaderDate(rawMessage, headerName) {
208
+ const value = extractHeaderValue(rawMessage, headerName);
209
+ if (!value)
210
+ return undefined;
211
+ const parsed = new Date(value);
212
+ return Number.isFinite(parsed.getTime()) ? parsed : undefined;
213
+ }
214
+ function normalizeSearchTerms(queryTerms) {
215
+ return queryTerms
216
+ .map((term) => term.trim().toLowerCase())
217
+ .filter((term) => term.length > 0);
218
+ }
219
+ function historicalImportClassification(resolvedPlacement, sourceGrant) {
220
+ return {
221
+ placement: resolvedPlacement,
222
+ candidate: false,
223
+ trustReason: `delegated source grant ${sourceGrant.source} historical mbox import`,
224
+ };
225
+ }
226
+ async function importParsedMessagesToStore(input) {
227
+ let imported = 0;
228
+ let duplicates = 0;
229
+ const messages = [];
230
+ let scanned = 0;
231
+ const importedAt = (input.importedAt ?? new Date()).toISOString();
232
+ const sourceFreshThrough = input.sourceFreshThrough ?? null;
233
+ const maxConcurrency = Math.max(1, input.maxConcurrency ?? 1);
234
+ const inFlight = new Set();
235
+ const enqueue = (parsedMessage) => {
236
+ const task = (async () => {
237
+ const result = await input.store.putRawMessage({
238
+ resolved: input.resolved,
239
+ envelope: parsedMessage.envelope,
240
+ rawMime: parsedMessage.rawMessage,
241
+ receivedAt: parsedMessage.messageDate ?? input.importedAt,
242
+ ingest: {
243
+ schemaVersion: 1,
244
+ kind: "mbox-import",
245
+ importedAt,
246
+ sourceFreshThrough,
247
+ attentionSuppressed: true,
248
+ },
249
+ classification: historicalImportClassification(input.resolved.defaultPlacement, input.sourceGrant),
250
+ });
251
+ if (input.collectMessages !== false)
252
+ messages.push(result.message);
253
+ if (result.created)
254
+ imported += 1;
255
+ else
256
+ duplicates += 1;
257
+ input.onProgress?.({ scanned, imported, duplicates });
258
+ })().finally(() => {
259
+ inFlight.delete(task);
260
+ });
261
+ inFlight.add(task);
262
+ return task;
263
+ };
264
+ for await (const parsedMessage of input.parsedMessages) {
265
+ scanned += 1;
266
+ input.onProgress?.({ scanned, imported, duplicates });
267
+ enqueue(parsedMessage);
268
+ if (inFlight.size >= maxConcurrency) {
269
+ await Promise.race(inFlight);
270
+ }
271
+ }
272
+ await Promise.all(inFlight);
273
+ (0, runtime_1.emitNervesEvent)({
274
+ component: "senses",
275
+ event: "senses.mail_mbox_imported",
276
+ message: "mbox mail imported",
277
+ meta: { agentId: input.sourceGrant.agentId.toLowerCase(), scanned, imported, duplicates, grantId: input.sourceGrant.grantId },
278
+ });
279
+ return {
280
+ agentId: input.sourceGrant.agentId.toLowerCase(),
281
+ sourceGrant: input.sourceGrant,
282
+ scanned,
283
+ imported,
284
+ duplicates,
285
+ sourceFreshThrough,
286
+ messages,
287
+ };
288
+ }
289
+ async function scanMboxFileFreshness(filePath, sourceGrant) {
290
+ let latestTimestamp = Number.NEGATIVE_INFINITY;
291
+ for await (const rawMessage of streamMboxMessagesFromFile(filePath)) {
292
+ const parsedMessage = parseMboxMessage(rawMessage, sourceGrant);
293
+ if (parsedMessage.messageDate) {
294
+ latestTimestamp = Math.max(latestTimestamp, parsedMessage.messageDate.getTime());
295
+ }
296
+ }
297
+ return Number.isFinite(latestTimestamp) ? new Date(latestTimestamp).toISOString() : null;
298
+ }
299
+ function resolveImportTarget(input) {
300
+ const agentId = input.agentId.toLowerCase();
301
+ const sourceGrant = findSourceGrant({
302
+ registry: input.registry,
303
+ agentId,
304
+ ownerEmail: input.ownerEmail,
305
+ source: input.source,
306
+ });
307
+ const resolved = (0, core_1.resolveMailAddress)(input.registry, sourceGrant.aliasAddress);
308
+ /* v8 ignore start -- findSourceGrant and resolveMailAddress share the same registry; this is a corruption guard. @preserve */
309
+ if (!resolved) {
310
+ throw new Error(`Source grant alias ${sourceGrant.aliasAddress} is not resolvable`);
311
+ }
312
+ /* v8 ignore stop */
313
+ return { agentId, sourceGrant, resolved };
314
+ }
315
+ async function importMboxToStore(input) {
316
+ const target = resolveImportTarget(input);
317
+ const rawMessages = splitMboxMessages(input.rawMbox);
318
+ const parsedMessages = rawMessages.map((rawMessage) => parseMboxMessage(rawMessage, target.sourceGrant));
319
+ const sourceFreshThrough = latestMessageDate(parsedMessages);
320
+ return importParsedMessagesToStore({
321
+ sourceGrant: target.sourceGrant,
322
+ resolved: target.resolved,
323
+ store: input.store,
324
+ parsedMessages,
325
+ importedAt: input.importedAt,
326
+ collectMessages: true,
327
+ sourceFreshThrough,
328
+ });
329
+ }
330
+ async function importMboxFileToStore(input) {
331
+ const target = resolveImportTarget(input);
332
+ const sourceFreshThrough = await scanMboxFileFreshness(input.filePath, target.sourceGrant);
333
+ async function* parsedMessages() {
334
+ for await (const rawMessage of streamMboxMessagesFromFile(input.filePath)) {
335
+ yield parseMboxMessage(rawMessage, target.sourceGrant);
336
+ }
337
+ }
338
+ return importParsedMessagesToStore({
339
+ sourceGrant: target.sourceGrant,
340
+ resolved: target.resolved,
341
+ store: input.store,
342
+ parsedMessages: parsedMessages(),
343
+ importedAt: input.importedAt,
344
+ collectMessages: false,
345
+ sourceFreshThrough,
346
+ maxConcurrency: 8,
347
+ onProgress: input.onProgress,
348
+ });
349
+ }
350
+ async function cacheMatchingMailSearchDocumentsFromMboxFile(input) {
351
+ const target = resolveImportTarget(input);
352
+ const queryTerms = normalizeSearchTerms(input.queryTerms);
353
+ if (queryTerms.length === 0 || input.limit <= 0)
354
+ return [];
355
+ const matches = [];
356
+ for await (const rawMessage of streamMboxMessagesFromFile(input.filePath)) {
357
+ const parsedMessage = parseMboxMessage(rawMessage, target.sourceGrant);
358
+ const { privateEnvelope, metadata } = await (0, core_1.buildStoredMailMessageMetadata)({
359
+ resolved: target.resolved,
360
+ envelope: parsedMessage.envelope,
361
+ rawMime: parsedMessage.rawMessage,
362
+ receivedAt: parsedMessage.messageDate,
363
+ ingest: {
364
+ schemaVersion: 1,
365
+ kind: "mbox-import",
366
+ attentionSuppressed: true,
367
+ },
368
+ classification: historicalImportClassification(target.resolved.defaultPlacement, target.sourceGrant),
369
+ });
370
+ // Projection-only: we need a `StoredMailMessage` shape for buildMailSearchCacheDocument
371
+ // but never persist this view; the live import (via store.putRawMessage) is
372
+ // what writes the durable record.
373
+ const { rawObjectStem, ...rest } = metadata;
374
+ const message = {
375
+ ...rest,
376
+ rawObject: `${rawObjectStem}.eml`,
377
+ bodyForm: "plaintext",
378
+ private: privateEnvelope,
379
+ };
380
+ const document = (0, search_cache_1.buildMailSearchCacheDocument)(message, privateEnvelope);
381
+ if (!queryTerms.some((term) => document.searchText.includes(term)))
382
+ continue;
383
+ (0, search_cache_1.upsertMailSearchCacheDocument)(message, privateEnvelope);
384
+ matches.push(document);
385
+ matches.sort((left, right) => (0, search_relevance_1.compareByRelevanceThenRecency)({ document: left, relevance: (0, search_relevance_1.scoreMailSearchDocument)(left, queryTerms) }, { document: right, relevance: (0, search_relevance_1.scoreMailSearchDocument)(right, queryTerms) }));
386
+ if (matches.length > input.limit)
387
+ matches.length = input.limit;
388
+ }
389
+ return matches
390
+ .map((document) => ({ document, relevance: (0, search_relevance_1.scoreMailSearchDocument)(document, queryTerms) }))
391
+ .sort(search_relevance_1.compareByRelevanceThenRecency)
392
+ .map((entry) => entry.document);
393
+ }
@@ -0,0 +1,164 @@
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.migrateLocalMailroomToPlaintext = migrateLocalMailroomToPlaintext;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const runtime_1 = require("../nerves/runtime");
40
+ function readJson(filePath) {
41
+ try {
42
+ return JSON.parse(fs.readFileSync(filePath, "utf-8"));
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ function listJsonEntries(dir) {
49
+ if (!fs.existsSync(dir))
50
+ return [];
51
+ return fs.readdirSync(dir).filter((name) => name.endsWith(".json"));
52
+ }
53
+ /**
54
+ * One-time, idempotent cleanup of pre-plaintext residue.
55
+ *
56
+ * Wipes:
57
+ * - `messages/*.json` for this agent that are not already in the new plaintext
58
+ * shape (no `bodyForm: "plaintext"` AND no `private` field). Unparseable JSON
59
+ * also goes — we cannot safely keep ambiguous bytes.
60
+ * - `raw/*.json` files that look like an `EncryptedPayload` JSON wrapper (the
61
+ * pre-change raw-storage shape). Plaintext `.eml` files are preserved.
62
+ * Non-EncryptedPayload JSON in `raw/` is left alone.
63
+ * - Coverage records in `searchCacheRoot/coverage/` whose `storeKind` is no
64
+ * longer reachable (`azure-blob` from a previous hosted attachment) or whose
65
+ * JSON is unreadable. `file` coverage records are preserved.
66
+ * - Orphan search-cache docs in `searchCacheRoot/*.json` that belong to this
67
+ * agent but reference a `messageId` no longer present in `messages/`.
68
+ *
69
+ * Idempotent: a second run finds nothing to wipe and returns zeroed counts.
70
+ */
71
+ function migrateLocalMailroomToPlaintext(input) {
72
+ const messagesDir = path.join(input.mailroomRoot, "messages");
73
+ const rawDir = path.join(input.mailroomRoot, "raw");
74
+ const coverageDir = path.join(input.searchCacheRoot, "coverage");
75
+ let wipedEnvelopes = 0;
76
+ let wipedRaw = 0;
77
+ let wipedCoverageRecords = 0;
78
+ let wipedOrphanSearchDocs = 0;
79
+ // 1. Messages: drop pre-plaintext or malformed shapes for this agent.
80
+ const surviving = new Set();
81
+ for (const entry of listJsonEntries(messagesDir)) {
82
+ const filePath = path.join(messagesDir, entry);
83
+ const value = readJson(filePath);
84
+ if (value === null) {
85
+ // Unparseable JSON — we cannot tell whose it is or what shape, but the
86
+ // pre-change codebase wrote message JSON here; treat as wipeable.
87
+ fs.unlinkSync(filePath);
88
+ wipedEnvelopes += 1;
89
+ continue;
90
+ }
91
+ const isCurrentShape = value.bodyForm === "plaintext" && value.private !== undefined && value.private !== null;
92
+ if (isCurrentShape) {
93
+ const stem = entry.slice(0, -".json".length);
94
+ surviving.add(stem);
95
+ continue;
96
+ }
97
+ // We don't restrict to a specific agentId here because the file store is
98
+ // single-agent: the bundle owns this directory and the migration is
99
+ // initiated from inside that bundle.
100
+ fs.unlinkSync(filePath);
101
+ wipedEnvelopes += 1;
102
+ }
103
+ // 2. Raw artifacts: drop pre-change encrypted JSON wrappers.
104
+ if (fs.existsSync(rawDir)) {
105
+ for (const entry of fs.readdirSync(rawDir)) {
106
+ if (!entry.endsWith(".json"))
107
+ continue;
108
+ const filePath = path.join(rawDir, entry);
109
+ const value = readJson(filePath);
110
+ const isEncryptedPayload = value !== null
111
+ && typeof value.algorithm === "string"
112
+ && value.algorithm.startsWith("RSA-OAEP")
113
+ && typeof value.ciphertext === "string";
114
+ if (!isEncryptedPayload)
115
+ continue;
116
+ fs.unlinkSync(filePath);
117
+ wipedRaw += 1;
118
+ }
119
+ }
120
+ // 3. Coverage records: drop azure-blob (no longer reachable) and malformed.
121
+ for (const entry of listJsonEntries(coverageDir)) {
122
+ const filePath = path.join(coverageDir, entry);
123
+ const value = readJson(filePath);
124
+ if (value === null) {
125
+ fs.unlinkSync(filePath);
126
+ wipedCoverageRecords += 1;
127
+ continue;
128
+ }
129
+ if (value.agentId !== input.agentId)
130
+ continue;
131
+ if (value.storeKind === "file")
132
+ continue;
133
+ fs.unlinkSync(filePath);
134
+ wipedCoverageRecords += 1;
135
+ }
136
+ // 4. Orphan search-cache docs.
137
+ for (const entry of listJsonEntries(input.searchCacheRoot)) {
138
+ const filePath = path.join(input.searchCacheRoot, entry);
139
+ const value = readJson(filePath);
140
+ if (value === null)
141
+ continue;
142
+ if (value.agentId !== input.agentId)
143
+ continue;
144
+ if (typeof value.messageId !== "string")
145
+ continue;
146
+ if (surviving.has(value.messageId))
147
+ continue;
148
+ fs.unlinkSync(filePath);
149
+ wipedOrphanSearchDocs += 1;
150
+ }
151
+ (0, runtime_1.emitNervesEvent)({
152
+ component: "senses",
153
+ event: "senses.mail_local_migration_executed",
154
+ message: "local mailroom plaintext migration executed",
155
+ meta: {
156
+ agentId: input.agentId,
157
+ wipedEnvelopes,
158
+ wipedRaw,
159
+ wipedCoverageRecords,
160
+ wipedOrphanSearchDocs,
161
+ },
162
+ });
163
+ return { wipedEnvelopes, wipedRaw, wipedCoverageRecords, wipedOrphanSearchDocs };
164
+ }