@ouro.bot/cli 0.1.0-alpha.83 → 0.1.0-alpha.831

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (647) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +154 -23
  3. package/RepairGuide.ouro/agent.json +5 -0
  4. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  5. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/assets/bluebubbles-host +264 -0
  14. package/assets/sanctuary-host-launcher.sh +16 -0
  15. package/changelog.json +5308 -16
  16. package/deploy/unraid/Dockerfile +54 -0
  17. package/deploy/unraid/README.txt +2983 -0
  18. package/deploy/unraid/audit-container-spec.sh +4 -0
  19. package/deploy/unraid/container-runtime.json +1 -0
  20. package/deploy/unraid/docker-man-template-transaction.mjs +711 -0
  21. package/deploy/unraid/docker-man-template-xml.cjs +105 -0
  22. package/deploy/unraid/migrate-sanctuary-bundle.mjs +60 -0
  23. package/deploy/unraid/ouro-events/bootstrap-spool.sh +92 -0
  24. package/deploy/unraid/ouro-events/emit-event.mjs +310 -0
  25. package/deploy/unraid/ouro-events/emit-usenet-event.sh +54 -0
  26. package/deploy/unraid/ouro-events/install-usenet-guard.sh +435 -0
  27. package/deploy/unraid/ouro-events/usenet-health.sh +176 -0
  28. package/deploy/unraid/sanctuary-acceptance-adapter.sh +43 -0
  29. package/deploy/unraid/sanctuary-acceptance-contract.json +198 -0
  30. package/deploy/unraid/sanctuary-acceptance-harness.sh +23 -0
  31. package/deploy/unraid/sanctuary-authority-installation.json +36 -0
  32. package/deploy/unraid/sanctuary-authority-service.sh +30 -0
  33. package/deploy/unraid/sanctuary-deployment-target.mjs +710 -0
  34. package/deploy/unraid/sanctuary-safe-rename.py +24 -0
  35. package/deploy/unraid/sanctuary-unit16-host-broker.mjs +2084 -0
  36. package/deploy/unraid/sanctuary-unit16-run.sh +560 -0
  37. package/deploy/unraid/sanctuary-unit18-target-audit.sh +27 -0
  38. package/deploy/unraid/sanctuary.ouro/agent.json +66 -0
  39. package/deploy/unraid/sanctuary.ouro/arc/README.md +3 -0
  40. package/deploy/unraid/sanctuary.ouro/bundle-meta.json +5 -0
  41. package/deploy/unraid/sanctuary.ouro/habits/sanctuary-health.md +8 -0
  42. package/deploy/unraid/sanctuary.ouro/mcp/media-mcp.mjs +795 -0
  43. package/deploy/unraid/sanctuary.ouro/provider-readiness.json +11 -0
  44. package/deploy/unraid/sanctuary.ouro/psyche/ASPIRATIONS.md +5 -0
  45. package/deploy/unraid/sanctuary.ouro/psyche/IDENTITY.md +5 -0
  46. package/deploy/unraid/sanctuary.ouro/psyche/LORE.md +15 -0
  47. package/deploy/unraid/sanctuary.ouro/psyche/SOUL.md +25 -0
  48. package/deploy/unraid/sanctuary.ouro/psyche/TACIT.md +15 -0
  49. package/deploy/unraid/sanctuary.ouro/state/policy/steward.json +7 -0
  50. package/deploy/unraid/sanctuary.ouro/tool-profiles.json +135 -0
  51. package/deploy/unraid/sanctuary.xml +28 -0
  52. package/dist/a2a/card.js +57 -0
  53. package/dist/a2a/client.js +180 -0
  54. package/dist/a2a/config.js +50 -0
  55. package/dist/a2a/delegation-stores.js +56 -0
  56. package/dist/a2a/did-resolution.js +93 -0
  57. package/dist/a2a/identity.js +170 -0
  58. package/dist/a2a/inbound-share.js +107 -0
  59. package/dist/a2a/mission-result-wire.js +196 -0
  60. package/dist/a2a/onboarding.js +115 -0
  61. package/dist/a2a/pin-store.js +132 -0
  62. package/dist/a2a/seen-ledger.js +120 -0
  63. package/dist/a2a/server.js +604 -0
  64. package/dist/a2a/task-store.js +69 -0
  65. package/dist/a2a/transport.js +45 -0
  66. package/dist/a2a/types.js +3 -0
  67. package/dist/arc/attention-types.js +8 -0
  68. package/dist/arc/cares.js +360 -0
  69. package/dist/arc/episodes.js +118 -0
  70. package/dist/arc/evolution.js +490 -0
  71. package/dist/arc/flight-recorder.js +1034 -0
  72. package/dist/arc/intentions.js +134 -0
  73. package/dist/arc/json-store.js +117 -0
  74. package/dist/arc/obligations.js +386 -0
  75. package/dist/arc/packets.js +336 -0
  76. package/dist/arc/presence.js +185 -0
  77. package/dist/arc/task-lifecycle.js +57 -0
  78. package/dist/commerce/store.js +755 -0
  79. package/dist/commerce/types.js +3 -0
  80. package/dist/heart/active-work.js +798 -40
  81. package/dist/heart/agent-entry.js +252 -3
  82. package/dist/heart/approval-files.js +113 -0
  83. package/dist/heart/approval-store.js +960 -0
  84. package/dist/heart/attachments/image-normalize.js +194 -0
  85. package/dist/heart/attachments/materialize.js +97 -0
  86. package/dist/heart/attachments/originals.js +88 -0
  87. package/dist/heart/attachments/render.js +29 -0
  88. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  89. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  90. package/dist/heart/attachments/sources/index.js +18 -0
  91. package/dist/heart/attachments/sources/telegram.js +71 -0
  92. package/dist/heart/attachments/store.js +132 -0
  93. package/dist/heart/attachments/types.js +93 -0
  94. package/dist/heart/auth/auth-flow.js +495 -0
  95. package/dist/heart/autonomy-budget.js +478 -0
  96. package/dist/heart/awaiting/await-alert.js +148 -0
  97. package/dist/heart/awaiting/await-expiry.js +143 -0
  98. package/dist/heart/awaiting/await-loader.js +91 -0
  99. package/dist/heart/awaiting/await-parser.js +149 -0
  100. package/dist/heart/awaiting/await-runtime-state.js +111 -0
  101. package/dist/heart/awaiting/await-scheduler.js +382 -0
  102. package/dist/heart/background-operations.js +281 -0
  103. package/dist/heart/bridges/manager.js +137 -17
  104. package/dist/heart/bridges/store.js +14 -2
  105. package/dist/heart/bundle-state.js +168 -0
  106. package/dist/heart/commitments.js +44 -18
  107. package/dist/heart/config-registry.js +331 -0
  108. package/dist/heart/config.js +174 -131
  109. package/dist/heart/context-loss-gauntlet.js +387 -0
  110. package/dist/heart/context-loss-sentinel.js +1157 -0
  111. package/dist/heart/core.js +2169 -581
  112. package/dist/heart/cross-chat-delivery.js +9 -22
  113. package/dist/heart/daemon/agent-config-check.js +451 -0
  114. package/dist/heart/daemon/agent-discovery.js +185 -3
  115. package/dist/heart/daemon/agent-service.js +542 -0
  116. package/dist/heart/daemon/agentic-repair.js +547 -0
  117. package/dist/heart/daemon/await-private-wake.js +59 -0
  118. package/dist/heart/daemon/bluebubbles-cli-integration.js +71 -0
  119. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  120. package/dist/heart/daemon/bluebubbles-host-protocol.js +433 -0
  121. package/dist/heart/daemon/bluebubbles-host.js +273 -0
  122. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  123. package/dist/heart/daemon/cadence.js +180 -0
  124. package/dist/heart/daemon/cli-defaults.js +854 -0
  125. package/dist/heart/daemon/cli-desk.js +322 -0
  126. package/dist/heart/daemon/cli-exec.js +8822 -0
  127. package/dist/heart/daemon/cli-help.js +716 -0
  128. package/dist/heart/daemon/cli-parse.js +2771 -0
  129. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  130. package/dist/heart/daemon/cli-render.js +777 -0
  131. package/dist/heart/daemon/cli-types.js +8 -0
  132. package/dist/heart/daemon/connect-bay.js +323 -0
  133. package/dist/heart/daemon/container-credential-bootstrap.js +273 -0
  134. package/dist/heart/daemon/container-healthcheck.js +112 -0
  135. package/dist/heart/daemon/container-runtime.js +97 -0
  136. package/dist/heart/daemon/container-spec-auditor-main.js +171 -0
  137. package/dist/heart/daemon/container-spec-auditor.js +229 -0
  138. package/dist/heart/daemon/daemon-bootstrap-startup.js +115 -0
  139. package/dist/heart/daemon/daemon-cli.js +29 -2349
  140. package/dist/heart/daemon/daemon-entry.js +930 -11
  141. package/dist/heart/daemon/daemon-health.js +186 -0
  142. package/dist/heart/daemon/daemon-rollup.js +57 -0
  143. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  144. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  145. package/dist/heart/daemon/daemon.js +2084 -105
  146. package/dist/heart/daemon/dns-workflow.js +394 -0
  147. package/dist/heart/daemon/doctor-types.js +8 -0
  148. package/dist/heart/daemon/doctor.js +1755 -0
  149. package/dist/heart/daemon/freshness.js +345 -0
  150. package/dist/heart/daemon/habit-private-wake.js +61 -0
  151. package/dist/heart/daemon/health-monitor.js +142 -11
  152. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  153. package/dist/heart/daemon/hooks/bundle-meta.js +135 -1
  154. package/dist/heart/daemon/http-health-probe.js +80 -0
  155. package/dist/heart/daemon/human-command-screens.js +234 -0
  156. package/dist/heart/daemon/human-readiness.js +114 -0
  157. package/dist/heart/daemon/inner-status.js +78 -0
  158. package/dist/heart/daemon/interactive-repair.js +394 -0
  159. package/dist/heart/daemon/launchd.js +37 -8
  160. package/dist/heart/daemon/log-tailer.js +79 -10
  161. package/dist/heart/daemon/logs-prune.js +132 -0
  162. package/dist/heart/daemon/mcp-canary.js +524 -0
  163. package/dist/heart/daemon/message-router.js +65 -5
  164. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  165. package/dist/heart/daemon/os-cron-deps.js +135 -0
  166. package/dist/heart/daemon/os-cron.js +22 -14
  167. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  168. package/dist/heart/daemon/ouro-entry.js +3 -1
  169. package/dist/heart/daemon/plugin-cli.js +432 -0
  170. package/dist/heart/daemon/process-manager.js +733 -61
  171. package/dist/heart/daemon/provider-discovery.js +137 -0
  172. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  173. package/dist/heart/daemon/prunable-bundle.js +144 -0
  174. package/dist/heart/daemon/pulse.js +511 -0
  175. package/dist/heart/daemon/readiness-repair.js +365 -0
  176. package/dist/heart/daemon/run-hooks.js +2 -0
  177. package/dist/heart/daemon/runtime-logging.js +47 -14
  178. package/dist/heart/daemon/runtime-metadata.js +2 -30
  179. package/dist/heart/daemon/runtime-mode.js +13 -2
  180. package/dist/heart/daemon/safe-mode.js +161 -0
  181. package/dist/heart/daemon/sanctuary-acceptance-adapter.js +2654 -0
  182. package/dist/heart/daemon/sanctuary-acceptance-harness.js +1830 -0
  183. package/dist/heart/daemon/sanctuary-acceptance-marker.js +267 -0
  184. package/dist/heart/daemon/sanctuary-acceptance-scenarios.js +955 -0
  185. package/dist/heart/daemon/sanctuary-authority-codec.js +86 -0
  186. package/dist/heart/daemon/sanctuary-authority-epoch.js +256 -0
  187. package/dist/heart/daemon/sanctuary-authority-installation.js +140 -0
  188. package/dist/heart/daemon/sanctuary-authority-ledger.js +241 -0
  189. package/dist/heart/daemon/sanctuary-authority-root-lifecycle.js +819 -0
  190. package/dist/heart/daemon/sanctuary-authority-vault-migration.js +79 -0
  191. package/dist/heart/daemon/sanctuary-bundle-migration.js +729 -0
  192. package/dist/heart/daemon/sanctuary-host-authority.js +1008 -0
  193. package/dist/heart/daemon/sanctuary-host-detached-supervisor.js +494 -0
  194. package/dist/heart/daemon/sanctuary-host-executor.js +670 -0
  195. package/dist/heart/daemon/sanctuary-host-linux-kernel.js +334 -0
  196. package/dist/heart/daemon/sanctuary-host-supervisor-entry.js +207 -0
  197. package/dist/heart/daemon/sanctuary-host-supervisor.js +95 -0
  198. package/dist/heart/daemon/sanctuary-package-management.js +103 -0
  199. package/dist/heart/daemon/sanctuary-scheduler-liveness.js +227 -0
  200. package/dist/heart/daemon/sanctuary-scheduler-origin.js +132 -0
  201. package/dist/heart/daemon/sanctuary-telegram-authority-entry.js +445 -0
  202. package/dist/heart/daemon/sanctuary-telegram-authority-gateway.js +585 -0
  203. package/dist/heart/daemon/sanctuary-telegram-authority-service.js +630 -0
  204. package/dist/heart/daemon/sense-manager.js +699 -48
  205. package/dist/heart/daemon/session-id-resolver.js +131 -0
  206. package/dist/heart/daemon/skill-management-installer.js +1 -1
  207. package/dist/heart/daemon/socket-client.js +180 -12
  208. package/dist/heart/daemon/stale-bundle-prune.js +113 -0
  209. package/dist/heart/daemon/startup-tui.js +339 -0
  210. package/dist/heart/daemon/supercronic-supervisor.js +282 -0
  211. package/dist/heart/daemon/task-scheduler.js +117 -39
  212. package/dist/heart/daemon/terminal-ui.js +499 -0
  213. package/dist/heart/daemon/thoughts.js +138 -54
  214. package/dist/heart/daemon/up-progress.js +366 -0
  215. package/dist/heart/daemon/vault-items.js +56 -0
  216. package/dist/heart/delegation.js +1 -4
  217. package/dist/heart/external-events/router.js +1430 -0
  218. package/dist/heart/frontend-approval-runtime.js +506 -0
  219. package/dist/heart/frontend-journal.js +215 -0
  220. package/dist/heart/frontend-session-service.js +237 -0
  221. package/dist/heart/frontend-socket-client.js +164 -0
  222. package/dist/heart/frontend-socket.js +400 -0
  223. package/dist/heart/habits/habit-cancel.js +810 -0
  224. package/dist/heart/habits/habit-lifecycle.js +1327 -0
  225. package/dist/heart/habits/habit-migration.js +194 -0
  226. package/dist/heart/habits/habit-parser.js +278 -0
  227. package/dist/heart/habits/habit-runtime-state.js +93 -0
  228. package/dist/heart/habits/habit-scheduler.js +653 -0
  229. package/dist/heart/habits/habit-session-summary.js +318 -0
  230. package/dist/heart/habits/habit-session.js +636 -0
  231. package/dist/heart/{daemon → hatch}/hatch-flow.js +55 -62
  232. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  233. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  234. package/dist/heart/{daemon → hatch}/specialist-tools.js +53 -18
  235. package/dist/heart/identity.js +196 -59
  236. package/dist/heart/kept-notes.js +289 -0
  237. package/dist/heart/kicks.js +1 -1
  238. package/dist/heart/machine-identity.js +161 -0
  239. package/dist/heart/mail-import-discovery.js +356 -0
  240. package/dist/heart/mailbox/mailbox-http-hooks.js +98 -0
  241. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  242. package/dist/heart/mailbox/mailbox-http-routes.js +398 -0
  243. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  244. package/dist/heart/mailbox/mailbox-http-transport.js +129 -0
  245. package/dist/heart/mailbox/mailbox-http.js +99 -0
  246. package/dist/heart/mailbox/mailbox-read.js +39 -0
  247. package/dist/heart/mailbox/mailbox-types.js +27 -0
  248. package/dist/heart/mailbox/mailbox-view.js +197 -0
  249. package/dist/heart/mailbox/readers/agent-machine.js +428 -0
  250. package/dist/heart/mailbox/readers/continuity-readers.js +329 -0
  251. package/dist/heart/mailbox/readers/mail.js +375 -0
  252. package/dist/heart/mailbox/readers/runtime-readers.js +823 -0
  253. package/dist/heart/mailbox/readers/sessions.js +231 -0
  254. package/dist/heart/mailbox/readers/shared.js +111 -0
  255. package/dist/heart/mcp/mcp-server.js +696 -0
  256. package/dist/heart/migrate-config.js +100 -0
  257. package/dist/heart/model-capabilities.js +11 -0
  258. package/dist/heart/orientation-frame.js +345 -0
  259. package/dist/heart/platform.js +81 -0
  260. package/dist/heart/primitives.js +1 -1
  261. package/dist/heart/private-runtime/decision-renderer.js +158 -0
  262. package/dist/heart/private-runtime/index.js +18 -0
  263. package/dist/heart/private-runtime/ledger.js +221 -0
  264. package/dist/heart/private-runtime/policy.js +252 -0
  265. package/dist/heart/private-runtime/types.js +2 -0
  266. package/dist/heart/progress-story.js +1 -1
  267. package/dist/heart/provider-attempt.js +137 -0
  268. package/dist/heart/provider-binding-resolver.js +273 -0
  269. package/dist/heart/provider-credentials.js +449 -0
  270. package/dist/heart/provider-failover.js +311 -0
  271. package/dist/heart/provider-models.js +96 -0
  272. package/dist/heart/provider-ping.js +265 -0
  273. package/dist/heart/provider-readiness-cache.js +119 -0
  274. package/dist/heart/provider-visibility.js +188 -0
  275. package/dist/heart/providers/anthropic-token.js +131 -0
  276. package/dist/heart/providers/anthropic.js +173 -60
  277. package/dist/heart/providers/azure.js +23 -11
  278. package/dist/heart/providers/error-classification.js +127 -0
  279. package/dist/heart/providers/github-copilot.js +34 -38
  280. package/dist/heart/providers/minimax-vlm.js +189 -0
  281. package/dist/heart/providers/minimax.js +26 -8
  282. package/dist/heart/providers/openai-codex-token.js +349 -0
  283. package/dist/heart/providers/openai-codex.js +55 -40
  284. package/dist/heart/providers/openai-compatible.js +177 -0
  285. package/dist/heart/run-ledger.js +247 -0
  286. package/dist/heart/runtime-capability-check.js +170 -0
  287. package/dist/heart/runtime-credentials.js +607 -0
  288. package/dist/heart/runtime-cwd.js +87 -0
  289. package/dist/heart/sense-truth.js +22 -4
  290. package/dist/heart/session-activity.js +92 -24
  291. package/dist/heart/session-events.js +1504 -0
  292. package/dist/heart/session-playback-cli-main.js +5 -0
  293. package/dist/heart/session-playback-cli.js +36 -0
  294. package/dist/heart/session-playback.js +231 -0
  295. package/dist/heart/session-redaction-repair-cli-main.js +31 -0
  296. package/dist/heart/session-redaction-repair.js +552 -0
  297. package/dist/heart/session-stats-cli-main.js +5 -0
  298. package/dist/heart/session-stats.js +183 -0
  299. package/dist/heart/session-transcript.js +133 -0
  300. package/dist/heart/start-of-turn-packet.js +372 -0
  301. package/dist/heart/steward-policy.js +618 -0
  302. package/dist/heart/streaming.js +604 -207
  303. package/dist/heart/structured-output.js +196 -0
  304. package/dist/heart/sync-classification.js +176 -0
  305. package/dist/heart/sync.js +449 -0
  306. package/dist/heart/target-resolution.js +11 -7
  307. package/dist/heart/tempo.js +93 -0
  308. package/dist/heart/temporal-view.js +41 -0
  309. package/dist/heart/timeouts.js +101 -0
  310. package/dist/heart/tool-activity-callbacks.js +59 -0
  311. package/dist/heart/tool-approval.js +382 -0
  312. package/dist/heart/tool-description.js +155 -0
  313. package/dist/heart/tool-friction.js +55 -0
  314. package/dist/heart/tool-loop.js +200 -0
  315. package/dist/heart/turn-context.js +482 -0
  316. package/dist/heart/turn-execution-lease.js +30 -0
  317. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  318. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  319. package/dist/heart/versioning/ouro-path-installer.js +432 -0
  320. package/dist/heart/versioning/ouro-recovery-launcher.js +76 -0
  321. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  322. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  323. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  324. package/dist/heart/versioning/update-hooks.js +154 -0
  325. package/dist/heart/versioning/version-intent.js +114 -0
  326. package/dist/heart/work-card.js +380 -0
  327. package/dist/mailbox-ui/assets/index-Cyv4mw3Y.js +1 -0
  328. package/dist/mailbox-ui/assets/index-Du_9G9WO.css +1 -0
  329. package/dist/mailbox-ui/assets/vendor-CcN1XpQ9.js +61 -0
  330. package/dist/mailbox-ui/index.html +16 -0
  331. package/dist/mailroom/attention.js +167 -0
  332. package/dist/mailroom/autonomy.js +209 -0
  333. package/dist/mailroom/blob-store.js +889 -0
  334. package/dist/mailroom/body-cache.js +61 -0
  335. package/dist/mailroom/cache-sync-cli.js +58 -0
  336. package/dist/mailroom/core.js +803 -0
  337. package/dist/mailroom/entry.js +160 -0
  338. package/dist/mailroom/file-store.js +568 -0
  339. package/dist/mailroom/hosted-cache-sync.js +384 -0
  340. package/dist/mailroom/mbox-import.js +393 -0
  341. package/dist/mailroom/migration.js +164 -0
  342. package/dist/mailroom/outbound.js +380 -0
  343. package/dist/mailroom/policy.js +263 -0
  344. package/dist/mailroom/reader.js +292 -0
  345. package/dist/mailroom/search-cache.js +513 -0
  346. package/dist/mailroom/search-relevance.js +319 -0
  347. package/dist/mailroom/smtp-ingress.js +176 -0
  348. package/dist/mailroom/source-state.js +176 -0
  349. package/dist/mailroom/thread.js +109 -0
  350. package/dist/mailroom/travel-extract.js +89 -0
  351. package/dist/mind/bundle-manifest.js +24 -2
  352. package/dist/mind/context.js +309 -111
  353. package/dist/mind/desk-section.js +362 -0
  354. package/dist/mind/diary-integrity.js +60 -0
  355. package/dist/mind/{memory.js → diary.js} +68 -77
  356. package/dist/mind/embedding-provider.js +60 -0
  357. package/dist/mind/file-state.js +179 -0
  358. package/dist/mind/{associative-recall.js → note-search.js} +47 -58
  359. package/dist/mind/obligation-steering.js +199 -3
  360. package/dist/mind/pending.js +36 -10
  361. package/dist/mind/prompt-budget.js +479 -0
  362. package/dist/mind/prompt-refresh.js +3 -2
  363. package/dist/mind/prompt.js +1050 -189
  364. package/dist/mind/provenance-trust.js +26 -0
  365. package/dist/mind/record-paths.js +312 -0
  366. package/dist/mind/scrutiny.js +173 -0
  367. package/dist/mind/session-transaction.js +564 -0
  368. package/dist/nerves/cli-logging.js +7 -1
  369. package/dist/nerves/coverage/audit-rules.js +15 -6
  370. package/dist/nerves/coverage/audit.js +28 -2
  371. package/dist/nerves/coverage/cli.js +1 -1
  372. package/dist/nerves/coverage/contract.js +5 -5
  373. package/dist/nerves/coverage/file-completeness.js +139 -5
  374. package/dist/nerves/coverage/run-artifacts.js +55 -35
  375. package/dist/nerves/coverage/source-scanner.js +4 -4
  376. package/dist/nerves/event-buffer.js +111 -0
  377. package/dist/nerves/index.js +293 -9
  378. package/dist/nerves/observation.js +20 -0
  379. package/dist/nerves/redact.js +79 -0
  380. package/dist/nerves/review/cli-main.js +5 -0
  381. package/dist/nerves/review/cli.js +156 -0
  382. package/dist/nerves/review/core.js +159 -0
  383. package/dist/nerves/runtime.js +17 -1
  384. package/dist/repertoire/ado-client.js +15 -56
  385. package/dist/repertoire/ado-semantic.js +16 -10
  386. package/dist/repertoire/api-client.js +97 -0
  387. package/dist/repertoire/bitwarden-store.js +1045 -0
  388. package/dist/repertoire/bundle-templates.js +71 -0
  389. package/dist/repertoire/bw-installer.js +180 -0
  390. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  391. package/dist/repertoire/coding/context-pack.js +331 -0
  392. package/dist/repertoire/coding/feedback.js +174 -32
  393. package/dist/repertoire/coding/index.js +15 -3
  394. package/dist/repertoire/coding/manager.js +159 -10
  395. package/dist/repertoire/coding/spawner.js +58 -11
  396. package/dist/repertoire/coding/tools.js +221 -15
  397. package/dist/repertoire/coding/workbench-client.js +272 -0
  398. package/dist/repertoire/coding/workbench-manager.js +346 -0
  399. package/dist/repertoire/commerce-errors.js +109 -0
  400. package/dist/repertoire/commerce-self-test.js +156 -0
  401. package/dist/repertoire/credential-access.js +178 -0
  402. package/dist/repertoire/desk/classifier.js +362 -0
  403. package/dist/repertoire/duffel-client.js +185 -0
  404. package/dist/repertoire/github-client.js +14 -55
  405. package/dist/repertoire/graph-client.js +11 -52
  406. package/dist/repertoire/guardrails.js +811 -18
  407. package/dist/repertoire/mcp-client.js +44 -3
  408. package/dist/repertoire/mcp-manager.js +427 -139
  409. package/dist/repertoire/mcp-tools.js +124 -0
  410. package/dist/repertoire/plugin-mcp.js +175 -0
  411. package/dist/repertoire/plugins.js +253 -0
  412. package/dist/repertoire/relationship-authorization.js +322 -0
  413. package/dist/repertoire/shell-sessions.js +134 -0
  414. package/dist/repertoire/skills.js +48 -4
  415. package/dist/repertoire/stripe-client.js +131 -0
  416. package/dist/repertoire/tool-arguments.js +170 -0
  417. package/dist/repertoire/tool-results.js +29 -0
  418. package/dist/repertoire/tools-a2a.js +699 -0
  419. package/dist/repertoire/tools-attachments.js +322 -0
  420. package/dist/repertoire/tools-awaiting.js +575 -0
  421. package/dist/repertoire/tools-base.js +77 -1138
  422. package/dist/repertoire/tools-bluebubbles.js +2 -0
  423. package/dist/repertoire/tools-bridge.js +144 -0
  424. package/dist/repertoire/tools-bundle.js +993 -0
  425. package/dist/repertoire/tools-commerce.js +253 -0
  426. package/dist/repertoire/tools-config.js +186 -0
  427. package/dist/repertoire/tools-continuity.js +575 -0
  428. package/dist/repertoire/tools-credential.js +383 -0
  429. package/dist/repertoire/tools-evolution.js +527 -0
  430. package/dist/repertoire/tools-files.js +344 -0
  431. package/dist/repertoire/tools-flight.js +290 -0
  432. package/dist/repertoire/tools-flow.js +119 -0
  433. package/dist/repertoire/tools-github.js +3 -8
  434. package/dist/repertoire/tools-habits.js +103 -0
  435. package/dist/repertoire/tools-mail.js +1828 -0
  436. package/dist/repertoire/tools-notes.js +485 -0
  437. package/dist/repertoire/tools-obligations.js +182 -0
  438. package/dist/repertoire/tools-orientation.js +31 -0
  439. package/dist/repertoire/tools-record.js +482 -0
  440. package/dist/repertoire/tools-rsvp.js +139 -0
  441. package/dist/repertoire/tools-runtime.js +150 -0
  442. package/dist/repertoire/tools-sanctuary-host.js +202 -0
  443. package/dist/repertoire/tools-session.js +1133 -0
  444. package/dist/repertoire/tools-shell.js +149 -0
  445. package/dist/repertoire/tools-steward-policy.js +119 -0
  446. package/dist/repertoire/tools-stripe.js +224 -0
  447. package/dist/repertoire/tools-surface.js +369 -0
  448. package/dist/repertoire/tools-teams.js +12 -39
  449. package/dist/repertoire/tools-telegram-contacts.js +37 -0
  450. package/dist/repertoire/tools-travel.js +125 -0
  451. package/dist/repertoire/tools-trip.js +982 -0
  452. package/dist/repertoire/tools-unraid.js +531 -0
  453. package/dist/repertoire/tools-user-profile.js +146 -0
  454. package/dist/repertoire/tools-vault.js +40 -0
  455. package/dist/repertoire/tools-voice.js +145 -0
  456. package/dist/repertoire/tools.js +494 -148
  457. package/dist/repertoire/travel-api-client.js +360 -0
  458. package/dist/repertoire/unraid-client.js +155 -0
  459. package/dist/repertoire/unraid-restart.js +339 -0
  460. package/dist/repertoire/user-profile.js +131 -0
  461. package/dist/repertoire/vault-setup.js +246 -0
  462. package/dist/repertoire/vault-unlock.js +628 -0
  463. package/dist/rsvp/aisleplanner-client.js +354 -0
  464. package/dist/rsvp/cli.js +926 -0
  465. package/dist/rsvp/config.js +327 -0
  466. package/dist/rsvp/cutover.js +433 -0
  467. package/dist/rsvp/diagnostics.js +232 -0
  468. package/dist/rsvp/diff-renderer.js +176 -0
  469. package/dist/rsvp/habit-policy.js +110 -0
  470. package/dist/rsvp/habit-stage.js +123 -0
  471. package/dist/rsvp/incident-bundle.js +97 -0
  472. package/dist/rsvp/migration.js +204 -0
  473. package/dist/rsvp/native-habit-runner.js +630 -0
  474. package/dist/rsvp/outbound-state.js +628 -0
  475. package/dist/rsvp/query.js +118 -0
  476. package/dist/rsvp/replay.js +233 -0
  477. package/dist/rsvp/snapshot.js +232 -0
  478. package/dist/rsvp/spend-ledger.js +175 -0
  479. package/dist/scripts/claude-code-hook.js +41 -0
  480. package/dist/scripts/claude-code-stop-hook.js +47 -0
  481. package/dist/senses/a2a-entry.js +115 -0
  482. package/dist/senses/acp-server.js +386 -0
  483. package/dist/senses/attention-queue.js +186 -0
  484. package/dist/senses/await-turn-message.js +58 -0
  485. package/dist/senses/bluebubbles/active-turns.js +216 -0
  486. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  487. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  488. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +355 -40
  489. package/dist/senses/bluebubbles/context-packet.js +207 -0
  490. package/dist/senses/bluebubbles/context-smoke.js +144 -0
  491. package/dist/senses/bluebubbles/entry.js +90 -0
  492. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +21 -3
  493. package/dist/senses/bluebubbles/index.js +3841 -0
  494. package/dist/senses/bluebubbles/latest-turn.js +311 -0
  495. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  496. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +159 -28
  497. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +24 -13
  498. package/dist/senses/bluebubbles/outbound-state.js +308 -0
  499. package/dist/senses/bluebubbles/processed-log.js +133 -0
  500. package/dist/senses/bluebubbles/reaction-policy.js +47 -0
  501. package/dist/senses/bluebubbles/replay.js +284 -0
  502. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  503. package/dist/senses/bluebubbles/semantic-receipts.js +1986 -0
  504. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  505. package/dist/senses/bluebubbles/webhook-registration.js +228 -0
  506. package/dist/senses/bluebubbles-meta-guard.js +39 -0
  507. package/dist/senses/cli/bracketed-paste.js +82 -0
  508. package/dist/senses/cli/image-paste.js +287 -0
  509. package/dist/senses/cli/image-ref-navigation.js +75 -0
  510. package/dist/senses/cli/ink-app.js +156 -0
  511. package/dist/senses/cli/inline-diff.js +64 -0
  512. package/dist/senses/cli/input-keys.js +174 -0
  513. package/dist/senses/cli/kill-ring.js +86 -0
  514. package/dist/senses/cli/message-list.js +51 -0
  515. package/dist/senses/cli/ouro-tui.js +607 -0
  516. package/dist/senses/cli/spinner-imperative.js +135 -0
  517. package/dist/senses/cli/spinner.js +101 -0
  518. package/dist/senses/cli/status-line.js +60 -0
  519. package/dist/senses/cli/streaming-markdown.js +526 -0
  520. package/dist/senses/cli/tool-display.js +85 -0
  521. package/dist/senses/cli/tool-render.js +85 -0
  522. package/dist/senses/cli/tui-store.js +241 -0
  523. package/dist/senses/cli/virtual-list.js +35 -0
  524. package/dist/senses/cli-entry.js +60 -8
  525. package/dist/senses/cli.js +604 -320
  526. package/dist/senses/commands.js +66 -3
  527. package/dist/senses/context-packet-ledger.js +371 -0
  528. package/dist/senses/context-packets.js +154 -0
  529. package/dist/senses/habit-lifecycle-guard.js +24 -0
  530. package/dist/senses/habit-turn-message.js +160 -0
  531. package/dist/senses/ingress-evidence.js +2 -0
  532. package/dist/senses/mail-entry.js +66 -0
  533. package/dist/senses/mail.js +524 -0
  534. package/dist/senses/pipeline.js +1115 -204
  535. package/dist/senses/private-runtime-worker.js +859 -0
  536. package/dist/senses/private-runtime.js +1517 -0
  537. package/dist/senses/proactive-content-guard.js +51 -0
  538. package/dist/senses/root-host-approval-port.js +345 -0
  539. package/dist/senses/root-host-approval-runtime.js +393 -0
  540. package/dist/senses/sanctuary-authority-resident.js +102 -0
  541. package/dist/senses/sanctuary-download-credit-presentation.js +31 -0
  542. package/dist/senses/sanctuary-full-visibility-contract.js +302 -0
  543. package/dist/senses/sanctuary-grounding.js +118 -0
  544. package/dist/senses/sanctuary-health-acceptance-probe-entry.js +12 -0
  545. package/dist/senses/sanctuary-health-acceptance-probe.js +774 -0
  546. package/dist/senses/sanctuary-health-runner.js +100 -0
  547. package/dist/senses/sanctuary-health.js +408 -0
  548. package/dist/senses/sanctuary-install-state-contract.js +126 -0
  549. package/dist/senses/sanctuary-interactive-control.js +410 -0
  550. package/dist/senses/sanctuary-media-catalog-contract.js +297 -0
  551. package/dist/senses/sanctuary-media-optimization.js +514 -0
  552. package/dist/senses/sanctuary-runtime.js +340 -0
  553. package/dist/senses/sanctuary-sab.js +85 -0
  554. package/dist/senses/sanctuary-storage-optimization-contract.js +32 -0
  555. package/dist/senses/shared-turn.js +772 -0
  556. package/dist/senses/surface-tool.js +109 -0
  557. package/dist/senses/teams-entry.js +60 -8
  558. package/dist/senses/teams.js +519 -218
  559. package/dist/senses/telegram-admission.js +718 -0
  560. package/dist/senses/telegram-approval-runtime.js +793 -0
  561. package/dist/senses/telegram-attachments.js +186 -0
  562. package/dist/senses/telegram-audit-ledger.js +220 -0
  563. package/dist/senses/telegram-authority-transport.js +231 -0
  564. package/dist/senses/telegram-client.js +1749 -0
  565. package/dist/senses/telegram-effect-adapter.js +896 -0
  566. package/dist/senses/telegram-entry.js +83 -0
  567. package/dist/senses/telegram.js +2324 -0
  568. package/dist/senses/trust-gate.js +104 -9
  569. package/dist/senses/voice/audio-playback.js +237 -0
  570. package/dist/senses/voice/audio-routing.js +119 -0
  571. package/dist/senses/voice/elevenlabs.js +202 -0
  572. package/dist/senses/voice/floor-control.js +431 -0
  573. package/dist/senses/voice/floor-controller.js +115 -0
  574. package/dist/senses/voice/golden-path.js +116 -0
  575. package/dist/senses/voice/index.js +29 -0
  576. package/dist/senses/voice/meeting.js +113 -0
  577. package/dist/senses/voice/outbound.js +190 -0
  578. package/dist/senses/voice/phone.js +33 -0
  579. package/dist/senses/voice/playback.js +139 -0
  580. package/dist/senses/voice/realtime-eval.js +496 -0
  581. package/dist/senses/voice/realtime-trace.js +531 -0
  582. package/dist/senses/voice/transcript.js +70 -0
  583. package/dist/senses/voice/turn.js +191 -0
  584. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  585. package/dist/senses/voice/twilio-phone.js +5031 -0
  586. package/dist/senses/voice/types.js +2 -0
  587. package/dist/senses/voice/whisper.js +161 -0
  588. package/dist/senses/voice-entry.js +81 -0
  589. package/dist/senses/voice-realtime-eval-command.js +99 -0
  590. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  591. package/dist/senses/voice-twilio-entry.js +87 -0
  592. package/dist/trips/core.js +138 -0
  593. package/dist/trips/store.js +265 -0
  594. package/dist/util/frontmatter.js +69 -0
  595. package/npm-shrinkwrap.json +8138 -0
  596. package/package.json +72 -13
  597. package/skills/agent-commerce.md +113 -0
  598. package/skills/browser-navigation.md +117 -0
  599. package/skills/commerce-setup-guide.md +116 -0
  600. package/skills/commerce-setup.md +84 -0
  601. package/skills/configure-dev-tools.md +99 -0
  602. package/skills/travel-planning.md +138 -0
  603. package/dist/heart/daemon/auth-flow.js +0 -430
  604. package/dist/heart/daemon/ouro-path-installer.js +0 -260
  605. package/dist/heart/daemon/ouro-version-manager.js +0 -171
  606. package/dist/heart/daemon/update-hooks.js +0 -138
  607. package/dist/heart/obligations.js +0 -191
  608. package/dist/heart/safe-workspace.js +0 -228
  609. package/dist/heart/session-recall.js +0 -116
  610. package/dist/mind/friends/channel.js +0 -84
  611. package/dist/mind/friends/group-context.js +0 -144
  612. package/dist/mind/friends/resolver.js +0 -84
  613. package/dist/mind/friends/store-file.js +0 -190
  614. package/dist/mind/friends/store.js +0 -4
  615. package/dist/mind/friends/tokens.js +0 -26
  616. package/dist/mind/friends/trust-explanation.js +0 -74
  617. package/dist/mind/friends/types.js +0 -29
  618. package/dist/repertoire/tasks/board.js +0 -134
  619. package/dist/repertoire/tasks/index.js +0 -224
  620. package/dist/repertoire/tasks/lifecycle.js +0 -80
  621. package/dist/repertoire/tasks/middleware.js +0 -65
  622. package/dist/repertoire/tasks/parser.js +0 -173
  623. package/dist/repertoire/tasks/scanner.js +0 -132
  624. package/dist/repertoire/tasks/transitions.js +0 -144
  625. package/dist/senses/bluebubbles-entry.js +0 -13
  626. package/dist/senses/bluebubbles.js +0 -1181
  627. package/dist/senses/debug-activity.js +0 -154
  628. package/dist/senses/inner-dialog-worker.js +0 -90
  629. package/dist/senses/inner-dialog.js +0 -525
  630. package/subagents/README.md +0 -7
  631. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  632. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  633. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  634. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  635. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  636. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  637. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  638. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  639. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  640. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  641. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  642. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  643. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  644. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  645. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  646. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  647. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.findObsoleteBlueBubblesThreadSessions = findObsoleteBlueBubblesThreadSessions;
37
37
  const fs = __importStar(require("node:fs"));
38
38
  const path = __importStar(require("node:path"));
39
- const runtime_1 = require("../nerves/runtime");
39
+ const runtime_1 = require("../../nerves/runtime");
40
40
  function findObsoleteBlueBubblesThreadSessions(trunkSessionPath) {
41
41
  const normalized = trunkSessionPath.trim();
42
42
  if (!normalized.endsWith(".json"))
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BLUEBUBBLES_WEBHOOK_RECONCILE_INTERVAL_MS = void 0;
4
+ exports.blueBubblesWebhookOwnerToken = blueBubblesWebhookOwnerToken;
5
+ exports.buildBlueBubblesWebhookCallbackUrl = buildBlueBubblesWebhookCallbackUrl;
6
+ exports.sanitizeBlueBubblesWebhookText = sanitizeBlueBubblesWebhookText;
7
+ exports.inspectBlueBubblesWebhookRegistration = inspectBlueBubblesWebhookRegistration;
8
+ exports.reconcileBlueBubblesWebhookRegistration = reconcileBlueBubblesWebhookRegistration;
9
+ exports.createBlueBubblesWebhookReconciler = createBlueBubblesWebhookReconciler;
10
+ const crypto_1 = require("crypto");
11
+ const runtime_1 = require("../../nerves/runtime");
12
+ exports.BLUEBUBBLES_WEBHOOK_RECONCILE_INTERVAL_MS = 180_000;
13
+ function result(state, detail, counts = {}) {
14
+ return {
15
+ ok: state === "exact",
16
+ state,
17
+ changed: counts.changed ?? false,
18
+ ownedCount: counts.ownedCount ?? 0,
19
+ exactCount: counts.exactCount ?? 0,
20
+ detail,
21
+ };
22
+ }
23
+ function blueBubblesWebhookOwnerToken(agentName, machineId) {
24
+ return `v1_${(0, crypto_1.createHash)("sha256").update(`ouro-bluebubbles-webhook\0${agentName}\0${machineId}`).digest("hex").slice(0, 32)}`;
25
+ }
26
+ function buildBlueBubblesWebhookCallbackUrl(input) {
27
+ const callback = new URL(`http://127.0.0.1:${input.callbackPort}`);
28
+ callback.pathname = input.callbackPath.startsWith("/") ? input.callbackPath : `/${input.callbackPath}`;
29
+ callback.searchParams.set("password", input.password);
30
+ callback.searchParams.set("ouroWebhook", blueBubblesWebhookOwnerToken(input.agentName, input.machineId));
31
+ return callback.toString();
32
+ }
33
+ function apiUrl(input, id) {
34
+ const base = `${input.serverUrl.replace(/\/+$/, "")}/api/v1/webhook${id === undefined ? "" : `/${id}`}`;
35
+ const url = new URL(base);
36
+ url.searchParams.set("password", input.password);
37
+ return url.toString();
38
+ }
39
+ function sanitizeBlueBubblesWebhookText(text, input) {
40
+ const owner = blueBubblesWebhookOwnerToken(input.agentName, input.machineId);
41
+ return text
42
+ .replaceAll(input.password, "[redacted]")
43
+ .replaceAll(owner, "[redacted]")
44
+ .replace(/(https?:\/\/[^\s?]+)\?[^\s]*/g, "$1?[redacted]");
45
+ }
46
+ function isWebhook(value) {
47
+ if (!value || typeof value !== "object")
48
+ return false;
49
+ const row = value;
50
+ return Number.isInteger(row.id)
51
+ && typeof row.url === "string"
52
+ && Array.isArray(row.events)
53
+ && row.events.every((event) => typeof event === "string");
54
+ }
55
+ function ownedBy(urlText, owner) {
56
+ try {
57
+ return new URL(urlText).searchParams.get("ouroWebhook") === owner;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ function exactUnmarked(urlText, desiredUrl) {
64
+ try {
65
+ const candidate = new URL(urlText);
66
+ const desired = new URL(desiredUrl);
67
+ if (candidate.searchParams.has("ouroWebhook"))
68
+ return false;
69
+ desired.searchParams.delete("ouroWebhook");
70
+ return candidate.toString() === desired.toString();
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ function exactHook(hook, desiredUrl) {
77
+ return hook.url === desiredUrl && hook.events.length === 1 && hook.events[0] === "*";
78
+ }
79
+ async function request(input, fetchImpl, method, id, body, signal) {
80
+ const timeoutSignal = AbortSignal.timeout(input.requestTimeoutMs);
81
+ return fetchImpl(apiUrl(input, id), {
82
+ method,
83
+ ...(body === undefined ? {} : {
84
+ headers: { "content-type": "application/json" },
85
+ body: JSON.stringify(body),
86
+ }),
87
+ signal: signal ? AbortSignal.any([timeoutSignal, signal]) : timeoutSignal,
88
+ });
89
+ }
90
+ async function readHooks(input, fetchImpl, signal) {
91
+ try {
92
+ const response = await request(input, fetchImpl, "GET", undefined, undefined, signal);
93
+ if (response.status === 401 || response.status === 403) {
94
+ return result("auth-failed", `BlueBubbles rejected webhook credentials (HTTP ${response.status})`);
95
+ }
96
+ if (!response.ok)
97
+ return result("api-unreachable", `BlueBubbles webhook API returned HTTP ${response.status}`);
98
+ let payload;
99
+ try {
100
+ payload = await response.json();
101
+ }
102
+ catch {
103
+ return result("malformed", "BlueBubbles webhook API returned invalid JSON");
104
+ }
105
+ const data = payload && typeof payload === "object" ? payload.data : undefined;
106
+ if (!Array.isArray(data) || !data.every(isWebhook)) {
107
+ return result("malformed", "BlueBubbles webhook API returned an invalid webhook list");
108
+ }
109
+ return { hooks: data };
110
+ }
111
+ catch (error) {
112
+ const detail = error instanceof Error ? error.message : String(error);
113
+ return result("api-unreachable", sanitizeBlueBubblesWebhookText(detail, input));
114
+ }
115
+ }
116
+ function inspectHooks(hooks, input) {
117
+ const desired = buildBlueBubblesWebhookCallbackUrl(input);
118
+ const owner = blueBubblesWebhookOwnerToken(input.agentName, input.machineId);
119
+ const owned = hooks.filter((hook) => ownedBy(hook.url, owner));
120
+ const exact = owned.filter((hook) => exactHook(hook, desired));
121
+ if (owned.length === 1 && exact.length === 1) {
122
+ return result("exact", "one exact Ouro-owned BlueBubbles webhook is registered", {
123
+ ownedCount: 1,
124
+ exactCount: 1,
125
+ });
126
+ }
127
+ return result(owned.length === 0 ? "missing" : "drifted", owned.length === 0
128
+ ? "the Ouro-owned BlueBubbles webhook is missing"
129
+ : "the Ouro-owned BlueBubbles webhook registration is drifted", {
130
+ ownedCount: owned.length,
131
+ exactCount: exact.length,
132
+ });
133
+ }
134
+ async function inspectBlueBubblesWebhookRegistration(input, deps = {}) {
135
+ if (!input.listenerReady)
136
+ return result("listener-not-ready", "the local BlueBubbles listener is not ready");
137
+ const listed = await readHooks(input, deps.fetchImpl ?? fetch, deps.signal);
138
+ return "hooks" in listed ? inspectHooks(listed.hooks, input) : listed;
139
+ }
140
+ async function mutate(input, fetchImpl, method, id, signal) {
141
+ try {
142
+ const response = await request(input, fetchImpl, method, id, method === "POST" ? { url: buildBlueBubblesWebhookCallbackUrl(input), events: ["*"] } : undefined, signal);
143
+ if (!response.ok)
144
+ return { ok: false, detail: `HTTP ${response.status}` };
145
+ return { ok: true };
146
+ }
147
+ catch (error) {
148
+ return { ok: false, detail: sanitizeBlueBubblesWebhookText(error instanceof Error ? error.message : String(error), input) };
149
+ }
150
+ }
151
+ async function reconcileBlueBubblesWebhookRegistration(input, deps = {}) {
152
+ if (!input.listenerReady)
153
+ return result("listener-not-ready", "the local BlueBubbles listener is not ready");
154
+ const fetchImpl = deps.fetchImpl ?? fetch;
155
+ const listed = await readHooks(input, fetchImpl, deps.signal);
156
+ if (!("hooks" in listed))
157
+ return listed;
158
+ const desired = buildBlueBubblesWebhookCallbackUrl(input);
159
+ const owner = blueBubblesWebhookOwnerToken(input.agentName, input.machineId);
160
+ const owned = listed.hooks.filter((hook) => ownedBy(hook.url, owner));
161
+ const exact = owned.filter((hook) => exactHook(hook, desired));
162
+ const keep = exact[0];
163
+ const stale = owned.filter((hook) => hook !== keep);
164
+ const adopt = keep ? [] : listed.hooks.filter((hook) => exactUnmarked(hook.url, desired)).slice(0, 1);
165
+ let changed = false;
166
+ if (!keep) {
167
+ const created = await mutate(input, fetchImpl, "POST", undefined, deps.signal);
168
+ if (!created.ok) {
169
+ return result(owned.length === 0 ? "missing" : "drifted", `could not create the desired webhook: ${created.detail}`, {
170
+ ownedCount: owned.length,
171
+ exactCount: exact.length,
172
+ });
173
+ }
174
+ changed = true;
175
+ }
176
+ for (const hook of [...stale, ...adopt]) {
177
+ const deleted = await mutate(input, fetchImpl, "DELETE", hook.id, deps.signal);
178
+ if (!deleted.ok) {
179
+ return result("drifted", `could not remove 1 stale owned registration: ${deleted.detail}`, {
180
+ ownedCount: owned.length,
181
+ exactCount: exact.length,
182
+ changed,
183
+ });
184
+ }
185
+ changed = true;
186
+ }
187
+ if (!changed)
188
+ return inspectHooks(listed.hooks, input);
189
+ const verified = await readHooks(input, fetchImpl, deps.signal);
190
+ if (!("hooks" in verified))
191
+ return { ...verified, changed };
192
+ return { ...inspectHooks(verified.hooks, input), changed };
193
+ }
194
+ function createBlueBubblesWebhookReconciler(input, deps = {}) {
195
+ const setIntervalImpl = deps.setIntervalImpl ?? ((callback, intervalMs) => setInterval(callback, intervalMs));
196
+ const clearIntervalImpl = deps.clearIntervalImpl ?? ((timer) => clearInterval(timer));
197
+ let closed = false;
198
+ let active = null;
199
+ const abortController = new AbortController();
200
+ const reconcileNow = () => {
201
+ if (closed)
202
+ return Promise.resolve(result("listener-not-ready", "the BlueBubbles webhook reconciler is closed"));
203
+ if (active)
204
+ return active;
205
+ active = reconcileBlueBubblesWebhookRegistration(input, { ...deps, signal: abortController.signal }).finally(() => { active = null; });
206
+ return active;
207
+ };
208
+ const timer = setIntervalImpl(() => { void reconcileNow(); }, exports.BLUEBUBBLES_WEBHOOK_RECONCILE_INTERVAL_MS);
209
+ void reconcileNow().then((outcome) => {
210
+ (0, runtime_1.emitNervesEvent)({
211
+ component: "senses",
212
+ event: "senses.bluebubbles_webhook_reconciled",
213
+ level: outcome.ok ? "info" : "warn",
214
+ message: "reconciled BlueBubbles webhook registration",
215
+ meta: { state: outcome.state, changed: outcome.changed },
216
+ });
217
+ });
218
+ return {
219
+ reconcileNow,
220
+ close: () => {
221
+ if (closed)
222
+ return;
223
+ closed = true;
224
+ clearIntervalImpl(timer);
225
+ abortController.abort(new Error("BlueBubbles webhook reconciliation closed"));
226
+ },
227
+ };
228
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ // Outbound BlueBubbles meta-content guard.
3
+ //
4
+ // Blocks accidental delivery of internal/meta text — pipeline section markers,
5
+ // surfacing-mechanics prefixes, reasoning tags — to the live iMessage channel.
6
+ // Failure mode is "drop and log", never queue for later delivery.
7
+ //
8
+ // Patterns are deliberately narrow: bracketed system markers and angle-bracket
9
+ // reasoning tags. Plain prose mentioning related concepts is NOT blocked, so
10
+ // user-facing replies that legitimately discuss those concepts still pass.
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.containsInternalMetaMarkers = containsInternalMetaMarkers;
13
+ exports.emitBluebubblesMetaBlocked = emitBluebubblesMetaBlocked;
14
+ const runtime_1 = require("../nerves/runtime");
15
+ const META_CONTENT_PATTERNS = [
16
+ /\[surfaced from inner dialog\]/i,
17
+ /\[pending from [^\]]+\]:/i,
18
+ /\[conversation scope:/i,
19
+ /\[recent active lanes\]/i,
20
+ /\[routing control:/i,
21
+ /<\/?think>/i,
22
+ ];
23
+ function containsInternalMetaMarkers(text) {
24
+ if (!text)
25
+ return false;
26
+ return META_CONTENT_PATTERNS.some((pattern) => pattern.test(text));
27
+ }
28
+ function emitBluebubblesMetaBlocked(options) {
29
+ (0, runtime_1.emitNervesEvent)({
30
+ level: "warn",
31
+ component: "senses",
32
+ event: "senses.bluebubbles_meta_blocked",
33
+ message: options.message,
34
+ meta: {
35
+ site: options.site,
36
+ ...options.meta,
37
+ },
38
+ });
39
+ }
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BracketedPasteHandler = void 0;
4
+ /**
5
+ * Bracketed paste mode handler for the TUI.
6
+ *
7
+ * Detects \x1b[200~ (paste start) and \x1b[201~ (paste end) markers in
8
+ * raw stdin data. Buffers paste content between markers and emits it as
9
+ * a single "paste" event. Non-paste data is emitted as "data" unchanged.
10
+ *
11
+ * Works alongside Ink's stdin handling by intercepting raw data events.
12
+ */
13
+ const events_1 = require("events");
14
+ const runtime_1 = require("../../nerves/runtime");
15
+ const PASTE_START = "\x1b[200~";
16
+ const PASTE_END = "\x1b[201~";
17
+ class BracketedPasteHandler extends events_1.EventEmitter {
18
+ stdin;
19
+ stdout;
20
+ pasting = false;
21
+ buffer = "";
22
+ dataHandler;
23
+ constructor(stdin, stdout) {
24
+ super();
25
+ this.stdin = stdin;
26
+ this.stdout = stdout;
27
+ // Enable bracketed paste mode
28
+ stdout.write("\x1b[?2004h");
29
+ this.dataHandler = (chunk) => {
30
+ this.processChunk(chunk.toString());
31
+ };
32
+ stdin.prependListener("data", this.dataHandler);
33
+ }
34
+ processChunk(data) {
35
+ let remaining = data;
36
+ while (remaining.length > 0) {
37
+ if (this.pasting) {
38
+ // Look for end marker in buffer + remaining
39
+ const combined = this.buffer + remaining;
40
+ const endIdx = combined.indexOf(PASTE_END);
41
+ if (endIdx !== -1) {
42
+ // Found end marker -- emit paste content
43
+ const pasteContent = combined.slice(0, endIdx);
44
+ (0, runtime_1.emitNervesEvent)({ component: "senses", event: "senses.bracketed_paste", message: "bracketed paste received", meta: { length: pasteContent.length } });
45
+ this.emit("paste", pasteContent);
46
+ this.buffer = "";
47
+ this.pasting = false;
48
+ // Process remaining data after end marker
49
+ remaining = combined.slice(endIdx + PASTE_END.length);
50
+ continue;
51
+ }
52
+ // No end marker yet -- buffer everything so far
53
+ this.buffer = combined;
54
+ return;
55
+ }
56
+ // Not pasting -- look for start marker
57
+ const startIdx = remaining.indexOf(PASTE_START);
58
+ if (startIdx !== -1) {
59
+ // Emit any data before the start marker
60
+ const before = remaining.slice(0, startIdx);
61
+ if (before.length > 0) {
62
+ this.emit("data", before);
63
+ }
64
+ // Enter paste mode
65
+ this.pasting = true;
66
+ this.buffer = "";
67
+ remaining = remaining.slice(startIdx + PASTE_START.length);
68
+ continue;
69
+ }
70
+ // No start marker -- emit as regular data
71
+ this.emit("data", remaining);
72
+ return;
73
+ }
74
+ }
75
+ /** Disable bracketed paste mode and remove listeners. */
76
+ destroy() {
77
+ this.stdout.write("\x1b[?2004l");
78
+ this.stdin.removeListener("data", this.dataHandler);
79
+ this.removeAllListeners();
80
+ }
81
+ }
82
+ exports.BracketedPasteHandler = BracketedPasteHandler;
@@ -0,0 +1,287 @@
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.IMAGE_EXTENSION_REGEX = void 0;
37
+ exports.isImagePath = isImagePath;
38
+ exports.unescapePath = unescapePath;
39
+ exports.tryReadImage = tryReadImage;
40
+ exports.formatImageRef = formatImageRef;
41
+ exports.replacePathsWithRefs = replacePathsWithRefs;
42
+ exports.processSubmitInput = processSubmitInput;
43
+ exports.resolveImageContent = resolveImageContent;
44
+ /**
45
+ * Image paste detection and resolution for the TUI.
46
+ *
47
+ * When a user drags an image file onto the terminal, macOS pastes the absolute
48
+ * path (often with backslash-escaped spaces). This module detects image paths
49
+ * in the input text, replaces them with `[Image #N]` references, reads the
50
+ * files, registers them as shared attachments, and produces OpenAI-compatible
51
+ * `image_url` content blocks.
52
+ */
53
+ const node_crypto_1 = require("node:crypto");
54
+ const promises_1 = require("fs/promises");
55
+ const child_process_1 = require("child_process");
56
+ const path = __importStar(require("path"));
57
+ const runtime_1 = require("../../nerves/runtime");
58
+ const identity_1 = require("../../heart/identity");
59
+ const render_1 = require("../../heart/attachments/render");
60
+ const store_1 = require("../../heart/attachments/store");
61
+ const materialize_1 = require("../../heart/attachments/materialize");
62
+ const cli_local_file_1 = require("../../heart/attachments/sources/cli-local-file");
63
+ /** Matches image file extensions (case-insensitive) */
64
+ exports.IMAGE_EXTENSION_REGEX = /\.(png|jpe?g|gif|webp)$/i;
65
+ /** Check whether a string (possibly backslash-escaped) ends with an image extension */
66
+ function isImagePath(str) {
67
+ return exports.IMAGE_EXTENSION_REGEX.test(unescapePath(str));
68
+ }
69
+ /** Strip shell escape backslashes from a path (macOS/Linux drag-drop format) */
70
+ function unescapePath(str) {
71
+ // Handle double-backslashes first (actual backslash in filename)
72
+ // then remove single escape backslashes
73
+ return str.replace(/\\(.)/g, "$1");
74
+ }
75
+ /** Detect temp screenshot paths from macOS screencapture */
76
+ const TEMP_SCREENSHOT_RE = /\/TemporaryItems\/.*screencaptureui.*\/Screenshot/i;
77
+ /** Map file extension to MIME media type */
78
+ function extensionToMediaType(ext) {
79
+ switch (ext.toLowerCase()) {
80
+ case ".jpg":
81
+ case ".jpeg":
82
+ return "image/jpeg";
83
+ case ".png":
84
+ return "image/png";
85
+ case ".gif":
86
+ return "image/gif";
87
+ case ".webp":
88
+ return "image/webp";
89
+ default:
90
+ return "image/png";
91
+ }
92
+ }
93
+ /**
94
+ * Read an image file and return base64 + media type.
95
+ * Falls back to clipboard for temp screenshot paths (macOS screencapture
96
+ * creates ephemeral files in TemporaryItems that are cleaned up quickly).
97
+ * Returns null on any error.
98
+ */
99
+ async function tryReadImage(absolutePath) {
100
+ // Try reading the file directly first
101
+ try {
102
+ const buffer = await (0, promises_1.readFile)(absolutePath);
103
+ if (buffer.length > 0) {
104
+ const ext = path.extname(absolutePath);
105
+ return {
106
+ buffer: Buffer.from(buffer),
107
+ base64: Buffer.from(buffer).toString("base64"),
108
+ mediaType: extensionToMediaType(ext),
109
+ fromClipboard: false,
110
+ };
111
+ }
112
+ }
113
+ catch {
114
+ // File not found or permission denied — try clipboard fallback
115
+ }
116
+ // Clipboard fallback for macOS temp screenshots
117
+ /* v8 ignore start -- clipboard fallback requires real macOS screencapture @preserve */
118
+ if (process.platform === "darwin" && TEMP_SCREENSHOT_RE.test(absolutePath)) {
119
+ const clipboardImage = await getImageFromClipboard();
120
+ if (clipboardImage)
121
+ return clipboardImage;
122
+ }
123
+ /* v8 ignore stop */
124
+ (0, runtime_1.emitNervesEvent)({
125
+ component: "senses",
126
+ event: "senses.image_read_error",
127
+ message: `Failed to read image: ${absolutePath}`,
128
+ meta: { path: absolutePath },
129
+ });
130
+ return null;
131
+ }
132
+ /**
133
+ * Read image data from macOS clipboard via osascript.
134
+ * Used as fallback when temp screenshot files are already cleaned up.
135
+ */
136
+ /* v8 ignore start -- macOS clipboard integration @preserve */
137
+ async function getImageFromClipboard() {
138
+ const tmpPath = "/tmp/ouro_clipboard_image.png";
139
+ try {
140
+ // Check if clipboard has image data
141
+ (0, child_process_1.execFileSync)("osascript", ["-e", "the clipboard as «class PNGf»"], { stdio: "pipe" });
142
+ // Save clipboard image to temp file
143
+ (0, child_process_1.execFileSync)("osascript", [
144
+ "-e", "set png_data to (the clipboard as «class PNGf»)",
145
+ "-e", `set fp to open for access POSIX file "${tmpPath}" with write permission`,
146
+ "-e", "write png_data to fp",
147
+ "-e", "close access fp",
148
+ ], { stdio: "pipe" });
149
+ const buffer = await (0, promises_1.readFile)(tmpPath);
150
+ void (0, promises_1.unlink)(tmpPath).catch(() => { });
151
+ if (buffer.length === 0)
152
+ return null;
153
+ return {
154
+ buffer: Buffer.from(buffer),
155
+ base64: Buffer.from(buffer).toString("base64"),
156
+ mediaType: "image/png",
157
+ fromClipboard: true,
158
+ };
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ /* v8 ignore stop */
165
+ /** Format an image reference placeholder */
166
+ function formatImageRef(n) {
167
+ return `[Image #${n}]`;
168
+ }
169
+ /**
170
+ * Scan input for absolute image file paths and replace with [Image #N] references.
171
+ * Handles backslash-escaped characters (macOS drag-drop) and paths with spaces.
172
+ */
173
+ function replacePathsWithRefs(input) {
174
+ const images = new Map();
175
+ // Match absolute paths: start with /, contain non-whitespace or backslash-escaped chars,
176
+ // end with an image extension. The (?:\\.|\S) alternation allows `\ ` sequences.
177
+ const pathRegex = /(?:\/(?:\\.|[^\s])+\.(?:png|jpe?g|gif|webp))/gi;
178
+ let counter = 0;
179
+ const text = input.replace(pathRegex, (match) => {
180
+ counter++;
181
+ images.set(counter, unescapePath(match));
182
+ return formatImageRef(counter);
183
+ });
184
+ return { text, images };
185
+ }
186
+ /**
187
+ * Process submit input: detect image paths, replace with refs, return map.
188
+ * This is the entry point called by InputArea on submit.
189
+ */
190
+ function processSubmitInput(text) {
191
+ return replacePathsWithRefs(text);
192
+ }
193
+ function extensionForMediaType(mediaType) {
194
+ switch (mediaType) {
195
+ case "image/jpeg":
196
+ return ".jpg";
197
+ case "image/gif":
198
+ return ".gif";
199
+ case "image/webp":
200
+ return ".webp";
201
+ default:
202
+ return ".png";
203
+ }
204
+ }
205
+ async function pathExists(targetPath) {
206
+ try {
207
+ await (0, promises_1.access)(targetPath);
208
+ return true;
209
+ }
210
+ catch {
211
+ return false;
212
+ }
213
+ }
214
+ async function persistClipboardImage(agentRoot, originalPath, image) {
215
+ const hash = (0, node_crypto_1.createHash)("sha1").update(originalPath).digest("hex").slice(0, 16);
216
+ const targetPath = path.join(agentRoot, "state", "attachments", "imports", "cli", `${hash}${extensionForMediaType(image.mediaType)}`);
217
+ await (0, promises_1.mkdir)(path.dirname(targetPath), { recursive: true });
218
+ await (0, promises_1.writeFile)(targetPath, image.buffer);
219
+ return targetPath;
220
+ }
221
+ /**
222
+ * Build OpenAI content parts from text + image map.
223
+ * For each image in the map, reads the file and creates an `image_url` content part.
224
+ * Images that fail to read are silently skipped.
225
+ * Returns `[{ type: "text", text }]` when no images resolve.
226
+ */
227
+ async function resolveImageContent(text, images) {
228
+ if (images.size === 0) {
229
+ return [{ type: "text", text }];
230
+ }
231
+ const agentName = (0, identity_1.getAgentName)();
232
+ const agentRoot = (0, identity_1.getAgentRoot)(agentName);
233
+ const parts = [];
234
+ const cachedAttachments = [];
235
+ // Read all images in parallel
236
+ const entries = Array.from(images.entries());
237
+ const results = await Promise.all(entries.map(async ([, absolutePath]) => {
238
+ const image = await tryReadImage(absolutePath);
239
+ if (!image)
240
+ return null;
241
+ const sourcePath = image.fromClipboard || !await pathExists(absolutePath)
242
+ ? await persistClipboardImage(agentRoot, absolutePath, image)
243
+ : absolutePath;
244
+ const attachment = (0, store_1.cacheRecentAttachment)(agentName, (0, cli_local_file_1.buildCliLocalFileAttachmentRecord)({
245
+ path: sourcePath,
246
+ mimeType: image.mediaType,
247
+ byteCount: image.buffer.length,
248
+ }), agentRoot);
249
+ cachedAttachments.push(attachment);
250
+ try {
251
+ const materialized = await (0, materialize_1.materializeAttachment)(agentName, attachment.id, {
252
+ agentRoot,
253
+ variant: "vision_safe",
254
+ });
255
+ const normalizedBuffer = await (0, promises_1.readFile)(materialized.path);
256
+ return {
257
+ attachment,
258
+ mediaType: materialized.mimeType ?? image.mediaType,
259
+ base64: Buffer.from(normalizedBuffer).toString("base64"),
260
+ };
261
+ }
262
+ catch {
263
+ return {
264
+ attachment,
265
+ mediaType: image.mediaType,
266
+ base64: image.base64,
267
+ };
268
+ }
269
+ }));
270
+ for (const result of results) {
271
+ if (result) {
272
+ parts.push({
273
+ type: "image_url",
274
+ image_url: { url: `data:${result.mediaType};base64,${result.base64}` },
275
+ });
276
+ }
277
+ }
278
+ // Always include the text part
279
+ const attachmentBlock = (0, render_1.renderAttachmentBlock)(cachedAttachments);
280
+ const textWithAttachments = [text, attachmentBlock].filter(Boolean).join("\n");
281
+ parts.push({ type: "text", text: textWithAttachments || text });
282
+ // If no images resolved, return just text
283
+ if (parts.length === 1) {
284
+ return [{ type: "text", text }];
285
+ }
286
+ return parts;
287
+ }