@ouro.bot/cli 0.1.0-alpha.8 → 0.1.0-alpha.800

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 (624) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -176
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/SerpentGuide.ouro/agent.json +83 -0
  11. package/SerpentGuide.ouro/psyche/SOUL.md +25 -0
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +2 -2
  13. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  14. package/assets/bluebubbles-host +264 -0
  15. package/assets/ouroboros.png +0 -0
  16. package/changelog.json +5563 -0
  17. package/deploy/unraid/Dockerfile +48 -0
  18. package/deploy/unraid/README.txt +3012 -0
  19. package/deploy/unraid/audit-container-spec.sh +4 -0
  20. package/deploy/unraid/container-runtime.json +1 -0
  21. package/deploy/unraid/docker-man-template-transaction.mjs +526 -0
  22. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  23. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  24. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  25. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  26. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  27. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  28. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  29. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  30. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  31. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  32. package/deploy/unraid/sanctuary-deployment-target.mjs +709 -0
  33. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  34. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2030 -0
  35. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  36. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  37. package/deploy/unraid/sanctuary.ouro/agent.json +24 -0
  38. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  39. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  40. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  41. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  42. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  43. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +11 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +11 -0
  47. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  48. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +23 -0
  49. package/deploy/unraid/sanctuary.xml +27 -0
  50. package/dist/a2a/card.js +57 -0
  51. package/dist/a2a/client.js +180 -0
  52. package/dist/a2a/config.js +50 -0
  53. package/dist/a2a/delegation-stores.js +56 -0
  54. package/dist/a2a/did-resolution.js +93 -0
  55. package/dist/a2a/identity.js +170 -0
  56. package/dist/a2a/inbound-share.js +107 -0
  57. package/dist/a2a/mission-result-wire.js +196 -0
  58. package/dist/a2a/onboarding.js +115 -0
  59. package/dist/a2a/pin-store.js +132 -0
  60. package/dist/a2a/seen-ledger.js +120 -0
  61. package/dist/a2a/server.js +604 -0
  62. package/dist/a2a/task-store.js +69 -0
  63. package/dist/a2a/transport.js +45 -0
  64. package/dist/a2a/types.js +3 -0
  65. package/dist/arc/attention-types.js +8 -0
  66. package/dist/arc/cares.js +360 -0
  67. package/dist/arc/episodes.js +118 -0
  68. package/dist/arc/evolution.js +490 -0
  69. package/dist/arc/flight-recorder.js +1034 -0
  70. package/dist/arc/intentions.js +134 -0
  71. package/dist/arc/json-store.js +117 -0
  72. package/dist/arc/obligations.js +386 -0
  73. package/dist/arc/packets.js +336 -0
  74. package/dist/arc/presence.js +185 -0
  75. package/dist/arc/task-lifecycle.js +57 -0
  76. package/dist/commerce/store.js +755 -0
  77. package/dist/commerce/types.js +3 -0
  78. package/dist/heart/active-work.js +1009 -0
  79. package/dist/heart/agent-entry.js +252 -3
  80. package/dist/heart/approval-files.js +113 -0
  81. package/dist/heart/approval-store.js +950 -0
  82. package/dist/heart/attachments/image-normalize.js +194 -0
  83. package/dist/heart/attachments/materialize.js +97 -0
  84. package/dist/heart/attachments/originals.js +88 -0
  85. package/dist/heart/attachments/render.js +29 -0
  86. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  87. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  88. package/dist/heart/attachments/sources/index.js +18 -0
  89. package/dist/heart/attachments/sources/telegram.js +71 -0
  90. package/dist/heart/attachments/store.js +132 -0
  91. package/dist/heart/attachments/types.js +93 -0
  92. package/dist/heart/auth/auth-flow.js +495 -0
  93. package/dist/heart/autonomy-budget.js +478 -0
  94. package/dist/heart/awaiting/await-alert.js +148 -0
  95. package/dist/heart/awaiting/await-expiry.js +143 -0
  96. package/dist/heart/awaiting/await-loader.js +91 -0
  97. package/dist/heart/awaiting/await-parser.js +149 -0
  98. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  99. package/dist/heart/awaiting/await-scheduler.js +382 -0
  100. package/dist/heart/background-operations.js +281 -0
  101. package/dist/heart/bridges/manager.js +478 -0
  102. package/dist/heart/bridges/state-machine.js +135 -0
  103. package/dist/heart/bridges/store.js +135 -0
  104. package/dist/heart/bundle-state.js +168 -0
  105. package/dist/heart/commitments.js +135 -0
  106. package/dist/heart/config-registry.js +331 -0
  107. package/dist/heart/config.js +195 -137
  108. package/dist/heart/context-loss-gauntlet.js +387 -0
  109. package/dist/heart/context-loss-sentinel.js +1157 -0
  110. package/dist/heart/core.js +2257 -338
  111. package/dist/heart/cross-chat-delivery.js +133 -0
  112. package/dist/heart/daemon/agent-config-check.js +451 -0
  113. package/dist/heart/daemon/agent-discovery.js +263 -0
  114. package/dist/heart/daemon/agent-service.js +542 -0
  115. package/dist/heart/daemon/agentic-repair.js +547 -0
  116. package/dist/heart/daemon/await-private-wake.js +59 -0
  117. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  118. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  119. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  120. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  121. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  122. package/dist/heart/daemon/cadence.js +180 -0
  123. package/dist/heart/daemon/cli-defaults.js +836 -0
  124. package/dist/heart/daemon/cli-desk.js +322 -0
  125. package/dist/heart/daemon/cli-exec.js +8730 -0
  126. package/dist/heart/daemon/cli-help.js +710 -0
  127. package/dist/heart/daemon/cli-parse.js +2719 -0
  128. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  129. package/dist/heart/daemon/cli-render.js +777 -0
  130. package/dist/heart/daemon/cli-types.js +8 -0
  131. package/dist/heart/daemon/connect-bay.js +323 -0
  132. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  133. package/dist/heart/daemon/container-healthcheck.js +112 -0
  134. package/dist/heart/daemon/container-runtime.js +97 -0
  135. package/dist/heart/daemon/container-spec-auditor-main.js +170 -0
  136. package/dist/heart/daemon/container-spec-auditor.js +236 -0
  137. package/dist/heart/daemon/daemon-bootstrap-startup.js +107 -0
  138. package/dist/heart/daemon/daemon-cli.js +30 -786
  139. package/dist/heart/daemon/daemon-entry.js +971 -13
  140. package/dist/heart/daemon/daemon-health.js +186 -0
  141. package/dist/heart/daemon/daemon-rollup.js +57 -0
  142. package/dist/heart/daemon/daemon-runtime-sync.js +287 -0
  143. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  144. package/dist/heart/daemon/daemon.js +2156 -28
  145. package/dist/heart/daemon/dns-workflow.js +394 -0
  146. package/dist/heart/daemon/doctor-types.js +8 -0
  147. package/dist/heart/daemon/doctor.js +1755 -0
  148. package/dist/heart/daemon/freshness.js +345 -0
  149. package/dist/heart/daemon/habit-private-wake.js +61 -0
  150. package/dist/heart/daemon/health-monitor.js +142 -11
  151. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  152. package/dist/heart/daemon/hooks/bundle-meta.js +226 -0
  153. package/dist/heart/daemon/http-health-probe.js +80 -0
  154. package/dist/heart/daemon/human-command-screens.js +234 -0
  155. package/dist/heart/daemon/human-readiness.js +114 -0
  156. package/dist/heart/daemon/inner-status.js +78 -0
  157. package/dist/heart/daemon/interactive-repair.js +394 -0
  158. package/dist/heart/daemon/launchd.js +188 -0
  159. package/dist/heart/daemon/log-tailer.js +82 -12
  160. package/dist/heart/daemon/logs-prune.js +132 -0
  161. package/dist/heart/daemon/mcp-canary.js +524 -0
  162. package/dist/heart/daemon/message-router.js +80 -11
  163. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  164. package/dist/heart/daemon/os-cron-deps.js +135 -0
  165. package/dist/heart/daemon/os-cron.js +22 -14
  166. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  167. package/dist/heart/daemon/ouro-entry.js +3 -1
  168. package/dist/heart/daemon/plugin-cli.js +432 -0
  169. package/dist/heart/daemon/process-manager.js +739 -54
  170. package/dist/heart/daemon/provider-discovery.js +137 -0
  171. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  172. package/dist/heart/daemon/prunable-bundle.js +144 -0
  173. package/dist/heart/daemon/pulse.js +511 -0
  174. package/dist/heart/daemon/readiness-repair.js +365 -0
  175. package/dist/heart/daemon/run-hooks.js +39 -0
  176. package/dist/heart/daemon/runtime-logging.js +92 -16
  177. package/dist/heart/daemon/runtime-metadata.js +191 -0
  178. package/dist/{repertoire/tasks/lifecycle.js → heart/daemon/runtime-mode.js} +37 -39
  179. package/dist/heart/daemon/safe-mode.js +161 -0
  180. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2609 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1866 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +976 -0
  184. package/dist/heart/daemon/sanctuary-bundle-migration.js +728 -0
  185. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  186. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  187. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  188. package/dist/heart/daemon/sense-manager.js +948 -0
  189. package/dist/heart/daemon/session-id-resolver.js +131 -0
  190. package/dist/heart/daemon/skill-management-installer.js +94 -0
  191. package/dist/heart/daemon/socket-client.js +370 -0
  192. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  193. package/dist/heart/daemon/startup-tui.js +339 -0
  194. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  195. package/dist/heart/daemon/task-scheduler.js +117 -39
  196. package/dist/heart/daemon/terminal-ui.js +499 -0
  197. package/dist/heart/daemon/thoughts.js +591 -0
  198. package/dist/heart/daemon/up-progress.js +366 -0
  199. package/dist/heart/daemon/vault-items.js +56 -0
  200. package/dist/heart/delegation.js +59 -0
  201. package/dist/heart/external-events/router.js +1414 -0
  202. package/dist/heart/habits/habit-cancel.js +810 -0
  203. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  204. package/dist/heart/habits/habit-migration.js +194 -0
  205. package/dist/heart/habits/habit-parser.js +278 -0
  206. package/dist/heart/habits/habit-runtime-state.js +93 -0
  207. package/dist/heart/habits/habit-scheduler.js +653 -0
  208. package/dist/heart/habits/habit-session-summary.js +318 -0
  209. package/dist/heart/habits/habit-session.js +636 -0
  210. package/dist/heart/{daemon → hatch}/hatch-animation.js +10 -3
  211. package/dist/heart/{daemon → hatch}/hatch-flow.js +57 -139
  212. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  213. package/dist/heart/hatch/specialist-orchestrator.js +129 -0
  214. package/dist/heart/hatch/specialist-prompt.js +102 -0
  215. package/dist/heart/hatch/specialist-tools.js +318 -0
  216. package/dist/heart/identity.js +297 -67
  217. package/dist/heart/kept-notes.js +289 -0
  218. package/dist/heart/kicks.js +2 -20
  219. package/dist/heart/machine-identity.js +161 -0
  220. package/dist/heart/mail-import-discovery.js +353 -0
  221. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  222. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  223. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  224. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  225. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  226. package/dist/heart/mailbox/mailbox-http.js +99 -0
  227. package/dist/heart/mailbox/mailbox-read.js +39 -0
  228. package/dist/heart/mailbox/mailbox-types.js +27 -0
  229. package/dist/heart/mailbox/mailbox-view.js +197 -0
  230. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  231. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  232. package/dist/heart/mailbox/readers/mail.js +375 -0
  233. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  234. package/dist/heart/mailbox/readers/sessions.js +232 -0
  235. package/dist/heart/mailbox/readers/shared.js +111 -0
  236. package/dist/heart/mcp/mcp-server.js +696 -0
  237. package/dist/heart/migrate-config.js +100 -0
  238. package/dist/heart/model-capabilities.js +59 -0
  239. package/dist/heart/orientation-frame.js +345 -0
  240. package/dist/heart/platform.js +81 -0
  241. package/dist/heart/primitives.js +1 -1
  242. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  243. package/dist/heart/private-runtime/index.js +18 -0
  244. package/dist/heart/private-runtime/ledger.js +221 -0
  245. package/dist/heart/private-runtime/policy.js +252 -0
  246. package/dist/heart/private-runtime/types.js +2 -0
  247. package/dist/heart/progress-story.js +42 -0
  248. package/dist/heart/provider-attempt.js +137 -0
  249. package/dist/heart/provider-binding-resolver.js +273 -0
  250. package/dist/heart/provider-credentials.js +449 -0
  251. package/dist/heart/provider-failover.js +311 -0
  252. package/dist/heart/provider-models.js +96 -0
  253. package/dist/heart/provider-ping.js +265 -0
  254. package/dist/heart/provider-readiness-cache.js +119 -0
  255. package/dist/heart/provider-visibility.js +188 -0
  256. package/dist/heart/providers/anthropic-token.js +131 -0
  257. package/dist/heart/providers/anthropic.js +236 -58
  258. package/dist/heart/providers/azure.js +104 -13
  259. package/dist/heart/providers/error-classification.js +127 -0
  260. package/dist/heart/providers/github-copilot.js +145 -0
  261. package/dist/heart/providers/minimax-vlm.js +189 -0
  262. package/dist/heart/providers/minimax.js +29 -7
  263. package/dist/heart/providers/openai-codex-token.js +349 -0
  264. package/dist/heart/providers/openai-codex.js +63 -39
  265. package/dist/heart/providers/openai-compatible.js +177 -0
  266. package/dist/heart/run-ledger.js +247 -0
  267. package/dist/heart/runtime-capability-check.js +170 -0
  268. package/dist/heart/runtime-credentials.js +607 -0
  269. package/dist/heart/runtime-cwd.js +87 -0
  270. package/dist/heart/sense-truth.js +79 -0
  271. package/dist/heart/session-activity.js +235 -0
  272. package/dist/heart/session-events.js +1318 -0
  273. package/dist/heart/session-playback-cli-main.js +5 -0
  274. package/dist/heart/session-playback-cli.js +36 -0
  275. package/dist/heart/session-playback.js +231 -0
  276. package/dist/heart/session-stats-cli-main.js +5 -0
  277. package/dist/heart/session-stats.js +182 -0
  278. package/dist/heart/session-transcript.js +133 -0
  279. package/dist/heart/start-of-turn-packet.js +372 -0
  280. package/dist/heart/steward-policy.js +302 -0
  281. package/dist/heart/streaming.js +682 -207
  282. package/dist/heart/structured-output.js +196 -0
  283. package/dist/heart/sync-classification.js +176 -0
  284. package/dist/heart/sync.js +449 -0
  285. package/dist/heart/target-resolution.js +127 -0
  286. package/dist/heart/tempo.js +93 -0
  287. package/dist/heart/temporal-view.js +41 -0
  288. package/dist/heart/timeouts.js +101 -0
  289. package/dist/heart/tool-activity-callbacks.js +59 -0
  290. package/dist/heart/tool-approval.js +342 -0
  291. package/dist/heart/tool-description.js +155 -0
  292. package/dist/heart/tool-friction.js +55 -0
  293. package/dist/heart/tool-loop.js +200 -0
  294. package/dist/heart/turn-context.js +481 -0
  295. package/dist/heart/turn-coordinator.js +28 -0
  296. package/dist/heart/versioning/ouro-bot-global-installer.js +129 -0
  297. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  298. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  299. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  300. package/dist/heart/{daemon → versioning}/ouro-uti.js +11 -2
  301. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  302. package/dist/heart/versioning/staged-restart.js +146 -0
  303. package/dist/heart/versioning/update-checker.js +116 -0
  304. package/dist/heart/versioning/update-hooks.js +154 -0
  305. package/dist/heart/versioning/version-intent.js +114 -0
  306. package/dist/heart/versioning/wrapper-publish-guard.js +86 -0
  307. package/dist/heart/work-card.js +380 -0
  308. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  309. package/dist/mailbox-ui/assets/index-J8zDwHmE.js +1 -0
  310. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  311. package/dist/mailbox-ui/index.html +16 -0
  312. package/dist/mailroom/attention.js +167 -0
  313. package/dist/mailroom/autonomy.js +209 -0
  314. package/dist/mailroom/blob-store.js +889 -0
  315. package/dist/mailroom/body-cache.js +61 -0
  316. package/dist/mailroom/cache-sync-cli.js +58 -0
  317. package/dist/mailroom/core.js +803 -0
  318. package/dist/mailroom/entry.js +160 -0
  319. package/dist/mailroom/file-store.js +568 -0
  320. package/dist/mailroom/hosted-cache-sync.js +384 -0
  321. package/dist/mailroom/mbox-import.js +393 -0
  322. package/dist/mailroom/migration.js +164 -0
  323. package/dist/mailroom/outbound.js +380 -0
  324. package/dist/mailroom/policy.js +263 -0
  325. package/dist/mailroom/reader.js +292 -0
  326. package/dist/mailroom/search-cache.js +513 -0
  327. package/dist/mailroom/search-relevance.js +319 -0
  328. package/dist/mailroom/smtp-ingress.js +176 -0
  329. package/dist/mailroom/source-state.js +176 -0
  330. package/dist/mailroom/thread.js +109 -0
  331. package/dist/mailroom/travel-extract.js +89 -0
  332. package/dist/mind/bundle-manifest.js +93 -1
  333. package/dist/mind/context.js +287 -104
  334. package/dist/mind/desk-section.js +362 -0
  335. package/dist/mind/diary-integrity.js +60 -0
  336. package/dist/mind/{memory.js → diary.js} +90 -98
  337. package/dist/mind/embedding-provider.js +60 -0
  338. package/dist/mind/file-state.js +179 -0
  339. package/dist/mind/first-impressions.js +16 -2
  340. package/dist/mind/{associative-recall.js → note-search.js} +61 -60
  341. package/dist/mind/obligation-steering.js +227 -0
  342. package/dist/mind/pending.js +102 -9
  343. package/dist/mind/phrases.js +1 -0
  344. package/dist/mind/prompt-budget.js +479 -0
  345. package/dist/mind/prompt-refresh.js +3 -2
  346. package/dist/mind/prompt.js +1377 -140
  347. package/dist/mind/provenance-trust.js +26 -0
  348. package/dist/mind/record-paths.js +312 -0
  349. package/dist/mind/scrutiny.js +173 -0
  350. package/dist/mind/session-transaction.js +415 -0
  351. package/dist/mind/token-estimate.js +8 -12
  352. package/dist/nerves/cli-logging.js +22 -3
  353. package/dist/nerves/coverage/audit-rules.js +15 -6
  354. package/dist/nerves/coverage/audit.js +28 -2
  355. package/dist/nerves/coverage/cli.js +1 -1
  356. package/dist/nerves/coverage/contract.js +5 -5
  357. package/dist/nerves/coverage/file-completeness.js +139 -5
  358. package/dist/nerves/coverage/run-artifacts.js +56 -36
  359. package/dist/nerves/coverage/source-scanner.js +4 -4
  360. package/dist/nerves/event-buffer.js +111 -0
  361. package/dist/nerves/index.js +305 -9
  362. package/dist/nerves/observation.js +20 -0
  363. package/dist/nerves/redact.js +79 -0
  364. package/dist/nerves/review/cli-main.js +5 -0
  365. package/dist/nerves/review/cli.js +156 -0
  366. package/dist/nerves/review/core.js +159 -0
  367. package/dist/nerves/runtime.js +17 -1
  368. package/dist/repertoire/ado-client.js +17 -56
  369. package/dist/repertoire/ado-semantic.js +16 -10
  370. package/dist/repertoire/api-client.js +97 -0
  371. package/dist/repertoire/bitwarden-store.js +1045 -0
  372. package/dist/repertoire/bundle-templates.js +71 -0
  373. package/dist/repertoire/bw-installer.js +180 -0
  374. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  375. package/dist/repertoire/coding/context-pack.js +331 -0
  376. package/dist/repertoire/coding/feedback.js +322 -0
  377. package/dist/repertoire/coding/index.js +18 -3
  378. package/dist/repertoire/coding/manager.js +228 -14
  379. package/dist/repertoire/coding/spawner.js +61 -14
  380. package/dist/repertoire/coding/tools.js +279 -12
  381. package/dist/repertoire/coding/workbench-client.js +272 -0
  382. package/dist/repertoire/coding/workbench-manager.js +346 -0
  383. package/dist/repertoire/commerce-errors.js +109 -0
  384. package/dist/repertoire/commerce-self-test.js +156 -0
  385. package/dist/repertoire/credential-access.js +178 -0
  386. package/dist/repertoire/data/ado-endpoints.json +188 -0
  387. package/dist/repertoire/desk/classifier.js +362 -0
  388. package/dist/repertoire/duffel-client.js +185 -0
  389. package/dist/repertoire/github-client.js +14 -55
  390. package/dist/repertoire/graph-client.js +11 -52
  391. package/dist/repertoire/guardrails.js +1083 -0
  392. package/dist/repertoire/mcp-client.js +295 -0
  393. package/dist/repertoire/mcp-manager.js +434 -0
  394. package/dist/repertoire/mcp-tools.js +83 -0
  395. package/dist/repertoire/plugin-mcp.js +175 -0
  396. package/dist/repertoire/plugins.js +253 -0
  397. package/dist/repertoire/relationship-authorization.js +194 -0
  398. package/dist/repertoire/shell-sessions.js +133 -0
  399. package/dist/repertoire/skills.js +45 -24
  400. package/dist/repertoire/stripe-client.js +131 -0
  401. package/dist/repertoire/tool-arguments.js +148 -0
  402. package/dist/repertoire/tool-results.js +29 -0
  403. package/dist/repertoire/tools-a2a.js +699 -0
  404. package/dist/repertoire/tools-attachments.js +322 -0
  405. package/dist/repertoire/tools-awaiting.js +575 -0
  406. package/dist/repertoire/tools-base.js +85 -707
  407. package/dist/repertoire/tools-bluebubbles.js +95 -0
  408. package/dist/repertoire/tools-bridge.js +144 -0
  409. package/dist/repertoire/tools-bundle.js +993 -0
  410. package/dist/repertoire/tools-commerce.js +253 -0
  411. package/dist/repertoire/tools-config.js +186 -0
  412. package/dist/repertoire/tools-continuity.js +575 -0
  413. package/dist/repertoire/tools-credential.js +383 -0
  414. package/dist/repertoire/tools-evolution.js +527 -0
  415. package/dist/repertoire/tools-files.js +344 -0
  416. package/dist/repertoire/tools-flight.js +290 -0
  417. package/dist/repertoire/tools-flow.js +119 -0
  418. package/dist/repertoire/tools-github.js +3 -8
  419. package/dist/repertoire/tools-habits.js +103 -0
  420. package/dist/repertoire/tools-mail.js +1828 -0
  421. package/dist/repertoire/tools-notes.js +485 -0
  422. package/dist/repertoire/tools-obligations.js +182 -0
  423. package/dist/repertoire/tools-orientation.js +31 -0
  424. package/dist/repertoire/tools-record.js +482 -0
  425. package/dist/repertoire/tools-rsvp.js +139 -0
  426. package/dist/repertoire/tools-runtime.js +150 -0
  427. package/dist/repertoire/tools-session.js +1108 -0
  428. package/dist/repertoire/tools-shell.js +133 -0
  429. package/dist/repertoire/tools-steward-policy.js +95 -0
  430. package/dist/repertoire/tools-stripe.js +224 -0
  431. package/dist/repertoire/tools-surface.js +369 -0
  432. package/dist/repertoire/tools-teams.js +67 -61
  433. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  434. package/dist/repertoire/tools-travel.js +125 -0
  435. package/dist/repertoire/tools-trip.js +982 -0
  436. package/dist/repertoire/tools-unraid.js +484 -0
  437. package/dist/repertoire/tools-user-profile.js +146 -0
  438. package/dist/repertoire/tools-vault.js +40 -0
  439. package/dist/repertoire/tools-voice.js +145 -0
  440. package/dist/repertoire/tools.js +441 -102
  441. package/dist/repertoire/travel-api-client.js +360 -0
  442. package/dist/repertoire/unraid-client.js +155 -0
  443. package/dist/repertoire/unraid-restart.js +212 -0
  444. package/dist/repertoire/user-profile.js +131 -0
  445. package/dist/repertoire/vault-setup.js +246 -0
  446. package/dist/repertoire/vault-unlock.js +628 -0
  447. package/dist/rsvp/aisleplanner-client.js +354 -0
  448. package/dist/rsvp/cli.js +926 -0
  449. package/dist/rsvp/config.js +327 -0
  450. package/dist/rsvp/cutover.js +433 -0
  451. package/dist/rsvp/diagnostics.js +232 -0
  452. package/dist/rsvp/diff-renderer.js +176 -0
  453. package/dist/rsvp/habit-policy.js +110 -0
  454. package/dist/rsvp/habit-stage.js +123 -0
  455. package/dist/rsvp/incident-bundle.js +97 -0
  456. package/dist/rsvp/migration.js +204 -0
  457. package/dist/rsvp/native-habit-runner.js +630 -0
  458. package/dist/rsvp/outbound-state.js +628 -0
  459. package/dist/rsvp/query.js +118 -0
  460. package/dist/rsvp/replay.js +233 -0
  461. package/dist/rsvp/snapshot.js +232 -0
  462. package/dist/rsvp/spend-ledger.js +175 -0
  463. package/dist/scripts/claude-code-hook.js +41 -0
  464. package/dist/scripts/claude-code-stop-hook.js +47 -0
  465. package/dist/senses/a2a-entry.js +115 -0
  466. package/dist/senses/attention-queue.js +186 -0
  467. package/dist/senses/await-turn-message.js +58 -0
  468. package/dist/senses/bluebubbles/active-turns.js +216 -0
  469. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  470. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  471. package/dist/senses/bluebubbles/client.js +799 -0
  472. package/dist/senses/bluebubbles/context-packet.js +207 -0
  473. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  474. package/dist/senses/bluebubbles/entry.js +90 -0
  475. package/dist/senses/bluebubbles/inbound-log.js +127 -0
  476. package/dist/senses/bluebubbles/index.js +3839 -0
  477. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  478. package/dist/senses/bluebubbles/media.js +389 -0
  479. package/dist/senses/bluebubbles/model.js +392 -0
  480. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +57 -6
  481. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  482. package/dist/senses/bluebubbles/processed-log.js +133 -0
  483. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  484. package/dist/senses/bluebubbles/replay.js +284 -0
  485. package/dist/senses/bluebubbles/runtime-state.js +137 -0
  486. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  487. package/dist/senses/bluebubbles/session-cleanup.js +72 -0
  488. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  489. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  490. package/dist/senses/cli/bracketed-paste.js +82 -0
  491. package/dist/senses/cli/image-paste.js +287 -0
  492. package/dist/senses/cli/image-ref-navigation.js +75 -0
  493. package/dist/senses/cli/ink-app.js +156 -0
  494. package/dist/senses/cli/inline-diff.js +64 -0
  495. package/dist/senses/cli/input-keys.js +174 -0
  496. package/dist/senses/cli/kill-ring.js +86 -0
  497. package/dist/senses/cli/message-list.js +51 -0
  498. package/dist/senses/cli/ouro-tui.js +607 -0
  499. package/dist/senses/cli/spinner-imperative.js +135 -0
  500. package/dist/senses/cli/spinner.js +101 -0
  501. package/dist/senses/cli/status-line.js +60 -0
  502. package/dist/senses/cli/streaming-markdown.js +526 -0
  503. package/dist/senses/cli/tool-display.js +85 -0
  504. package/dist/senses/cli/tool-render.js +85 -0
  505. package/dist/senses/cli/tui-store.js +241 -0
  506. package/dist/senses/cli/virtual-list.js +35 -0
  507. package/dist/senses/cli-entry.js +60 -8
  508. package/dist/senses/cli-layout.js +187 -0
  509. package/dist/senses/cli.js +813 -281
  510. package/dist/senses/commands.js +66 -3
  511. package/dist/senses/context-packet-ledger.js +371 -0
  512. package/dist/senses/context-packets.js +154 -0
  513. package/dist/senses/continuity.js +94 -0
  514. package/dist/senses/habit-lifecycle-guard.js +24 -0
  515. package/dist/senses/habit-turn-message.js +160 -0
  516. package/dist/senses/ingress-evidence.js +2 -0
  517. package/dist/senses/mail-entry.js +66 -0
  518. package/dist/senses/mail.js +524 -0
  519. package/dist/senses/pipeline.js +1213 -0
  520. package/dist/senses/private-runtime-worker.js +859 -0
  521. package/dist/senses/private-runtime.js +1496 -0
  522. package/dist/senses/proactive-content-guard.js +51 -0
  523. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  524. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  525. package/dist/senses/sanctuary-grounding.js +118 -0
  526. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  527. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  528. package/dist/senses/sanctuary-health-runner.js +101 -0
  529. package/dist/senses/sanctuary-health.js +408 -0
  530. package/dist/senses/sanctuary-interactive-control.js +306 -0
  531. package/dist/senses/sanctuary-media-catalog-contract.js +235 -0
  532. package/dist/senses/sanctuary-media-optimization.js +514 -0
  533. package/dist/senses/sanctuary-runtime.js +338 -0
  534. package/dist/senses/sanctuary-sab.js +85 -0
  535. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  536. package/dist/senses/shared-turn.js +571 -0
  537. package/dist/senses/surface-tool.js +109 -0
  538. package/dist/senses/teams-entry.js +60 -8
  539. package/dist/senses/teams.js +953 -211
  540. package/dist/senses/telegram-admission.js +711 -0
  541. package/dist/senses/telegram-approval-runtime.js +566 -0
  542. package/dist/senses/telegram-attachments.js +182 -0
  543. package/dist/senses/telegram-audit-ledger.js +220 -0
  544. package/dist/senses/telegram-client.js +1677 -0
  545. package/dist/senses/telegram-effect-adapter.js +859 -0
  546. package/dist/senses/telegram-entry.js +83 -0
  547. package/dist/senses/telegram.js +2026 -0
  548. package/dist/senses/trust-gate.js +207 -2
  549. package/dist/senses/voice/audio-playback.js +237 -0
  550. package/dist/senses/voice/audio-routing.js +119 -0
  551. package/dist/senses/voice/elevenlabs.js +202 -0
  552. package/dist/senses/voice/floor-control.js +431 -0
  553. package/dist/senses/voice/floor-controller.js +115 -0
  554. package/dist/senses/voice/golden-path.js +116 -0
  555. package/dist/senses/voice/index.js +29 -0
  556. package/dist/senses/voice/meeting.js +113 -0
  557. package/dist/senses/voice/outbound.js +190 -0
  558. package/dist/senses/voice/phone.js +33 -0
  559. package/dist/senses/voice/playback.js +139 -0
  560. package/dist/senses/voice/realtime-eval.js +496 -0
  561. package/dist/senses/voice/realtime-trace.js +531 -0
  562. package/dist/senses/voice/transcript.js +70 -0
  563. package/dist/senses/voice/turn.js +191 -0
  564. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  565. package/dist/senses/voice/twilio-phone.js +5081 -0
  566. package/dist/senses/voice/types.js +2 -0
  567. package/dist/senses/voice/whisper.js +161 -0
  568. package/dist/senses/voice-entry.js +81 -0
  569. package/dist/senses/voice-realtime-eval-command.js +99 -0
  570. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  571. package/dist/senses/voice-twilio-entry.js +87 -0
  572. package/dist/trips/core.js +138 -0
  573. package/dist/trips/store.js +265 -0
  574. package/dist/util/frontmatter.js +69 -0
  575. package/npm-shrinkwrap.json +8144 -0
  576. package/package.json +82 -12
  577. package/skills/agent-commerce.md +113 -0
  578. package/skills/browser-navigation.md +117 -0
  579. package/skills/commerce-setup-guide.md +116 -0
  580. package/skills/commerce-setup.md +84 -0
  581. package/skills/configure-dev-tools.md +99 -0
  582. package/skills/travel-planning.md +138 -0
  583. package/AdoptionSpecialist.ouro/agent.json +0 -20
  584. package/AdoptionSpecialist.ouro/psyche/SOUL.md +0 -22
  585. package/dist/heart/daemon/specialist-orchestrator.js +0 -160
  586. package/dist/heart/daemon/specialist-prompt.js +0 -47
  587. package/dist/heart/daemon/specialist-session.js +0 -142
  588. package/dist/heart/daemon/specialist-tools.js +0 -132
  589. package/dist/heart/daemon/subagent-installer.js +0 -125
  590. package/dist/inner-worker-entry.js +0 -4
  591. package/dist/mind/friends/channel.js +0 -49
  592. package/dist/mind/friends/resolver.js +0 -84
  593. package/dist/mind/friends/store-file.js +0 -171
  594. package/dist/mind/friends/store.js +0 -4
  595. package/dist/mind/friends/tokens.js +0 -26
  596. package/dist/mind/friends/types.js +0 -21
  597. package/dist/repertoire/tasks/board.js +0 -122
  598. package/dist/repertoire/tasks/index.js +0 -210
  599. package/dist/repertoire/tasks/middleware.js +0 -65
  600. package/dist/repertoire/tasks/parser.js +0 -173
  601. package/dist/repertoire/tasks/scanner.js +0 -132
  602. package/dist/repertoire/tasks/transitions.js +0 -145
  603. package/dist/senses/bluebubbles-client.js +0 -279
  604. package/dist/senses/bluebubbles-entry.js +0 -11
  605. package/dist/senses/bluebubbles-model.js +0 -253
  606. package/dist/senses/bluebubbles.js +0 -332
  607. package/dist/senses/inner-dialog-worker.js +0 -61
  608. package/dist/senses/inner-dialog.js +0 -231
  609. package/subagents/README.md +0 -73
  610. package/subagents/work-doer.md +0 -233
  611. package/subagents/work-merger.md +0 -624
  612. package/subagents/work-planner.md +0 -373
  613. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  614. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  615. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  616. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  617. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  618. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  619. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  620. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  621. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  622. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  623. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  624. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
@@ -0,0 +1,799 @@
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.BlueBubblesSendError = void 0;
37
+ exports.createBlueBubblesClient = createBlueBubblesClient;
38
+ const node_crypto_1 = require("node:crypto");
39
+ const config_1 = require("../../heart/config");
40
+ const identity_1 = require("../../heart/identity");
41
+ const bluebubbles_health_diagnostics_1 = require("../../heart/daemon/bluebubbles-health-diagnostics");
42
+ const runtime_1 = require("../../nerves/runtime");
43
+ const minimax_1 = require("../../heart/providers/minimax");
44
+ const minimax_vlm_1 = require("../../heart/providers/minimax-vlm");
45
+ const model_1 = require("./model");
46
+ const media_1 = require("./media");
47
+ class BlueBubblesSendError extends Error {
48
+ httpStatus;
49
+ status;
50
+ errorCode;
51
+ transportInvoked;
52
+ constructor(input) {
53
+ super(input.message, input.cause === undefined ? undefined : { cause: input.cause });
54
+ this.name = "BlueBubblesSendError";
55
+ this.httpStatus = input.httpStatus;
56
+ this.status = input.httpStatus;
57
+ this.errorCode = input.errorCode;
58
+ this.transportInvoked = input.transportInvoked;
59
+ }
60
+ }
61
+ exports.BlueBubblesSendError = BlueBubblesSendError;
62
+ function buildBlueBubblesApiUrl(baseUrl, endpoint, password) {
63
+ const root = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
64
+ const url = new URL(endpoint.replace(/^\//, ""), root);
65
+ url.searchParams.set("password", password);
66
+ return url.toString();
67
+ }
68
+ function asRecord(value) {
69
+ return value && typeof value === "object" && !Array.isArray(value)
70
+ ? value
71
+ : null;
72
+ }
73
+ function readString(record, key) {
74
+ const value = record[key];
75
+ return typeof value === "string" ? value : undefined;
76
+ }
77
+ function extractMessageGuid(payload) {
78
+ if (!payload || typeof payload !== "object")
79
+ return undefined;
80
+ const record = payload;
81
+ const data = record.data && typeof record.data === "object" && !Array.isArray(record.data)
82
+ ? record.data
83
+ : null;
84
+ const candidates = [
85
+ record.messageGuid,
86
+ record.messageId,
87
+ record.guid,
88
+ data?.messageGuid,
89
+ data?.messageId,
90
+ data?.guid,
91
+ ];
92
+ for (const candidate of candidates) {
93
+ if (typeof candidate === "string" && candidate.trim()) {
94
+ return candidate.trim();
95
+ }
96
+ }
97
+ return undefined;
98
+ }
99
+ async function parseJsonBody(response) {
100
+ const raw = await response.text();
101
+ if (!raw.trim())
102
+ return null;
103
+ try {
104
+ return JSON.parse(raw);
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
110
+ function describeCaughtValue(error) {
111
+ return error instanceof Error ? error.message : String(error);
112
+ }
113
+ function sendTransportErrorCode(error) {
114
+ if (error instanceof Error && error.name === "TimeoutError")
115
+ return "timeout";
116
+ if (error instanceof Error && error.name === "AbortError")
117
+ return "abort";
118
+ if (error instanceof TypeError)
119
+ return "socket";
120
+ return "transport_error";
121
+ }
122
+ function emitBlueBubblesSendError(input) {
123
+ (0, runtime_1.emitNervesEvent)({
124
+ level: "error",
125
+ component: "senses",
126
+ event: "senses.bluebubbles_send_error",
127
+ message: "bluebubbles send failed",
128
+ meta: {
129
+ status: input.status,
130
+ errorCode: input.errorCode,
131
+ reason: input.reason,
132
+ },
133
+ });
134
+ }
135
+ function buildRepairUrl(baseUrl, messageGuid, password) {
136
+ const url = buildBlueBubblesApiUrl(baseUrl, `/api/v1/message/${encodeURIComponent(messageGuid)}`, password);
137
+ const parsed = new URL(url);
138
+ parsed.searchParams.set("with", "attachments,payloadData,chats,messageSummaryInfo");
139
+ return parsed.toString();
140
+ }
141
+ function extractChatIdentifierFromGuid(chatGuid) {
142
+ const parts = chatGuid.split(";");
143
+ return parts.length >= 3 ? parts[2]?.trim() || undefined : undefined;
144
+ }
145
+ function extractChatGuid(value) {
146
+ const record = asRecord(value);
147
+ const candidates = [
148
+ record?.chatGuid,
149
+ record?.guid,
150
+ record?.chat_guid,
151
+ record?.identifier,
152
+ record?.chatIdentifier,
153
+ record?.chat_identifier,
154
+ ];
155
+ for (const candidate of candidates) {
156
+ if (typeof candidate === "string" && candidate.trim()) {
157
+ return candidate.trim();
158
+ }
159
+ }
160
+ return undefined;
161
+ }
162
+ function extractQueriedChatIdentifier(chat, chatGuid) {
163
+ const explicitIdentifier = readString(chat, "chatIdentifier")
164
+ ?? readString(chat, "identifier")
165
+ ?? readString(chat, "chat_identifier");
166
+ if (explicitIdentifier) {
167
+ return explicitIdentifier;
168
+ }
169
+ return extractChatIdentifierFromGuid(chatGuid);
170
+ }
171
+ function extractChatQueryRows(payload) {
172
+ const record = asRecord(payload);
173
+ const data = Array.isArray(record?.data) ? record.data : payload;
174
+ if (!Array.isArray(data)) {
175
+ return [];
176
+ }
177
+ return data.map((entry) => asRecord(entry)).filter((entry) => entry !== null);
178
+ }
179
+ function extractMessageQueryRows(payload) {
180
+ const record = asRecord(payload);
181
+ const data = asRecord(record?.data);
182
+ const rows = Array.isArray(record?.data) ? record.data
183
+ : Array.isArray(data?.messages) ? data.messages
184
+ : Array.isArray(data?.results) ? data.results
185
+ : Array.isArray(record?.messages) ? record.messages
186
+ : Array.isArray(payload) ? payload
187
+ : [];
188
+ return rows;
189
+ }
190
+ function hasValidRawMessageCausalTimestamp(row) {
191
+ const record = asRecord(row);
192
+ return typeof record?.dateCreated === "number"
193
+ && Number.isFinite(record.dateCreated)
194
+ && record.dateCreated > 0;
195
+ }
196
+ async function resolveChatGuidForIdentifier(config, channelConfig, chatIdentifier) {
197
+ const trimmedIdentifier = chatIdentifier.trim();
198
+ if (!trimmedIdentifier)
199
+ return undefined;
200
+ const url = buildBlueBubblesApiUrl(config.serverUrl, "/api/v1/chat/query", config.password);
201
+ const response = await fetch(url, {
202
+ method: "POST",
203
+ headers: { "Content-Type": "application/json" },
204
+ body: JSON.stringify({
205
+ limit: 500,
206
+ offset: 0,
207
+ with: ["participants"],
208
+ }),
209
+ signal: AbortSignal.timeout(channelConfig.requestTimeoutMs),
210
+ });
211
+ if (!response.ok) {
212
+ return undefined;
213
+ }
214
+ const payload = await parseJsonBody(response);
215
+ const rows = extractChatQueryRows(payload);
216
+ for (const row of rows) {
217
+ const guid = extractChatGuid(row);
218
+ if (!guid)
219
+ continue;
220
+ const identifier = extractQueriedChatIdentifier(row, guid);
221
+ if (identifier === trimmedIdentifier || guid === trimmedIdentifier) {
222
+ return guid;
223
+ }
224
+ }
225
+ return undefined;
226
+ }
227
+ function collectPreviewStrings(value, out, depth = 0) {
228
+ if (depth > 4 || out.length >= 4)
229
+ return;
230
+ if (typeof value === "string") {
231
+ const trimmed = value.trim();
232
+ if (trimmed)
233
+ out.push(trimmed);
234
+ return;
235
+ }
236
+ if (Array.isArray(value)) {
237
+ for (const entry of value)
238
+ collectPreviewStrings(entry, out, depth + 1);
239
+ return;
240
+ }
241
+ const record = asRecord(value);
242
+ if (!record)
243
+ return;
244
+ const preferredKeys = ["title", "summary", "subtitle", "previewText", "siteName", "host", "url"];
245
+ for (const key of preferredKeys) {
246
+ if (out.length >= 4)
247
+ break;
248
+ collectPreviewStrings(record[key], out, depth + 1);
249
+ }
250
+ }
251
+ function extractLinkPreviewText(data) {
252
+ const values = [];
253
+ collectPreviewStrings(data.payloadData, values);
254
+ collectPreviewStrings(data.messageSummaryInfo, values);
255
+ const unique = [...new Set(values.map((value) => value.trim()).filter(Boolean))];
256
+ if (unique.length === 0)
257
+ return undefined;
258
+ return unique.slice(0, 2).join(" — ");
259
+ }
260
+ function applyRepairNotice(event, notice) {
261
+ return {
262
+ ...event,
263
+ requiresRepair: false,
264
+ repairNotice: notice,
265
+ };
266
+ }
267
+ function hasRecoverableMessageContent(event) {
268
+ return event.kind === "message"
269
+ && (event.textForAgent.trim().length > 0
270
+ || event.attachments.length > 0
271
+ || event.hasPayloadData);
272
+ }
273
+ function hydrateTextForAgent(event, rawData) {
274
+ if (event.kind !== "message") {
275
+ return { ...event, requiresRepair: false };
276
+ }
277
+ if (event.balloonBundleId !== "com.apple.messages.URLBalloonProvider") {
278
+ return { ...event, requiresRepair: false };
279
+ }
280
+ const previewText = extractLinkPreviewText(rawData);
281
+ if (!previewText) {
282
+ return { ...event, requiresRepair: false };
283
+ }
284
+ const base = event.text.trim();
285
+ const textForAgent = base
286
+ ? `${base}\n[link preview: ${previewText}]`
287
+ : `[link preview: ${previewText}]`;
288
+ return {
289
+ ...event,
290
+ textForAgent,
291
+ requiresRepair: false,
292
+ };
293
+ }
294
+ function extractRepairData(payload) {
295
+ const record = asRecord(payload);
296
+ return asRecord(record?.data) ?? record;
297
+ }
298
+ function providerSupportsAudioInput(provider) {
299
+ void provider;
300
+ return false;
301
+ }
302
+ async function resolveChatGuid(chat, config, channelConfig) {
303
+ return chat.chatGuid
304
+ ?? await resolveChatGuidForIdentifier(config, channelConfig, chat.chatIdentifier ?? "");
305
+ }
306
+ function createBlueBubblesClient(config = (0, config_1.getBlueBubblesConfig)(), channelConfig = (0, config_1.getBlueBubblesChannelConfig)()) {
307
+ return {
308
+ async sendText(params) {
309
+ const trimmedText = params.text.trim();
310
+ if (!trimmedText) {
311
+ throw new Error("BlueBubbles send requires non-empty text.");
312
+ }
313
+ const resolvedChatGuid = await resolveChatGuid(params.chat, config, channelConfig);
314
+ if (!resolvedChatGuid) {
315
+ throw new Error("BlueBubbles send currently requires chat.chatGuid from the inbound event.");
316
+ }
317
+ const url = buildBlueBubblesApiUrl(config.serverUrl, "/api/v1/message/text", config.password);
318
+ const body = {
319
+ chatGuid: resolvedChatGuid,
320
+ tempGuid: params.tempGuid?.trim() || (0, node_crypto_1.randomUUID)(),
321
+ message: trimmedText,
322
+ };
323
+ if (params.replyToMessageGuid?.trim()) {
324
+ body.method = "private-api";
325
+ body.selectedMessageGuid = params.replyToMessageGuid.trim();
326
+ body.partIndex = 0;
327
+ }
328
+ (0, runtime_1.emitNervesEvent)({
329
+ component: "senses",
330
+ event: "senses.bluebubbles_send_start",
331
+ message: "sending bluebubbles message",
332
+ meta: {
333
+ chatGuid: resolvedChatGuid,
334
+ hasReplyTarget: Boolean(params.replyToMessageGuid?.trim()),
335
+ },
336
+ });
337
+ const requestTimeoutSignal = AbortSignal.timeout(channelConfig.requestTimeoutMs);
338
+ if (params.beforeTransportInvocation && !params.beforeTransportInvocation()) {
339
+ throw new BlueBubblesSendError({
340
+ message: "BlueBubbles send was not admitted at the transport boundary.",
341
+ httpStatus: null,
342
+ errorCode: "admission_denied",
343
+ transportInvoked: false,
344
+ });
345
+ }
346
+ params.onTransportInvocation?.();
347
+ let response;
348
+ try {
349
+ response = await fetch(url, {
350
+ method: "POST",
351
+ headers: { "Content-Type": "application/json" },
352
+ body: JSON.stringify(body),
353
+ redirect: "manual",
354
+ signal: params.signal
355
+ ? AbortSignal.any([params.signal, requestTimeoutSignal])
356
+ : requestTimeoutSignal,
357
+ });
358
+ }
359
+ catch (error) {
360
+ const errorCode = sendTransportErrorCode(error);
361
+ const reason = describeCaughtValue(error);
362
+ emitBlueBubblesSendError({ status: null, errorCode, reason });
363
+ throw new BlueBubblesSendError({
364
+ message: `BlueBubbles send failed (${errorCode}): ${reason}`,
365
+ httpStatus: null,
366
+ errorCode,
367
+ transportInvoked: true,
368
+ cause: error,
369
+ });
370
+ }
371
+ if (!response.ok) {
372
+ const errorText = await response.text().catch(() => "");
373
+ const reason = errorText || "unknown";
374
+ const errorCode = `http_${response.status}`;
375
+ emitBlueBubblesSendError({ status: response.status, errorCode, reason });
376
+ throw new BlueBubblesSendError({
377
+ message: `BlueBubbles send failed (${response.status}): ${reason}`,
378
+ httpStatus: response.status,
379
+ errorCode,
380
+ transportInvoked: true,
381
+ });
382
+ }
383
+ const rawPayload = await response.text();
384
+ let payload = null;
385
+ if (rawPayload.trim()) {
386
+ try {
387
+ payload = JSON.parse(rawPayload);
388
+ }
389
+ catch (error) {
390
+ const errorCode = "malformed_response";
391
+ emitBlueBubblesSendError({ status: response.status, errorCode, reason: errorCode });
392
+ throw new BlueBubblesSendError({
393
+ message: `BlueBubbles send failed (${response.status}): malformed response`,
394
+ httpStatus: response.status,
395
+ errorCode,
396
+ transportInvoked: true,
397
+ cause: error,
398
+ });
399
+ }
400
+ }
401
+ const messageGuid = extractMessageGuid(payload);
402
+ (0, runtime_1.emitNervesEvent)({
403
+ component: "senses",
404
+ event: "senses.bluebubbles_send_end",
405
+ message: "bluebubbles message sent",
406
+ meta: {
407
+ chatGuid: resolvedChatGuid,
408
+ messageGuid: messageGuid ?? null,
409
+ },
410
+ });
411
+ return { messageGuid };
412
+ },
413
+ async editMessage(params) {
414
+ const messageGuid = params.messageGuid.trim();
415
+ const text = params.text.trim();
416
+ if (!messageGuid) {
417
+ throw new Error("BlueBubbles edit requires messageGuid.");
418
+ }
419
+ if (!text) {
420
+ throw new Error("BlueBubbles edit requires non-empty text.");
421
+ }
422
+ const editTimeoutMs = Math.max(channelConfig.requestTimeoutMs, 120000);
423
+ const url = buildBlueBubblesApiUrl(config.serverUrl, `/api/v1/message/${encodeURIComponent(messageGuid)}/edit`, config.password);
424
+ const response = await fetch(url, {
425
+ method: "POST",
426
+ headers: { "Content-Type": "application/json" },
427
+ body: JSON.stringify({
428
+ editedMessage: text,
429
+ backwardsCompatibilityMessage: params.backwardsCompatibilityMessage ?? `Edited to: ${text}`,
430
+ partIndex: typeof params.partIndex === "number" ? params.partIndex : 0,
431
+ }),
432
+ signal: AbortSignal.timeout(editTimeoutMs),
433
+ });
434
+ if (!response.ok) {
435
+ const errorText = await response.text().catch(() => "");
436
+ throw new Error(`BlueBubbles edit failed (${response.status}): ${errorText || "unknown"}`);
437
+ }
438
+ },
439
+ async setTyping(chat, typing, signal) {
440
+ const resolvedChatGuid = await resolveChatGuid(chat, config, channelConfig);
441
+ if (!resolvedChatGuid) {
442
+ return;
443
+ }
444
+ const url = buildBlueBubblesApiUrl(config.serverUrl, `/api/v1/chat/${encodeURIComponent(resolvedChatGuid)}/typing`, config.password);
445
+ const requestTimeoutSignal = AbortSignal.timeout(channelConfig.requestTimeoutMs);
446
+ const response = await fetch(url, {
447
+ method: typing ? "POST" : "DELETE",
448
+ signal: signal ? AbortSignal.any([signal, requestTimeoutSignal]) : requestTimeoutSignal,
449
+ });
450
+ if (!response.ok) {
451
+ const errorText = await response.text().catch(() => "");
452
+ throw new Error(`BlueBubbles typing failed (${response.status}): ${errorText || "unknown"}`);
453
+ }
454
+ },
455
+ async markChatRead(chat, signal) {
456
+ const resolvedChatGuid = await resolveChatGuid(chat, config, channelConfig);
457
+ if (!resolvedChatGuid) {
458
+ return;
459
+ }
460
+ const url = buildBlueBubblesApiUrl(config.serverUrl, `/api/v1/chat/${encodeURIComponent(resolvedChatGuid)}/read`, config.password);
461
+ const requestTimeoutSignal = AbortSignal.timeout(channelConfig.requestTimeoutMs);
462
+ const response = await fetch(url, {
463
+ method: "POST",
464
+ signal: signal ? AbortSignal.any([signal, requestTimeoutSignal]) : requestTimeoutSignal,
465
+ });
466
+ if (!response.ok) {
467
+ const errorText = await response.text().catch(() => "");
468
+ throw new Error(`BlueBubbles read failed (${response.status}): ${errorText || "unknown"}`);
469
+ }
470
+ },
471
+ async checkHealth() {
472
+ (0, runtime_1.emitNervesEvent)({
473
+ component: "senses",
474
+ event: "senses.bluebubbles_healthcheck_start",
475
+ message: "probing bluebubbles upstream health",
476
+ meta: { serverUrl: config.serverUrl },
477
+ });
478
+ const result = await (0, bluebubbles_health_diagnostics_1.probeBlueBubblesHealth)({
479
+ serverUrl: config.serverUrl,
480
+ password: config.password,
481
+ requestTimeoutMs: channelConfig.requestTimeoutMs,
482
+ fetchImpl: fetch,
483
+ });
484
+ if (!result.ok) {
485
+ (0, runtime_1.emitNervesEvent)({
486
+ level: "warn",
487
+ component: "senses",
488
+ event: "senses.bluebubbles_healthcheck_error",
489
+ message: "bluebubbles upstream health probe failed",
490
+ meta: {
491
+ serverUrl: config.serverUrl,
492
+ status: result.status,
493
+ reason: result.reason,
494
+ classification: result.classification,
495
+ detail: (0, bluebubbles_health_diagnostics_1.redactBlueBubblesHealthDetailForNerves)(result.detail),
496
+ },
497
+ });
498
+ throw new Error(result.detail);
499
+ }
500
+ (0, runtime_1.emitNervesEvent)({
501
+ component: "senses",
502
+ event: "senses.bluebubbles_healthcheck_end",
503
+ message: "bluebubbles upstream health probe succeeded",
504
+ meta: { serverUrl: config.serverUrl },
505
+ });
506
+ },
507
+ async queryRecentMessagesWithMetadata(params = {}) {
508
+ const limit = Math.max(1, Math.min(100, Math.floor(params.limit ?? 50)));
509
+ const offset = Math.max(0, Math.floor(params.offset ?? 0));
510
+ const url = buildBlueBubblesApiUrl(config.serverUrl, "/api/v1/message/query", config.password);
511
+ (0, runtime_1.emitNervesEvent)({
512
+ component: "senses",
513
+ event: "senses.bluebubbles_query_recent_start",
514
+ message: "querying recent bluebubbles messages",
515
+ meta: { limit, offset },
516
+ });
517
+ const request = {
518
+ limit,
519
+ offset,
520
+ sort: "DESC",
521
+ ...(params.chatGuid?.trim() ? { chatGuid: params.chatGuid.trim() } : {}),
522
+ ...(params.chatIdentifier?.trim() ? { chatIdentifier: params.chatIdentifier.trim() } : {}),
523
+ ...(typeof params.beforeTimestamp === "number" && Number.isFinite(params.beforeTimestamp)
524
+ ? { beforeTimestamp: params.beforeTimestamp }
525
+ : {}),
526
+ };
527
+ const { beforeTimestamp, ...wireRequest } = request;
528
+ const body = {
529
+ ...wireRequest,
530
+ // BlueBubbles names its inclusive message-date upper bound `before`.
531
+ ...(beforeTimestamp !== undefined ? { before: beforeTimestamp } : {}),
532
+ with: ["chats", "attachments", "payloadData", "messageSummaryInfo"],
533
+ };
534
+ const response = await fetch(url, {
535
+ method: "POST",
536
+ headers: { "Content-Type": "application/json" },
537
+ body: JSON.stringify(body),
538
+ signal: AbortSignal.timeout(channelConfig.requestTimeoutMs),
539
+ });
540
+ if (!response.ok) {
541
+ const errorText = await response.text().catch(() => "");
542
+ (0, runtime_1.emitNervesEvent)({
543
+ level: "warn",
544
+ component: "senses",
545
+ event: "senses.bluebubbles_query_recent_error",
546
+ message: "bluebubbles recent message query failed",
547
+ meta: {
548
+ status: response.status,
549
+ reason: errorText || "unknown",
550
+ },
551
+ });
552
+ throw new Error(`BlueBubbles recent message query failed (${response.status}): ${errorText || "unknown"}`);
553
+ }
554
+ const payload = await parseJsonBody(response);
555
+ const rows = extractMessageQueryRows(payload);
556
+ const invalidCausalTimestampRowCount = rows.filter((row) => !hasValidRawMessageCausalTimestamp(row)).length;
557
+ const messages = [];
558
+ for (const row of rows) {
559
+ try {
560
+ messages.push((0, model_1.normalizeBlueBubblesEvent)({ type: "new-message", data: row }));
561
+ }
562
+ catch (error) {
563
+ (0, runtime_1.emitNervesEvent)({
564
+ level: "warn",
565
+ component: "senses",
566
+ event: "senses.bluebubbles_query_recent_skip",
567
+ message: "skipped unusable bluebubbles recent message row",
568
+ meta: {
569
+ reason: describeCaughtValue(error),
570
+ },
571
+ });
572
+ }
573
+ }
574
+ (0, runtime_1.emitNervesEvent)({
575
+ component: "senses",
576
+ event: "senses.bluebubbles_query_recent_end",
577
+ message: "queried recent bluebubbles messages",
578
+ meta: {
579
+ rows: rows.length,
580
+ normalized: messages.length,
581
+ skipped: rows.length - messages.length,
582
+ },
583
+ });
584
+ return {
585
+ messages,
586
+ rawRowCount: rows.length,
587
+ normalizedRowCount: messages.length,
588
+ skippedRowCount: rows.length - messages.length,
589
+ invalidCausalTimestampRowCount,
590
+ request,
591
+ };
592
+ },
593
+ async listRecentMessages(params = {}) {
594
+ const result = await this.queryRecentMessagesWithMetadata(params);
595
+ return result.messages;
596
+ },
597
+ async repairEvent(event) {
598
+ if (!event.requiresRepair) {
599
+ (0, runtime_1.emitNervesEvent)({
600
+ component: "senses",
601
+ event: "senses.bluebubbles_repair_skipped",
602
+ message: "bluebubbles event repair skipped",
603
+ meta: {
604
+ kind: event.kind,
605
+ messageGuid: event.messageGuid,
606
+ },
607
+ });
608
+ return event;
609
+ }
610
+ (0, runtime_1.emitNervesEvent)({
611
+ level: "warn",
612
+ component: "senses",
613
+ event: "senses.bluebubbles_repair_start",
614
+ message: "repairing bluebubbles event by guid",
615
+ meta: {
616
+ kind: event.kind,
617
+ messageGuid: event.messageGuid,
618
+ eventType: event.eventType,
619
+ },
620
+ });
621
+ const url = buildRepairUrl(config.serverUrl, event.messageGuid, config.password);
622
+ try {
623
+ const response = await fetch(url, {
624
+ method: "GET",
625
+ signal: AbortSignal.timeout(channelConfig.requestTimeoutMs),
626
+ });
627
+ if (!response.ok) {
628
+ const errorText = await response.text().catch(() => "");
629
+ const repaired = applyRepairNotice(event, `BlueBubbles repair failed: ${errorText || `HTTP ${response.status}`}`);
630
+ (0, runtime_1.emitNervesEvent)({
631
+ level: "warn",
632
+ component: "senses",
633
+ event: "senses.bluebubbles_repair_error",
634
+ message: "bluebubbles repair request failed",
635
+ meta: {
636
+ messageGuid: event.messageGuid,
637
+ status: response.status,
638
+ reason: errorText || "unknown",
639
+ },
640
+ });
641
+ return repaired;
642
+ }
643
+ const payload = await parseJsonBody(response);
644
+ const data = extractRepairData(payload);
645
+ if (!data || typeof data.guid !== "string") {
646
+ const repaired = applyRepairNotice(event, "BlueBubbles repair failed: invalid message payload");
647
+ (0, runtime_1.emitNervesEvent)({
648
+ level: "warn",
649
+ component: "senses",
650
+ event: "senses.bluebubbles_repair_error",
651
+ message: "bluebubbles repair returned unusable payload",
652
+ meta: {
653
+ messageGuid: event.messageGuid,
654
+ },
655
+ });
656
+ return repaired;
657
+ }
658
+ const normalized = (0, model_1.normalizeBlueBubblesEvent)({
659
+ type: event.eventType,
660
+ data,
661
+ });
662
+ const recoveredMessage = event.kind === "mutation"
663
+ && !event.shouldNotifyAgent
664
+ ? (0, model_1.normalizeBlueBubblesEvent)({
665
+ type: "new-message",
666
+ data,
667
+ })
668
+ : null;
669
+ let hydrated = recoveredMessage && hasRecoverableMessageContent(recoveredMessage)
670
+ ? hydrateTextForAgent(recoveredMessage, data)
671
+ : hydrateTextForAgent(normalized, data);
672
+ if (hydrated.kind === "message" &&
673
+ hydrated.balloonBundleId !== "com.apple.messages.URLBalloonProvider" &&
674
+ hydrated.attachments.length > 0) {
675
+ const agentConfig = (0, identity_1.loadAgentConfig)();
676
+ const chatModel = agentConfig.humanFacing.model;
677
+ const chatProvider = agentConfig.humanFacing.provider;
678
+ const vlmDescribe = async (params) => {
679
+ if (chatProvider !== "minimax") {
680
+ throw new Error("VLM fallback requires a minimax credential for this agent — " +
681
+ "configure one or switch to a vision-capable chat model");
682
+ }
683
+ const { readProviderCredentialRecord } = await Promise.resolve().then(() => __importStar(require("../../heart/provider-credentials")));
684
+ const credential = await readProviderCredentialRecord((0, identity_1.getAgentName)(), "minimax");
685
+ const apiKey = credential.ok ? credential.record.credentials.apiKey : undefined;
686
+ if (!apiKey) {
687
+ throw new Error("VLM fallback: minimax API key not found in the agent vault — " +
688
+ "run `ouro auth --agent <agent> --provider minimax`");
689
+ }
690
+ return (0, minimax_vlm_1.minimaxVlmDescribe)({
691
+ apiKey: String(apiKey),
692
+ prompt: params.prompt,
693
+ imageDataUrl: params.imageDataUrl,
694
+ baseURL: minimax_1.MINIMAX_PROVIDER_BASE_URL,
695
+ attachmentGuid: params.attachmentGuid,
696
+ mimeType: params.mimeType,
697
+ chatModel: params.chatModel,
698
+ });
699
+ };
700
+ // VLM prompt context wants the user's raw inbound text — NOT
701
+ // the agent-facing rendering, which now carries the attachment
702
+ // marker after the B2 fix. Pull it from the source payload.
703
+ const rawUserText = typeof data.text === "string"
704
+ ? (data.text).trim()
705
+ : "";
706
+ const media = await (0, media_1.hydrateBlueBubblesAttachments)(hydrated.attachments, config, channelConfig, {
707
+ preferAudioInput: providerSupportsAudioInput(chatProvider),
708
+ chatModel,
709
+ vlmDescribe,
710
+ userText: rawUserText,
711
+ });
712
+ const transcriptSuffix = media.transcriptAdditions.map((entry) => `[${entry}]`).join("\n");
713
+ const noticeSuffix = media.notices.map((entry) => `[${entry}]`).join("\n");
714
+ const combinedSuffix = [transcriptSuffix, noticeSuffix].filter(Boolean).join("\n");
715
+ hydrated = {
716
+ ...hydrated,
717
+ inputPartsForAgent: media.inputParts.length > 0 ? media.inputParts : undefined,
718
+ textForAgent: [hydrated.textForAgent, combinedSuffix].filter(Boolean).join("\n"),
719
+ };
720
+ }
721
+ (0, runtime_1.emitNervesEvent)({
722
+ level: "warn",
723
+ component: "senses",
724
+ event: "senses.bluebubbles_repair_end",
725
+ message: "bluebubbles event repaired",
726
+ meta: {
727
+ kind: hydrated.kind,
728
+ messageGuid: hydrated.messageGuid,
729
+ repairedFrom: event.kind,
730
+ promotedFromMutation: event.kind === "mutation" && hydrated.kind === "message",
731
+ },
732
+ });
733
+ return hydrated;
734
+ }
735
+ catch (error) {
736
+ const reason = error instanceof Error ? error.message : String(error);
737
+ (0, runtime_1.emitNervesEvent)({
738
+ level: "warn",
739
+ component: "senses",
740
+ event: "senses.bluebubbles_repair_error",
741
+ message: "bluebubbles repair threw",
742
+ meta: {
743
+ messageGuid: event.messageGuid,
744
+ reason,
745
+ },
746
+ });
747
+ return applyRepairNotice(event, `BlueBubbles repair failed: ${reason}`);
748
+ }
749
+ },
750
+ async getMessageText(messageGuid) {
751
+ const url = buildRepairUrl(config.serverUrl, messageGuid, config.password);
752
+ try {
753
+ const response = await fetch(url, {
754
+ method: "GET",
755
+ signal: AbortSignal.timeout(channelConfig.requestTimeoutMs),
756
+ });
757
+ if (!response.ok) {
758
+ (0, runtime_1.emitNervesEvent)({
759
+ level: "warn",
760
+ component: "senses",
761
+ event: "senses.bluebubbles_get_message_text_error",
762
+ message: "failed to fetch message text",
763
+ meta: { messageGuid, status: response.status },
764
+ });
765
+ return null;
766
+ }
767
+ const payload = await parseJsonBody(response);
768
+ const data = extractRepairData(payload);
769
+ if (!data || typeof data.text !== "string") {
770
+ (0, runtime_1.emitNervesEvent)({
771
+ level: "warn",
772
+ component: "senses",
773
+ event: "senses.bluebubbles_get_message_text_error",
774
+ message: "message payload missing text field",
775
+ meta: { messageGuid, hasData: !!data, textType: data ? typeof data.text : "n/a" },
776
+ });
777
+ return null;
778
+ }
779
+ (0, runtime_1.emitNervesEvent)({
780
+ component: "senses",
781
+ event: "senses.bluebubbles_get_message_text",
782
+ message: "fetched message text by guid",
783
+ meta: { messageGuid },
784
+ });
785
+ return data.text.trim() || null;
786
+ }
787
+ catch (error) {
788
+ (0, runtime_1.emitNervesEvent)({
789
+ level: "warn",
790
+ component: "senses",
791
+ event: "senses.bluebubbles_get_message_text_error",
792
+ message: "exception fetching message text",
793
+ meta: { messageGuid, reason: error instanceof Error ? error.message : String(error) },
794
+ });
795
+ return null;
796
+ }
797
+ },
798
+ };
799
+ }