@ouro.bot/cli 0.1.0-alpha.58 → 0.1.0-alpha.580

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 (404) 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 +3738 -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 +237 -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/background-operations.js +281 -0
  36. package/dist/heart/bundle-state.js +168 -0
  37. package/dist/heart/commitments.js +111 -0
  38. package/dist/heart/config-registry.js +322 -0
  39. package/dist/heart/config.js +114 -118
  40. package/dist/heart/core.js +909 -246
  41. package/dist/heart/cross-chat-delivery.js +3 -18
  42. package/dist/heart/daemon/agent-config-check.js +419 -0
  43. package/dist/heart/daemon/agent-discovery.js +102 -3
  44. package/dist/heart/daemon/agent-service.js +522 -0
  45. package/dist/heart/daemon/agentic-repair.js +547 -0
  46. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  47. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  48. package/dist/heart/daemon/cadence.js +70 -0
  49. package/dist/heart/daemon/cli-defaults.js +776 -0
  50. package/dist/heart/daemon/cli-exec.js +7559 -0
  51. package/dist/heart/daemon/cli-help.js +498 -0
  52. package/dist/heart/daemon/cli-parse.js +1592 -0
  53. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  54. package/dist/heart/daemon/cli-render.js +763 -0
  55. package/dist/heart/daemon/cli-types.js +8 -0
  56. package/dist/heart/daemon/connect-bay.js +323 -0
  57. package/dist/heart/daemon/daemon-cli.js +29 -1703
  58. package/dist/heart/daemon/daemon-entry.js +387 -2
  59. package/dist/heart/daemon/daemon-health.js +176 -0
  60. package/dist/heart/daemon/daemon-rollup.js +57 -0
  61. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  62. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  63. package/dist/heart/daemon/daemon.js +816 -71
  64. package/dist/heart/daemon/dns-workflow.js +394 -0
  65. package/dist/heart/daemon/doctor-types.js +8 -0
  66. package/dist/heart/daemon/doctor.js +826 -0
  67. package/dist/heart/daemon/health-monitor.js +122 -1
  68. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  69. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  70. package/dist/heart/daemon/http-health-probe.js +80 -0
  71. package/dist/heart/daemon/human-command-screens.js +234 -0
  72. package/dist/heart/daemon/human-readiness.js +114 -0
  73. package/dist/heart/daemon/inner-status.js +89 -0
  74. package/dist/heart/daemon/interactive-repair.js +394 -0
  75. package/dist/heart/daemon/launchd.js +37 -8
  76. package/dist/heart/daemon/log-tailer.js +82 -12
  77. package/dist/heart/daemon/logs-prune.js +110 -0
  78. package/dist/heart/daemon/mcp-canary.js +297 -0
  79. package/dist/heart/daemon/message-router.js +2 -2
  80. package/dist/heart/daemon/os-cron-deps.js +135 -0
  81. package/dist/heart/daemon/os-cron.js +14 -12
  82. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  83. package/dist/heart/daemon/ouro-entry.js +3 -1
  84. package/dist/heart/daemon/process-manager.js +375 -33
  85. package/dist/heart/daemon/provider-discovery.js +137 -0
  86. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  87. package/dist/heart/daemon/pulse.js +475 -0
  88. package/dist/heart/daemon/readiness-repair.js +365 -0
  89. package/dist/heart/daemon/run-hooks.js +2 -0
  90. package/dist/heart/daemon/runtime-logging.js +30 -6
  91. package/dist/heart/daemon/runtime-metadata.js +3 -31
  92. package/dist/heart/daemon/safe-mode.js +161 -0
  93. package/dist/heart/daemon/sense-manager.js +462 -38
  94. package/dist/heart/daemon/session-id-resolver.js +131 -0
  95. package/dist/heart/daemon/skill-management-installer.js +94 -0
  96. package/dist/heart/daemon/socket-client.js +158 -11
  97. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  98. package/dist/heart/daemon/startup-tui.js +330 -0
  99. package/dist/heart/daemon/task-scheduler.js +3 -25
  100. package/dist/heart/daemon/terminal-ui.js +499 -0
  101. package/dist/heart/daemon/thoughts.js +162 -17
  102. package/dist/heart/daemon/up-progress.js +366 -0
  103. package/dist/heart/daemon/vault-items.js +56 -0
  104. package/dist/heart/delegation.js +1 -1
  105. package/dist/heart/habits/habit-migration.js +189 -0
  106. package/dist/heart/habits/habit-parser.js +140 -0
  107. package/dist/heart/habits/habit-runtime-state.js +100 -0
  108. package/dist/heart/habits/habit-scheduler.js +372 -0
  109. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  110. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  111. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  112. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  113. package/dist/heart/identity.js +203 -57
  114. package/dist/heart/kept-notes.js +357 -0
  115. package/dist/heart/kicks.js +1 -1
  116. package/dist/heart/machine-identity.js +161 -0
  117. package/dist/heart/mail-import-discovery.js +353 -0
  118. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  119. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  120. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  121. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  122. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  123. package/dist/heart/mailbox/mailbox-http.js +99 -0
  124. package/dist/heart/mailbox/mailbox-read.js +31 -0
  125. package/dist/heart/mailbox/mailbox-types.js +27 -0
  126. package/dist/heart/mailbox/mailbox-view.js +195 -0
  127. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  128. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  129. package/dist/heart/mailbox/readers/mail.js +362 -0
  130. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  131. package/dist/heart/mailbox/readers/sessions.js +232 -0
  132. package/dist/heart/mailbox/readers/shared.js +111 -0
  133. package/dist/heart/mcp/mcp-server.js +656 -0
  134. package/dist/heart/migrate-config.js +100 -0
  135. package/dist/heart/model-capabilities.js +19 -0
  136. package/dist/heart/platform.js +81 -0
  137. package/dist/heart/provider-attempt.js +134 -0
  138. package/dist/heart/provider-binding-resolver.js +267 -0
  139. package/dist/heart/provider-credentials.js +425 -0
  140. package/dist/heart/provider-failover.js +301 -0
  141. package/dist/heart/provider-models.js +81 -0
  142. package/dist/heart/provider-ping.js +262 -0
  143. package/dist/heart/provider-readiness-cache.js +40 -0
  144. package/dist/heart/provider-visibility.js +188 -0
  145. package/dist/heart/providers/anthropic-token.js +131 -0
  146. package/dist/heart/providers/anthropic.js +139 -52
  147. package/dist/heart/providers/azure.js +97 -13
  148. package/dist/heart/providers/error-classification.js +127 -0
  149. package/dist/heart/providers/github-copilot.js +145 -0
  150. package/dist/heart/providers/minimax-vlm.js +189 -0
  151. package/dist/heart/providers/minimax.js +26 -8
  152. package/dist/heart/providers/openai-codex.js +55 -40
  153. package/dist/heart/runtime-capability-check.js +170 -0
  154. package/dist/heart/runtime-credentials.js +367 -0
  155. package/dist/heart/runtime-cwd.js +87 -0
  156. package/dist/heart/sense-truth.js +13 -4
  157. package/dist/heart/session-activity.js +43 -22
  158. package/dist/heart/session-events.js +1149 -0
  159. package/dist/heart/session-playback-cli-main.js +5 -0
  160. package/dist/heart/session-playback-cli.js +36 -0
  161. package/dist/heart/session-playback.js +231 -0
  162. package/dist/heart/session-stats-cli-main.js +5 -0
  163. package/dist/heart/session-stats.js +182 -0
  164. package/dist/heart/session-transcript.js +243 -0
  165. package/dist/heart/start-of-turn-packet.js +345 -0
  166. package/dist/heart/streaming.js +44 -27
  167. package/dist/heart/sync-classification.js +176 -0
  168. package/dist/heart/sync.js +449 -0
  169. package/dist/heart/target-resolution.js +9 -5
  170. package/dist/heart/tempo.js +93 -0
  171. package/dist/heart/temporal-view.js +41 -0
  172. package/dist/heart/timeouts.js +101 -0
  173. package/dist/heart/tool-activity-callbacks.js +59 -0
  174. package/dist/heart/tool-description.js +143 -0
  175. package/dist/heart/tool-friction.js +55 -0
  176. package/dist/heart/tool-loop.js +200 -0
  177. package/dist/heart/turn-context.js +421 -0
  178. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  179. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  180. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  181. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  182. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  183. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  184. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  185. package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
  186. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  187. package/dist/mailbox-ui/index.html +15 -0
  188. package/dist/mailroom/attention.js +167 -0
  189. package/dist/mailroom/autonomy.js +209 -0
  190. package/dist/mailroom/blob-store.js +674 -0
  191. package/dist/mailroom/body-cache.js +61 -0
  192. package/dist/mailroom/core.js +720 -0
  193. package/dist/mailroom/entry.js +160 -0
  194. package/dist/mailroom/file-store.js +430 -0
  195. package/dist/mailroom/mbox-import.js +383 -0
  196. package/dist/mailroom/outbound.js +380 -0
  197. package/dist/mailroom/policy.js +263 -0
  198. package/dist/mailroom/reader.js +233 -0
  199. package/dist/mailroom/search-cache.js +256 -0
  200. package/dist/mailroom/search-relevance.js +319 -0
  201. package/dist/mailroom/smtp-ingress.js +176 -0
  202. package/dist/mailroom/source-state.js +176 -0
  203. package/dist/mailroom/thread.js +109 -0
  204. package/dist/mailroom/travel-extract.js +89 -0
  205. package/dist/mind/bundle-manifest.js +7 -1
  206. package/dist/mind/context.js +165 -101
  207. package/dist/mind/diary-integrity.js +60 -0
  208. package/dist/mind/{memory.js → diary.js} +62 -75
  209. package/dist/mind/embedding-provider.js +60 -0
  210. package/dist/mind/file-state.js +179 -0
  211. package/dist/mind/friends/channel.js +39 -0
  212. package/dist/mind/friends/resolver.js +54 -2
  213. package/dist/mind/friends/store-file.js +39 -3
  214. package/dist/mind/friends/types.js +2 -2
  215. package/dist/mind/journal-index.js +161 -0
  216. package/dist/mind/note-search.js +268 -0
  217. package/dist/mind/obligation-steering.js +221 -0
  218. package/dist/mind/pending.js +4 -0
  219. package/dist/mind/prompt-refresh.js +3 -2
  220. package/dist/mind/prompt.js +1039 -135
  221. package/dist/mind/provenance-trust.js +26 -0
  222. package/dist/mind/scrutiny.js +173 -0
  223. package/dist/nerves/cli-logging.js +7 -1
  224. package/dist/nerves/coverage/audit-rules.js +15 -6
  225. package/dist/nerves/coverage/audit.js +28 -2
  226. package/dist/nerves/coverage/cli.js +1 -1
  227. package/dist/nerves/coverage/contract.js +5 -5
  228. package/dist/nerves/coverage/file-completeness.js +129 -5
  229. package/dist/nerves/coverage/run-artifacts.js +1 -1
  230. package/dist/nerves/event-buffer.js +111 -0
  231. package/dist/nerves/index.js +224 -4
  232. package/dist/nerves/observation.js +20 -0
  233. package/dist/nerves/redact.js +79 -0
  234. package/dist/nerves/review/cli-main.js +5 -0
  235. package/dist/nerves/review/cli.js +156 -0
  236. package/dist/nerves/review/core.js +152 -0
  237. package/dist/nerves/runtime.js +5 -1
  238. package/dist/repertoire/ado-client.js +15 -56
  239. package/dist/repertoire/ado-semantic.js +11 -10
  240. package/dist/repertoire/api-client.js +97 -0
  241. package/dist/repertoire/bitwarden-store.js +997 -0
  242. package/dist/repertoire/bundle-templates.js +72 -0
  243. package/dist/repertoire/bw-installer.js +180 -0
  244. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  245. package/dist/repertoire/coding/context-pack.js +330 -0
  246. package/dist/repertoire/coding/feedback.js +197 -30
  247. package/dist/repertoire/coding/manager.js +158 -9
  248. package/dist/repertoire/coding/spawner.js +55 -9
  249. package/dist/repertoire/coding/tools.js +170 -7
  250. package/dist/repertoire/commerce-errors.js +109 -0
  251. package/dist/repertoire/commerce-self-test.js +156 -0
  252. package/dist/repertoire/credential-access.js +178 -0
  253. package/dist/repertoire/duffel-client.js +185 -0
  254. package/dist/repertoire/github-client.js +14 -55
  255. package/dist/repertoire/graph-client.js +11 -52
  256. package/dist/repertoire/guardrails.js +396 -0
  257. package/dist/repertoire/mcp-client.js +295 -0
  258. package/dist/repertoire/mcp-manager.js +362 -0
  259. package/dist/repertoire/mcp-tools.js +63 -0
  260. package/dist/repertoire/shell-sessions.js +133 -0
  261. package/dist/repertoire/skills.js +15 -24
  262. package/dist/repertoire/stripe-client.js +131 -0
  263. package/dist/repertoire/tasks/board.js +31 -5
  264. package/dist/repertoire/tasks/fix.js +182 -0
  265. package/dist/repertoire/tasks/index.js +16 -4
  266. package/dist/repertoire/tasks/lifecycle.js +2 -2
  267. package/dist/repertoire/tasks/parser.js +3 -2
  268. package/dist/repertoire/tasks/scanner.js +194 -37
  269. package/dist/repertoire/tasks/transitions.js +16 -78
  270. package/dist/repertoire/tool-results.js +29 -0
  271. package/dist/repertoire/tools-attachments.js +317 -0
  272. package/dist/repertoire/tools-base.js +47 -1075
  273. package/dist/repertoire/tools-bluebubbles.js +1 -0
  274. package/dist/repertoire/tools-bridge.js +142 -0
  275. package/dist/repertoire/tools-bundle.js +984 -0
  276. package/dist/repertoire/tools-config.js +185 -0
  277. package/dist/repertoire/tools-continuity.js +248 -0
  278. package/dist/repertoire/tools-credential.js +381 -0
  279. package/dist/repertoire/tools-files.js +342 -0
  280. package/dist/repertoire/tools-flight.js +224 -0
  281. package/dist/repertoire/tools-flow.js +119 -0
  282. package/dist/repertoire/tools-github.js +1 -7
  283. package/dist/repertoire/tools-mail.js +1857 -0
  284. package/dist/repertoire/tools-notes.js +421 -0
  285. package/dist/repertoire/tools-session.js +809 -0
  286. package/dist/repertoire/tools-shell.js +120 -0
  287. package/dist/repertoire/tools-stripe.js +180 -0
  288. package/dist/repertoire/tools-surface.js +345 -0
  289. package/dist/repertoire/tools-teams.js +9 -39
  290. package/dist/repertoire/tools-travel.js +125 -0
  291. package/dist/repertoire/tools-trip.js +604 -0
  292. package/dist/repertoire/tools-user-profile.js +144 -0
  293. package/dist/repertoire/tools-vault.js +40 -0
  294. package/dist/repertoire/tools-voice.js +144 -0
  295. package/dist/repertoire/tools.js +115 -103
  296. package/dist/repertoire/travel-api-client.js +360 -0
  297. package/dist/repertoire/user-profile.js +131 -0
  298. package/dist/repertoire/vault-setup.js +246 -0
  299. package/dist/repertoire/vault-unlock.js +594 -0
  300. package/dist/scripts/claude-code-hook.js +41 -0
  301. package/dist/scripts/claude-code-stop-hook.js +47 -0
  302. package/dist/senses/attention-queue.js +116 -0
  303. package/dist/senses/bluebubbles/active-turns.js +216 -0
  304. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  305. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  306. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  307. package/dist/senses/bluebubbles/entry.js +77 -0
  308. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  309. package/dist/senses/bluebubbles/index.js +2420 -0
  310. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  311. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  312. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  313. package/dist/senses/bluebubbles/processed-log.js +133 -0
  314. package/dist/senses/bluebubbles/replay.js +137 -0
  315. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  316. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  317. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +100 -0
  337. package/dist/senses/cli.js +516 -204
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +654 -181
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +392 -0
  347. package/dist/senses/surface-tool.js +70 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/senses/voice/audio-playback.js +237 -0
  352. package/dist/senses/voice/audio-routing.js +119 -0
  353. package/dist/senses/voice/elevenlabs.js +202 -0
  354. package/dist/senses/voice/golden-path.js +116 -0
  355. package/dist/senses/voice/index.js +28 -0
  356. package/dist/senses/voice/meeting.js +113 -0
  357. package/dist/senses/voice/outbound.js +190 -0
  358. package/dist/senses/voice/phone.js +33 -0
  359. package/dist/senses/voice/playback.js +139 -0
  360. package/dist/senses/voice/transcript.js +70 -0
  361. package/dist/senses/voice/turn.js +191 -0
  362. package/dist/senses/voice/twilio-phone-runtime.js +755 -0
  363. package/dist/senses/voice/twilio-phone.js +4484 -0
  364. package/dist/senses/voice/types.js +2 -0
  365. package/dist/senses/voice/whisper.js +161 -0
  366. package/dist/senses/voice-entry.js +81 -0
  367. package/dist/senses/voice-twilio-entry.js +87 -0
  368. package/dist/trips/core.js +138 -0
  369. package/dist/trips/store.js +146 -0
  370. package/package.json +40 -7
  371. package/skills/agent-commerce.md +106 -0
  372. package/skills/browser-navigation.md +117 -0
  373. package/skills/commerce-setup-guide.md +116 -0
  374. package/skills/commerce-setup.md +84 -0
  375. package/skills/configure-dev-tools.md +99 -0
  376. package/skills/travel-planning.md +138 -0
  377. package/dist/heart/daemon/auth-flow.js +0 -351
  378. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  379. package/dist/heart/daemon/subagent-installer.js +0 -166
  380. package/dist/heart/session-recall.js +0 -116
  381. package/dist/mind/associative-recall.js +0 -209
  382. package/dist/senses/bluebubbles-entry.js +0 -13
  383. package/dist/senses/bluebubbles.js +0 -1177
  384. package/dist/senses/debug-activity.js +0 -148
  385. package/subagents/README.md +0 -86
  386. package/subagents/work-doer.md +0 -237
  387. package/subagents/work-merger.md +0 -618
  388. package/subagents/work-planner.md +0 -390
  389. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  390. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  391. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  392. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  393. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  394. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  395. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  396. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  397. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  398. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  399. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  400. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  401. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  402. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  403. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  404. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runVoiceGoldenPath = runVoiceGoldenPath;
4
+ const runtime_1 = require("../../nerves/runtime");
5
+ const audio_routing_1 = require("./audio-routing");
6
+ const meeting_1 = require("./meeting");
7
+ const playback_1 = require("./playback");
8
+ const turn_1 = require("./turn");
9
+ const defaultVoiceMeetingJoiner = {
10
+ async join(request) {
11
+ const result = {
12
+ status: "manual_required",
13
+ detail: `Open ${request.meeting.redactedUrl} in a browser profile whose meeting audio is routed through Multi-Output Device.`,
14
+ };
15
+ (0, runtime_1.emitNervesEvent)({
16
+ component: "senses",
17
+ event: "senses.voice_meeting_join_manual_required",
18
+ message: "voice meeting join requires browser handoff",
19
+ meta: {
20
+ provider: request.meeting.provider,
21
+ sessionKey: request.meeting.sessionKey,
22
+ routingStatus: request.audioRouting.status,
23
+ },
24
+ });
25
+ return result;
26
+ },
27
+ };
28
+ function defaultUtteranceId() {
29
+ return `voice-${Date.now().toString(36)}`;
30
+ }
31
+ function playbackSkipped() {
32
+ (0, runtime_1.emitNervesEvent)({
33
+ component: "senses",
34
+ event: "senses.voice_golden_path_playback_skipped",
35
+ message: "voice golden path skipped playback because TTS failed",
36
+ meta: { reason: "tts_failed" },
37
+ });
38
+ return {
39
+ status: "skipped",
40
+ reason: "tts_failed",
41
+ playbackAttempted: false,
42
+ };
43
+ }
44
+ async function runVoiceGoldenPath(options) {
45
+ (0, runtime_1.emitNervesEvent)({
46
+ component: "senses",
47
+ event: "senses.voice_golden_path_start",
48
+ message: "starting voice golden path",
49
+ meta: { agentName: options.agentName, friendId: options.friendId },
50
+ });
51
+ try {
52
+ const meeting = (0, meeting_1.parseVoiceMeetingUrl)(options.meetingUrl);
53
+ const audioRouting = await (options.inspectAudioRouting ?? audio_routing_1.inspectVoiceAudioRouting)();
54
+ const joiner = options.meetingJoiner ?? defaultVoiceMeetingJoiner;
55
+ const join = await joiner.join({ meeting, audioRouting });
56
+ const utteranceId = options.utteranceId ?? defaultUtteranceId();
57
+ const transcript = await options.transcriber.transcribe({
58
+ utteranceId,
59
+ audioPath: options.audioPath,
60
+ language: options.language,
61
+ });
62
+ const sessionKey = options.sessionKey ?? meeting.sessionKey;
63
+ const runSenseTurn = options.runSenseTurn;
64
+ const turn = await (0, turn_1.runVoiceLoopbackTurn)({
65
+ agentName: options.agentName,
66
+ friendId: options.friendId,
67
+ sessionKey,
68
+ transcript,
69
+ tts: options.tts,
70
+ runSenseTurn,
71
+ });
72
+ const writePlaybackArtifact = options.writePlaybackArtifact ?? playback_1.writeVoicePlaybackArtifact;
73
+ const playback = turn.tts.status === "delivered"
74
+ ? await writePlaybackArtifact({
75
+ utteranceId,
76
+ delivery: turn.tts,
77
+ outputDir: options.outputDir,
78
+ playAudio: options.playAudio ?? false,
79
+ })
80
+ : playbackSkipped();
81
+ const result = {
82
+ meeting,
83
+ audioRouting,
84
+ join,
85
+ transcript,
86
+ responseText: turn.responseText,
87
+ ponderDeferred: turn.ponderDeferred,
88
+ tts: turn.tts,
89
+ playback,
90
+ sessionKey,
91
+ };
92
+ (0, runtime_1.emitNervesEvent)({
93
+ component: "senses",
94
+ event: "senses.voice_golden_path_end",
95
+ message: "finished voice golden path",
96
+ meta: {
97
+ sessionKey,
98
+ joinStatus: join.status,
99
+ ttsStatus: turn.tts.status,
100
+ playbackStatus: playback.status,
101
+ },
102
+ });
103
+ return result;
104
+ }
105
+ catch (error) {
106
+ const message = error instanceof Error ? error.message : String(error);
107
+ (0, runtime_1.emitNervesEvent)({
108
+ level: "error",
109
+ component: "senses",
110
+ event: "senses.voice_golden_path_error",
111
+ message: "voice golden path failed",
112
+ meta: { error: message },
113
+ });
114
+ throw new Error(`voice golden path failed: ${message}`);
115
+ }
116
+ }
@@ -0,0 +1,28 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /* v8 ignore file -- barrel exports only; executable voice helpers are covered directly. @preserve */
18
+ __exportStar(require("./types"), exports);
19
+ __exportStar(require("./transcript"), exports);
20
+ __exportStar(require("./whisper"), exports);
21
+ __exportStar(require("./elevenlabs"), exports);
22
+ __exportStar(require("./turn"), exports);
23
+ __exportStar(require("./meeting"), exports);
24
+ __exportStar(require("./audio-routing"), exports);
25
+ __exportStar(require("./playback"), exports);
26
+ __exportStar(require("./golden-path"), exports);
27
+ __exportStar(require("./twilio-phone"), exports);
28
+ __exportStar(require("./twilio-phone-runtime"), exports);
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.redactVoiceMeetingUrl = redactVoiceMeetingUrl;
4
+ exports.parseVoiceMeetingUrl = parseVoiceMeetingUrl;
5
+ const crypto_1 = require("crypto");
6
+ const runtime_1 = require("../../nerves/runtime");
7
+ function isRiversideHost(host) {
8
+ return host === "riverside.fm" || host === "riverside.com";
9
+ }
10
+ function stableMeetingHash(provider, url) {
11
+ return (0, crypto_1.createHash)("sha256")
12
+ .update(`${provider}:${url.protocol}//${url.host}${url.pathname}`)
13
+ .digest("hex")
14
+ .slice(0, 12);
15
+ }
16
+ function redactPath(pathname) {
17
+ const parts = pathname.split("/").filter(Boolean);
18
+ if (parts.length === 0)
19
+ return "/";
20
+ if (parts.length === 1)
21
+ return "/:redacted";
22
+ return `/${parts[0]}/:redacted`;
23
+ }
24
+ function redactVoiceMeetingUrl(input) {
25
+ try {
26
+ const url = new URL(input);
27
+ return `${url.protocol}//${url.host}${redactPath(url.pathname)}`;
28
+ }
29
+ catch {
30
+ return ":invalid";
31
+ }
32
+ }
33
+ function parseVoiceMeetingUrl(input) {
34
+ const trimmed = input.trim();
35
+ if (!trimmed) {
36
+ (0, runtime_1.emitNervesEvent)({
37
+ level: "error",
38
+ component: "senses",
39
+ event: "senses.voice_meeting_rejected",
40
+ message: "voice meeting URL is empty",
41
+ meta: { reason: "empty" },
42
+ });
43
+ throw new Error("voice meeting URL is empty");
44
+ }
45
+ let url;
46
+ try {
47
+ url = new URL(trimmed);
48
+ }
49
+ catch (error) {
50
+ (0, runtime_1.emitNervesEvent)({
51
+ level: "error",
52
+ component: "senses",
53
+ event: "senses.voice_meeting_rejected",
54
+ message: "voice meeting URL is invalid",
55
+ meta: { reason: "invalid_url" },
56
+ });
57
+ throw new Error("voice meeting URL is invalid");
58
+ }
59
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
60
+ (0, runtime_1.emitNervesEvent)({
61
+ level: "error",
62
+ component: "senses",
63
+ event: "senses.voice_meeting_rejected",
64
+ message: "voice meeting URL must be http or https",
65
+ meta: { protocol: url.protocol },
66
+ });
67
+ throw new Error("voice meeting URL must be http or https");
68
+ }
69
+ const host = url.hostname.toLowerCase();
70
+ const provider = isRiversideHost(host) ? "riverside" : "generic";
71
+ if (provider === "riverside" && !url.pathname.startsWith("/studio/")) {
72
+ (0, runtime_1.emitNervesEvent)({
73
+ level: "error",
74
+ component: "senses",
75
+ event: "senses.voice_meeting_rejected",
76
+ message: "Riverside voice meeting URLs must use /studio/",
77
+ meta: { host, redactedUrl: redactVoiceMeetingUrl(trimmed) },
78
+ });
79
+ throw new Error("Riverside voice meeting URLs must use /studio/");
80
+ }
81
+ if (provider === "generic" && url.protocol !== "https:") {
82
+ (0, runtime_1.emitNervesEvent)({
83
+ level: "error",
84
+ component: "senses",
85
+ event: "senses.voice_meeting_rejected",
86
+ message: "generic voice meeting URLs must use https",
87
+ meta: { host, redactedUrl: redactVoiceMeetingUrl(trimmed) },
88
+ });
89
+ throw new Error("generic voice meeting URLs must use https");
90
+ }
91
+ const hash = stableMeetingHash(provider, url);
92
+ const meeting = {
93
+ originalUrl: trimmed,
94
+ provider,
95
+ host,
96
+ pathname: url.pathname,
97
+ redactedUrl: redactVoiceMeetingUrl(trimmed),
98
+ sessionKey: `voice-${provider}-${hash}`,
99
+ requiresBrowserJoin: true,
100
+ };
101
+ (0, runtime_1.emitNervesEvent)({
102
+ component: "senses",
103
+ event: "senses.voice_meeting_parsed",
104
+ message: "voice meeting URL parsed",
105
+ meta: {
106
+ provider: meeting.provider,
107
+ host: meeting.host,
108
+ sessionKey: meeting.sessionKey,
109
+ redactedUrl: meeting.redactedUrl,
110
+ },
111
+ });
112
+ return meeting;
113
+ }
@@ -0,0 +1,190 @@
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.readVoiceOutboundFriendRecordById = readVoiceOutboundFriendRecordById;
37
+ exports.findVoiceOutboundFriendRecord = findVoiceOutboundFriendRecord;
38
+ exports.voiceOutboundPhoneNumberForFriend = voiceOutboundPhoneNumberForFriend;
39
+ exports.placeTrustedFriendVoiceOutboundCall = placeTrustedFriendVoiceOutboundCall;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const types_1 = require("../../mind/friends/types");
43
+ const runtime_1 = require("../../nerves/runtime");
44
+ const phone_1 = require("./phone");
45
+ function readVoiceOutboundFriendRecordById(friendsDir, friendId) {
46
+ const recordPath = path.join(friendsDir, `${friendId}.json`);
47
+ if (!fs.existsSync(recordPath))
48
+ return null;
49
+ try {
50
+ return JSON.parse(fs.readFileSync(recordPath, "utf-8"));
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ function externalIdMatches(externalId, wanted, wantedPhone) {
57
+ const normalized = externalId.trim().toLowerCase();
58
+ /* v8 ignore next -- exact external-id aliases are supported for non-phone providers; phone aliases are the production voice path @preserve */
59
+ if (normalized === wanted)
60
+ return true;
61
+ const phone = (0, phone_1.normalizeTwilioE164PhoneNumber)(externalId);
62
+ return Boolean(wantedPhone && phone === wantedPhone);
63
+ }
64
+ function findVoiceOutboundFriendRecord(friendsDir, friendId) {
65
+ const byId = readVoiceOutboundFriendRecordById(friendsDir, friendId);
66
+ if (byId)
67
+ return byId;
68
+ const normalized = friendId.trim().toLowerCase();
69
+ if (!normalized)
70
+ return null;
71
+ const normalizedPhone = (0, phone_1.normalizeTwilioE164PhoneNumber)(friendId);
72
+ try {
73
+ const records = fs.readdirSync(friendsDir)
74
+ .filter((file) => file.endsWith(".json"))
75
+ .map((file) => {
76
+ try {
77
+ return JSON.parse(fs.readFileSync(path.join(friendsDir, file), "utf-8"));
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ })
83
+ .filter((record) => Boolean(record));
84
+ return records.find((record) => record.id === friendId
85
+ || record.name?.toLowerCase() === normalized
86
+ || record.externalIds?.some((externalId) => externalIdMatches(externalId.externalId, normalized, normalizedPhone))) ?? records.find((record) => record.name?.toLowerCase().startsWith(normalized)) ?? null;
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ function voiceOutboundPhoneNumberForFriend(friend, explicitPhoneNumber) {
93
+ const explicit = (0, phone_1.normalizeTwilioE164PhoneNumber)(explicitPhoneNumber);
94
+ if (explicit)
95
+ return explicit;
96
+ for (const externalId of friend?.externalIds ?? []) {
97
+ /* v8 ignore next -- voice outbound only consumes iMessage phone handles today @preserve */
98
+ if (externalId.provider !== "imessage-handle")
99
+ continue;
100
+ const phoneNumber = (0, phone_1.normalizeTwilioE164PhoneNumber)(externalId.externalId);
101
+ /* v8 ignore next -- malformed iMessage handles are covered by missing-number blocking at the caller boundary @preserve */
102
+ if (phoneNumber)
103
+ return phoneNumber;
104
+ }
105
+ return undefined;
106
+ }
107
+ async function placeTrustedFriendVoiceOutboundCall(request) {
108
+ (0, runtime_1.emitNervesEvent)({
109
+ component: "senses",
110
+ event: "senses.voice_outbound_call_start",
111
+ message: "checking trusted friend outbound voice call request",
112
+ meta: { agentName: request.agentName, friendId: request.friendId },
113
+ });
114
+ const friendsDir = path.join(request.agentRoot, "friends");
115
+ const friend = findVoiceOutboundFriendRecord(friendsDir, request.friendId);
116
+ if (!friend) {
117
+ (0, runtime_1.emitNervesEvent)({
118
+ component: "senses",
119
+ event: "senses.voice_outbound_call_blocked",
120
+ message: "blocked outbound voice call request",
121
+ meta: { agentName: request.agentName, friendId: request.friendId, reason: "unknown_friend" },
122
+ });
123
+ return { status: "blocked", detail: "voice call requires a known friend record" };
124
+ }
125
+ if (!(0, types_1.isTrustedLevel)(friend.trustLevel)) {
126
+ (0, runtime_1.emitNervesEvent)({
127
+ component: "senses",
128
+ event: "senses.voice_outbound_call_blocked",
129
+ message: "blocked outbound voice call request",
130
+ meta: { agentName: request.agentName, friendId: friend.id, reason: "untrusted_friend" },
131
+ });
132
+ return { status: "blocked", detail: "voice calls are limited to trusted friends" };
133
+ }
134
+ const phoneNumber = voiceOutboundPhoneNumberForFriend(friend, request.phoneNumber);
135
+ if (!phoneNumber) {
136
+ (0, runtime_1.emitNervesEvent)({
137
+ component: "senses",
138
+ event: "senses.voice_outbound_call_blocked",
139
+ message: "blocked outbound voice call request",
140
+ meta: { agentName: request.agentName, friendId: friend.id, reason: "missing_phone_number" },
141
+ });
142
+ return { status: "blocked", detail: "no phone number is available for voice call" };
143
+ }
144
+ try {
145
+ const { placeConfiguredTwilioPhoneCall } = await Promise.resolve().then(() => __importStar(require("./twilio-phone-runtime")));
146
+ const call = await placeConfiguredTwilioPhoneCall({
147
+ agentName: request.agentName,
148
+ friendId: friend.id,
149
+ to: phoneNumber,
150
+ reason: request.reason,
151
+ ...(request.initialAudio ? { initialAudio: request.initialAudio } : {}),
152
+ });
153
+ (0, runtime_1.emitNervesEvent)({
154
+ component: "senses",
155
+ event: "senses.voice_outbound_call_placed",
156
+ message: "placed outbound voice call request",
157
+ meta: {
158
+ agentName: request.agentName,
159
+ friendId: friend.id,
160
+ outboundId: call.outboundId.replace(/[^A-Za-z0-9._-]+/g, "-"),
161
+ callSid: call.callSid?.replace(/[^A-Za-z0-9._-]+/g, "-") ?? "unknown",
162
+ status: call.status ?? "unknown",
163
+ },
164
+ });
165
+ return {
166
+ status: "placed",
167
+ detail: `voice call initiated${call.status ? ` (${call.status})` : ""}`,
168
+ friendId: friend.id,
169
+ phoneNumber,
170
+ outboundId: call.outboundId,
171
+ ...(call.callSid ? { callSid: call.callSid } : {}),
172
+ ...(call.status ? { callStatus: call.status } : {}),
173
+ };
174
+ }
175
+ catch (error) {
176
+ (0, runtime_1.emitNervesEvent)({
177
+ level: "error",
178
+ component: "senses",
179
+ event: "senses.voice_outbound_call_failed",
180
+ message: "failed outbound voice call request",
181
+ /* v8 ignore next -- dynamic import/runtime failures arrive as Error objects in supported Node runtimes @preserve */
182
+ meta: { agentName: request.agentName, friendId: friend.id, error: error instanceof Error ? error.message : String(error) },
183
+ });
184
+ return {
185
+ status: "failed",
186
+ /* v8 ignore next -- dynamic import/runtime failures arrive as Error objects in supported Node runtimes @preserve */
187
+ detail: error instanceof Error ? error.message : String(error),
188
+ };
189
+ }
190
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeTwilioE164PhoneNumber = normalizeTwilioE164PhoneNumber;
4
+ const runtime_1 = require("../../nerves/runtime");
5
+ function normalizeTwilioE164PhoneNumber(value) {
6
+ const raw = value?.trim();
7
+ if (!raw)
8
+ return undefined;
9
+ if (raw.toLowerCase().startsWith("group:")) {
10
+ (0, runtime_1.emitNervesEvent)({
11
+ component: "senses",
12
+ event: "senses.voice_phone_number_rejected",
13
+ message: "voice phone number candidate rejected",
14
+ meta: { reason: "group_handle" },
15
+ });
16
+ return undefined;
17
+ }
18
+ const cleaned = raw.replace(/[^\d+]+/g, "");
19
+ if (/^\+[1-9]\d{6,14}$/.test(cleaned))
20
+ return cleaned;
21
+ const digits = cleaned.replace(/\D+/g, "");
22
+ if (/^1\d{10}$/.test(digits))
23
+ return `+${digits}`;
24
+ if (/^\d{10}$/.test(digits))
25
+ return `+1${digits}`;
26
+ (0, runtime_1.emitNervesEvent)({
27
+ component: "senses",
28
+ event: "senses.voice_phone_number_rejected",
29
+ message: "voice phone number candidate rejected",
30
+ meta: { reason: "invalid_e164" },
31
+ });
32
+ return undefined;
33
+ }
@@ -0,0 +1,139 @@
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.writeVoicePlaybackArtifact = writeVoicePlaybackArtifact;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const runtime_1 = require("../../nerves/runtime");
40
+ const audio_routing_1 = require("./audio-routing");
41
+ function audioExtension(mimeType) {
42
+ if (mimeType === "audio/mpeg")
43
+ return "mp3";
44
+ if (mimeType === "audio/wav" || mimeType === "audio/x-wav")
45
+ return "wav";
46
+ if (mimeType.startsWith("audio/pcm"))
47
+ return "pcm";
48
+ return "audio";
49
+ }
50
+ function safeFileStem(input) {
51
+ const stem = input
52
+ .trim()
53
+ .toLowerCase()
54
+ .replace(/[^a-z0-9]+/g, "-")
55
+ .replace(/^-+|-+$/g, "");
56
+ return stem || "utterance";
57
+ }
58
+ function commandFailureMessage(exitCode, result) {
59
+ const stderr = result.stderr?.trim();
60
+ if (stderr)
61
+ return `exit ${exitCode}: ${stderr}`;
62
+ const stdout = result.stdout?.trim();
63
+ if (stdout)
64
+ return `exit ${exitCode}: ${stdout}`;
65
+ return `exit ${exitCode}`;
66
+ }
67
+ async function writeVoicePlaybackArtifact(request) {
68
+ const mkdir = request.mkdir ?? fs.mkdir;
69
+ const writeFile = request.writeFile ?? fs.writeFile;
70
+ const commandRunner = request.commandRunner ?? (0, audio_routing_1.createNodeVoiceCommandRunner)();
71
+ const timeoutMs = request.timeoutMs ?? 30_000;
72
+ const playbackCommandPath = request.playbackCommandPath ?? "afplay";
73
+ const audioPath = path.join(request.outputDir, `${safeFileStem(request.utteranceId)}.${audioExtension(request.delivery.mimeType)}`);
74
+ await mkdir(request.outputDir, { recursive: true });
75
+ await writeFile(audioPath, request.delivery.audio);
76
+ (0, runtime_1.emitNervesEvent)({
77
+ component: "senses",
78
+ event: "senses.voice_playback_artifact_written",
79
+ message: "voice playback artifact written",
80
+ meta: {
81
+ utteranceId: request.utteranceId,
82
+ audioPath,
83
+ byteLength: request.delivery.byteLength,
84
+ mimeType: request.delivery.mimeType,
85
+ },
86
+ });
87
+ if (request.playAudio !== true) {
88
+ return {
89
+ status: "written",
90
+ audioPath,
91
+ byteLength: request.delivery.byteLength,
92
+ mimeType: request.delivery.mimeType,
93
+ playbackAttempted: false,
94
+ };
95
+ }
96
+ (0, runtime_1.emitNervesEvent)({
97
+ component: "senses",
98
+ event: "senses.voice_playback_start",
99
+ message: "starting voice playback",
100
+ meta: { utteranceId: request.utteranceId, audioPath, playbackCommandPath },
101
+ });
102
+ try {
103
+ const result = await commandRunner(playbackCommandPath, [audioPath], { timeoutMs });
104
+ if (typeof result.exitCode === "number" && result.exitCode !== 0) {
105
+ throw new Error(commandFailureMessage(result.exitCode, result));
106
+ }
107
+ (0, runtime_1.emitNervesEvent)({
108
+ component: "senses",
109
+ event: "senses.voice_playback_end",
110
+ message: "finished voice playback",
111
+ meta: { utteranceId: request.utteranceId, audioPath },
112
+ });
113
+ return {
114
+ status: "played",
115
+ audioPath,
116
+ byteLength: request.delivery.byteLength,
117
+ mimeType: request.delivery.mimeType,
118
+ playbackAttempted: true,
119
+ };
120
+ }
121
+ catch (error) {
122
+ const message = error instanceof Error ? error.message : String(error);
123
+ (0, runtime_1.emitNervesEvent)({
124
+ level: "error",
125
+ component: "senses",
126
+ event: "senses.voice_playback_error",
127
+ message: "voice playback failed",
128
+ meta: { utteranceId: request.utteranceId, audioPath, error: message },
129
+ });
130
+ return {
131
+ status: "failed",
132
+ audioPath,
133
+ byteLength: request.delivery.byteLength,
134
+ mimeType: request.delivery.mimeType,
135
+ playbackAttempted: true,
136
+ error: message,
137
+ };
138
+ }
139
+ }