@ouro.bot/cli 0.1.0-alpha.65 → 0.1.0-alpha.651

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 (435) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +4157 -14
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +144 -0
  15. package/dist/arc/episodes.js +118 -0
  16. package/dist/arc/evolution.js +487 -0
  17. package/dist/arc/intentions.js +134 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +270 -0
  20. package/dist/arc/packets.js +288 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +57 -0
  23. package/dist/heart/active-work.js +860 -43
  24. package/dist/heart/agent-entry.js +69 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/awaiting/await-alert.js +146 -0
  36. package/dist/heart/awaiting/await-expiry.js +108 -0
  37. package/dist/heart/awaiting/await-loader.js +91 -0
  38. package/dist/heart/awaiting/await-parser.js +141 -0
  39. package/dist/heart/awaiting/await-runtime-state.js +100 -0
  40. package/dist/heart/awaiting/await-scheduler.js +377 -0
  41. package/dist/heart/background-operations.js +281 -0
  42. package/dist/heart/bridges/manager.js +137 -17
  43. package/dist/heart/bridges/store.js +14 -2
  44. package/dist/heart/bundle-state.js +168 -0
  45. package/dist/heart/commitments.js +135 -0
  46. package/dist/heart/config-registry.js +322 -0
  47. package/dist/heart/config.js +118 -119
  48. package/dist/heart/core.js +1123 -247
  49. package/dist/heart/cross-chat-delivery.js +3 -18
  50. package/dist/heart/daemon/agent-config-check.js +419 -0
  51. package/dist/heart/daemon/agent-discovery.js +102 -3
  52. package/dist/heart/daemon/agent-service.js +522 -0
  53. package/dist/heart/daemon/agentic-repair.js +547 -0
  54. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  55. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  56. package/dist/heart/daemon/cadence.js +70 -0
  57. package/dist/heart/daemon/cli-defaults.js +780 -0
  58. package/dist/heart/daemon/cli-desk.js +322 -0
  59. package/dist/heart/daemon/cli-exec.js +7480 -0
  60. package/dist/heart/daemon/cli-help.js +505 -0
  61. package/dist/heart/daemon/cli-parse.js +1554 -0
  62. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  63. package/dist/heart/daemon/cli-render.js +763 -0
  64. package/dist/heart/daemon/cli-types.js +8 -0
  65. package/dist/heart/daemon/connect-bay.js +323 -0
  66. package/dist/heart/daemon/daemon-cli.js +29 -1750
  67. package/dist/heart/daemon/daemon-entry.js +485 -2
  68. package/dist/heart/daemon/daemon-health.js +176 -0
  69. package/dist/heart/daemon/daemon-rollup.js +57 -0
  70. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  71. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  72. package/dist/heart/daemon/daemon.js +932 -74
  73. package/dist/heart/daemon/dns-workflow.js +394 -0
  74. package/dist/heart/daemon/doctor-types.js +8 -0
  75. package/dist/heart/daemon/doctor.js +873 -0
  76. package/dist/heart/daemon/health-monitor.js +122 -1
  77. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  78. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  79. package/dist/heart/daemon/http-health-probe.js +80 -0
  80. package/dist/heart/daemon/human-command-screens.js +234 -0
  81. package/dist/heart/daemon/human-readiness.js +114 -0
  82. package/dist/heart/daemon/inner-status.js +89 -0
  83. package/dist/heart/daemon/interactive-repair.js +394 -0
  84. package/dist/heart/daemon/launchd.js +37 -8
  85. package/dist/heart/daemon/log-tailer.js +79 -10
  86. package/dist/heart/daemon/logs-prune.js +110 -0
  87. package/dist/heart/daemon/mcp-canary.js +297 -0
  88. package/dist/heart/daemon/message-router.js +6 -2
  89. package/dist/heart/daemon/migrate-to-desk.js +848 -0
  90. package/dist/heart/daemon/os-cron-deps.js +135 -0
  91. package/dist/heart/daemon/os-cron.js +14 -12
  92. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  93. package/dist/heart/daemon/ouro-entry.js +3 -1
  94. package/dist/heart/daemon/plugin-cli.js +432 -0
  95. package/dist/heart/daemon/process-manager.js +510 -40
  96. package/dist/heart/daemon/provider-discovery.js +137 -0
  97. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  98. package/dist/heart/daemon/pulse.js +475 -0
  99. package/dist/heart/daemon/readiness-repair.js +365 -0
  100. package/dist/heart/daemon/run-hooks.js +2 -0
  101. package/dist/heart/daemon/runtime-logging.js +35 -14
  102. package/dist/heart/daemon/runtime-metadata.js +2 -30
  103. package/dist/heart/daemon/safe-mode.js +161 -0
  104. package/dist/heart/daemon/sense-manager.js +493 -38
  105. package/dist/heart/daemon/session-id-resolver.js +131 -0
  106. package/dist/heart/daemon/skill-management-installer.js +1 -1
  107. package/dist/heart/daemon/socket-client.js +158 -11
  108. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  109. package/dist/heart/daemon/startup-tui.js +330 -0
  110. package/dist/heart/daemon/task-scheduler.js +117 -39
  111. package/dist/heart/daemon/terminal-ui.js +499 -0
  112. package/dist/heart/daemon/thoughts.js +229 -17
  113. package/dist/heart/daemon/up-progress.js +366 -0
  114. package/dist/heart/daemon/vault-items.js +56 -0
  115. package/dist/heart/delegation.js +1 -4
  116. package/dist/heart/habits/habit-migration.js +189 -0
  117. package/dist/heart/habits/habit-parser.js +140 -0
  118. package/dist/heart/habits/habit-runtime-state.js +100 -0
  119. package/dist/heart/habits/habit-scheduler.js +372 -0
  120. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  121. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  122. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  123. package/dist/heart/{daemon → hatch}/specialist-tools.js +37 -14
  124. package/dist/heart/identity.js +168 -57
  125. package/dist/heart/kept-notes.js +357 -0
  126. package/dist/heart/kicks.js +1 -1
  127. package/dist/heart/machine-identity.js +161 -0
  128. package/dist/heart/mail-import-discovery.js +353 -0
  129. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  130. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  131. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  132. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  133. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  134. package/dist/heart/mailbox/mailbox-http.js +99 -0
  135. package/dist/heart/mailbox/mailbox-read.js +31 -0
  136. package/dist/heart/mailbox/mailbox-types.js +27 -0
  137. package/dist/heart/mailbox/mailbox-view.js +197 -0
  138. package/dist/heart/mailbox/readers/agent-machine.js +418 -0
  139. package/dist/heart/mailbox/readers/continuity-readers.js +319 -0
  140. package/dist/heart/mailbox/readers/mail.js +375 -0
  141. package/dist/heart/mailbox/readers/runtime-readers.js +756 -0
  142. package/dist/heart/mailbox/readers/sessions.js +232 -0
  143. package/dist/heart/mailbox/readers/shared.js +111 -0
  144. package/dist/heart/mcp/mcp-server.js +692 -0
  145. package/dist/heart/migrate-config.js +100 -0
  146. package/dist/heart/model-capabilities.js +19 -0
  147. package/dist/heart/orientation-frame.js +217 -0
  148. package/dist/heart/platform.js +81 -0
  149. package/dist/heart/provider-attempt.js +134 -0
  150. package/dist/heart/provider-binding-resolver.js +272 -0
  151. package/dist/heart/provider-credentials.js +425 -0
  152. package/dist/heart/provider-failover.js +311 -0
  153. package/dist/heart/provider-models.js +81 -0
  154. package/dist/heart/provider-ping.js +262 -0
  155. package/dist/heart/provider-readiness-cache.js +40 -0
  156. package/dist/heart/provider-visibility.js +188 -0
  157. package/dist/heart/providers/anthropic-token.js +131 -0
  158. package/dist/heart/providers/anthropic.js +139 -52
  159. package/dist/heart/providers/azure.js +23 -11
  160. package/dist/heart/providers/error-classification.js +127 -0
  161. package/dist/heart/providers/github-copilot.js +145 -0
  162. package/dist/heart/providers/minimax-vlm.js +189 -0
  163. package/dist/heart/providers/minimax.js +26 -8
  164. package/dist/heart/providers/openai-codex-token.js +349 -0
  165. package/dist/heart/providers/openai-codex.js +55 -40
  166. package/dist/heart/runtime-capability-check.js +170 -0
  167. package/dist/heart/runtime-credentials.js +367 -0
  168. package/dist/heart/runtime-cwd.js +87 -0
  169. package/dist/heart/sense-truth.js +13 -4
  170. package/dist/heart/session-activity.js +48 -24
  171. package/dist/heart/session-events.js +1163 -0
  172. package/dist/heart/session-playback-cli-main.js +5 -0
  173. package/dist/heart/session-playback-cli.js +36 -0
  174. package/dist/heart/session-playback.js +231 -0
  175. package/dist/heart/session-stats-cli-main.js +5 -0
  176. package/dist/heart/session-stats.js +182 -0
  177. package/dist/heart/session-transcript.js +133 -0
  178. package/dist/heart/start-of-turn-packet.js +345 -0
  179. package/dist/heart/streaming.js +44 -27
  180. package/dist/heart/structured-output.js +196 -0
  181. package/dist/heart/sync-classification.js +176 -0
  182. package/dist/heart/sync.js +449 -0
  183. package/dist/heart/target-resolution.js +9 -5
  184. package/dist/heart/tempo.js +93 -0
  185. package/dist/heart/temporal-view.js +41 -0
  186. package/dist/heart/timeouts.js +101 -0
  187. package/dist/heart/tool-activity-callbacks.js +59 -0
  188. package/dist/heart/tool-description.js +143 -0
  189. package/dist/heart/tool-friction.js +55 -0
  190. package/dist/heart/tool-loop.js +200 -0
  191. package/dist/heart/turn-context.js +389 -0
  192. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  193. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  194. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  195. package/dist/heart/versioning/ouro-version-manager.js +409 -0
  196. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  197. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  198. package/dist/heart/versioning/update-hooks.js +154 -0
  199. package/dist/mailbox-ui/assets/index-9-AxCxuB.js +61 -0
  200. package/dist/mailbox-ui/assets/index-CWzt267f.css +1 -0
  201. package/dist/mailbox-ui/index.html +15 -0
  202. package/dist/mailroom/attention.js +167 -0
  203. package/dist/mailroom/autonomy.js +209 -0
  204. package/dist/mailroom/blob-store.js +715 -0
  205. package/dist/mailroom/body-cache.js +61 -0
  206. package/dist/mailroom/core.js +788 -0
  207. package/dist/mailroom/entry.js +160 -0
  208. package/dist/mailroom/file-store.js +568 -0
  209. package/dist/mailroom/mbox-import.js +393 -0
  210. package/dist/mailroom/migration.js +164 -0
  211. package/dist/mailroom/outbound.js +380 -0
  212. package/dist/mailroom/policy.js +263 -0
  213. package/dist/mailroom/reader.js +233 -0
  214. package/dist/mailroom/search-cache.js +334 -0
  215. package/dist/mailroom/search-relevance.js +319 -0
  216. package/dist/mailroom/smtp-ingress.js +176 -0
  217. package/dist/mailroom/source-state.js +176 -0
  218. package/dist/mailroom/thread.js +109 -0
  219. package/dist/mailroom/travel-extract.js +89 -0
  220. package/dist/mind/bundle-manifest.js +14 -1
  221. package/dist/mind/context.js +251 -101
  222. package/dist/mind/desk-section.js +310 -0
  223. package/dist/mind/diary-integrity.js +60 -0
  224. package/dist/mind/{memory.js → diary.js} +68 -76
  225. package/dist/mind/embedding-provider.js +60 -0
  226. package/dist/mind/file-state.js +179 -0
  227. package/dist/mind/friends/channel.js +39 -0
  228. package/dist/mind/friends/resolver.js +54 -2
  229. package/dist/mind/friends/store-file.js +48 -4
  230. package/dist/mind/friends/types.js +2 -2
  231. package/dist/mind/journal-index.js +162 -0
  232. package/dist/mind/note-search.js +268 -0
  233. package/dist/mind/obligation-steering.js +221 -0
  234. package/dist/mind/pending.js +6 -1
  235. package/dist/mind/prompt-refresh.js +3 -2
  236. package/dist/mind/prompt.js +1051 -138
  237. package/dist/mind/provenance-trust.js +26 -0
  238. package/dist/mind/scrutiny.js +173 -0
  239. package/dist/nerves/cli-logging.js +7 -1
  240. package/dist/nerves/coverage/audit-rules.js +15 -6
  241. package/dist/nerves/coverage/audit.js +28 -2
  242. package/dist/nerves/coverage/cli.js +1 -1
  243. package/dist/nerves/coverage/contract.js +5 -5
  244. package/dist/nerves/coverage/file-completeness.js +139 -5
  245. package/dist/nerves/event-buffer.js +111 -0
  246. package/dist/nerves/index.js +224 -4
  247. package/dist/nerves/observation.js +20 -0
  248. package/dist/nerves/redact.js +79 -0
  249. package/dist/nerves/review/cli-main.js +5 -0
  250. package/dist/nerves/review/cli.js +156 -0
  251. package/dist/nerves/review/core.js +152 -0
  252. package/dist/nerves/runtime.js +5 -1
  253. package/dist/repertoire/ado-client.js +15 -56
  254. package/dist/repertoire/ado-semantic.js +16 -10
  255. package/dist/repertoire/api-client.js +97 -0
  256. package/dist/repertoire/bitwarden-store.js +1041 -0
  257. package/dist/repertoire/bundle-templates.js +72 -0
  258. package/dist/repertoire/bw-installer.js +180 -0
  259. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  260. package/dist/repertoire/coding/context-pack.js +331 -0
  261. package/dist/repertoire/coding/feedback.js +197 -30
  262. package/dist/repertoire/coding/manager.js +166 -10
  263. package/dist/repertoire/coding/spawner.js +55 -9
  264. package/dist/repertoire/coding/tools.js +219 -7
  265. package/dist/repertoire/commerce-errors.js +109 -0
  266. package/dist/repertoire/commerce-self-test.js +156 -0
  267. package/dist/repertoire/credential-access.js +178 -0
  268. package/dist/repertoire/desk/classifier.js +362 -0
  269. package/dist/repertoire/duffel-client.js +185 -0
  270. package/dist/repertoire/github-client.js +14 -55
  271. package/dist/repertoire/graph-client.js +11 -52
  272. package/dist/repertoire/guardrails.js +136 -25
  273. package/dist/repertoire/mcp-client.js +295 -0
  274. package/dist/repertoire/mcp-manager.js +403 -0
  275. package/dist/repertoire/mcp-tools.js +83 -0
  276. package/dist/repertoire/plugin-mcp.js +175 -0
  277. package/dist/repertoire/plugins.js +253 -0
  278. package/dist/repertoire/shell-sessions.js +133 -0
  279. package/dist/repertoire/skills.js +48 -4
  280. package/dist/repertoire/stripe-client.js +131 -0
  281. package/dist/repertoire/tool-results.js +29 -0
  282. package/dist/repertoire/tools-attachments.js +317 -0
  283. package/dist/repertoire/tools-awaiting.js +372 -0
  284. package/dist/repertoire/tools-base.js +59 -1082
  285. package/dist/repertoire/tools-bluebubbles.js +2 -0
  286. package/dist/repertoire/tools-bridge.js +144 -0
  287. package/dist/repertoire/tools-bundle.js +993 -0
  288. package/dist/repertoire/tools-config.js +186 -0
  289. package/dist/repertoire/tools-continuity.js +252 -0
  290. package/dist/repertoire/tools-credential.js +383 -0
  291. package/dist/repertoire/tools-evolution.js +527 -0
  292. package/dist/repertoire/tools-files.js +344 -0
  293. package/dist/repertoire/tools-flight.js +227 -0
  294. package/dist/repertoire/tools-flow.js +119 -0
  295. package/dist/repertoire/tools-github.js +3 -8
  296. package/dist/repertoire/tools-mail.js +1975 -0
  297. package/dist/repertoire/tools-notes.js +438 -0
  298. package/dist/repertoire/tools-obligations.js +143 -0
  299. package/dist/repertoire/tools-orientation.js +31 -0
  300. package/dist/repertoire/tools-record.js +464 -0
  301. package/dist/repertoire/tools-runtime.js +150 -0
  302. package/dist/repertoire/tools-session.js +766 -0
  303. package/dist/repertoire/tools-shell.js +120 -0
  304. package/dist/repertoire/tools-stripe.js +182 -0
  305. package/dist/repertoire/tools-surface.js +344 -0
  306. package/dist/repertoire/tools-teams.js +12 -39
  307. package/dist/repertoire/tools-travel.js +125 -0
  308. package/dist/repertoire/tools-trip.js +982 -0
  309. package/dist/repertoire/tools-user-profile.js +146 -0
  310. package/dist/repertoire/tools-vault.js +40 -0
  311. package/dist/repertoire/tools-voice.js +145 -0
  312. package/dist/repertoire/tools.js +193 -77
  313. package/dist/repertoire/travel-api-client.js +360 -0
  314. package/dist/repertoire/user-profile.js +131 -0
  315. package/dist/repertoire/vault-setup.js +246 -0
  316. package/dist/repertoire/vault-unlock.js +594 -0
  317. package/dist/scripts/claude-code-hook.js +41 -0
  318. package/dist/scripts/claude-code-stop-hook.js +47 -0
  319. package/dist/senses/attention-queue.js +186 -0
  320. package/dist/senses/await-turn-message.js +58 -0
  321. package/dist/senses/bluebubbles/active-turns.js +216 -0
  322. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  323. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  324. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  325. package/dist/senses/bluebubbles/entry.js +77 -0
  326. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  327. package/dist/senses/bluebubbles/index.js +2737 -0
  328. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  329. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  330. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  331. package/dist/senses/bluebubbles/processed-log.js +133 -0
  332. package/dist/senses/bluebubbles/replay.js +137 -0
  333. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  334. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  335. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  336. package/dist/senses/cli/bracketed-paste.js +82 -0
  337. package/dist/senses/cli/image-paste.js +287 -0
  338. package/dist/senses/cli/image-ref-navigation.js +75 -0
  339. package/dist/senses/cli/ink-app.js +156 -0
  340. package/dist/senses/cli/inline-diff.js +64 -0
  341. package/dist/senses/cli/input-keys.js +174 -0
  342. package/dist/senses/cli/kill-ring.js +86 -0
  343. package/dist/senses/cli/message-list.js +51 -0
  344. package/dist/senses/cli/ouro-tui.js +607 -0
  345. package/dist/senses/cli/spinner-imperative.js +135 -0
  346. package/dist/senses/cli/spinner.js +101 -0
  347. package/dist/senses/cli/status-line.js +60 -0
  348. package/dist/senses/cli/streaming-markdown.js +526 -0
  349. package/dist/senses/cli/tool-display.js +85 -0
  350. package/dist/senses/cli/tool-render.js +85 -0
  351. package/dist/senses/cli/tui-store.js +240 -0
  352. package/dist/senses/cli/virtual-list.js +35 -0
  353. package/dist/senses/cli-entry.js +60 -8
  354. package/dist/senses/cli-layout.js +100 -0
  355. package/dist/senses/cli.js +517 -204
  356. package/dist/senses/commands.js +66 -3
  357. package/dist/senses/habit-turn-message.js +108 -0
  358. package/dist/senses/inner-dialog-worker.js +254 -22
  359. package/dist/senses/inner-dialog.js +505 -40
  360. package/dist/senses/mail-entry.js +66 -0
  361. package/dist/senses/mail.js +379 -0
  362. package/dist/senses/pipeline.js +711 -181
  363. package/dist/senses/proactive-content-guard.js +51 -0
  364. package/dist/senses/shared-turn.js +393 -0
  365. package/dist/senses/surface-tool.js +108 -0
  366. package/dist/senses/teams-entry.js +60 -8
  367. package/dist/senses/teams.js +390 -98
  368. package/dist/senses/trust-gate.js +100 -5
  369. package/dist/senses/voice/audio-playback.js +237 -0
  370. package/dist/senses/voice/audio-routing.js +119 -0
  371. package/dist/senses/voice/elevenlabs.js +202 -0
  372. package/dist/senses/voice/floor-control.js +431 -0
  373. package/dist/senses/voice/floor-controller.js +115 -0
  374. package/dist/senses/voice/golden-path.js +116 -0
  375. package/dist/senses/voice/index.js +29 -0
  376. package/dist/senses/voice/meeting.js +113 -0
  377. package/dist/senses/voice/outbound.js +190 -0
  378. package/dist/senses/voice/phone.js +33 -0
  379. package/dist/senses/voice/playback.js +139 -0
  380. package/dist/senses/voice/realtime-eval.js +496 -0
  381. package/dist/senses/voice/realtime-trace.js +531 -0
  382. package/dist/senses/voice/transcript.js +70 -0
  383. package/dist/senses/voice/turn.js +191 -0
  384. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  385. package/dist/senses/voice/twilio-phone.js +5079 -0
  386. package/dist/senses/voice/types.js +2 -0
  387. package/dist/senses/voice/whisper.js +161 -0
  388. package/dist/senses/voice-entry.js +81 -0
  389. package/dist/senses/voice-realtime-eval-command.js +99 -0
  390. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  391. package/dist/senses/voice-twilio-entry.js +87 -0
  392. package/dist/trips/core.js +138 -0
  393. package/dist/trips/store.js +265 -0
  394. package/dist/util/frontmatter.js +53 -0
  395. package/package.json +53 -10
  396. package/skills/agent-commerce.md +106 -0
  397. package/skills/browser-navigation.md +117 -0
  398. package/skills/commerce-setup-guide.md +116 -0
  399. package/skills/commerce-setup.md +84 -0
  400. package/skills/configure-dev-tools.md +99 -0
  401. package/skills/travel-planning.md +138 -0
  402. package/dist/heart/daemon/auth-flow.js +0 -351
  403. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  404. package/dist/heart/daemon/update-hooks.js +0 -138
  405. package/dist/heart/safe-workspace.js +0 -228
  406. package/dist/heart/session-recall.js +0 -116
  407. package/dist/mind/associative-recall.js +0 -209
  408. package/dist/repertoire/tasks/board.js +0 -134
  409. package/dist/repertoire/tasks/index.js +0 -224
  410. package/dist/repertoire/tasks/lifecycle.js +0 -80
  411. package/dist/repertoire/tasks/middleware.js +0 -65
  412. package/dist/repertoire/tasks/parser.js +0 -173
  413. package/dist/repertoire/tasks/scanner.js +0 -132
  414. package/dist/repertoire/tasks/transitions.js +0 -144
  415. package/dist/senses/bluebubbles-entry.js +0 -13
  416. package/dist/senses/bluebubbles.js +0 -1177
  417. package/dist/senses/debug-activity.js +0 -148
  418. package/subagents/README.md +0 -7
  419. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  420. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  421. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  422. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  423. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  424. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  425. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  426. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  427. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  428. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  429. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  430. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  431. /package/dist/{repertoire/tasks/types.js → heart/attachments/sources/adapter.js} +0 -0
  432. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  433. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  434. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  435. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAttentionQueue = buildAttentionQueue;
4
+ exports.dequeueAttentionItem = dequeueAttentionItem;
5
+ exports.attentionQueueEmpty = attentionQueueEmpty;
6
+ exports.buildAttentionQueueSummary = buildAttentionQueueSummary;
7
+ exports.buildAttentionQueueStatusFrame = buildAttentionQueueStatusFrame;
8
+ const runtime_1 = require("../nerves/runtime");
9
+ // ── Queue construction ───────────────────────────────────────────
10
+ function generateItemId() {
11
+ return Math.random().toString(36).slice(2, 10);
12
+ }
13
+ function originKey(friendId, channel, key) {
14
+ return `${friendId}/${channel}/${key}`;
15
+ }
16
+ const PACKET_RETURN_HINT_MAX = 180;
17
+ const PACKET_RETURN_HINT_COUNT_MAX = 4;
18
+ const LITERAL_MARKER_RE = /\b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+){2,}\b/;
19
+ const RETURN_HINT_KEY_RE = /(expected|return|marker|answer|verdict)/i;
20
+ function addReturnHint(hints, seen, value) {
21
+ if (typeof value !== "string")
22
+ return;
23
+ const trimmed = value.trim();
24
+ if (!trimmed || trimmed.length > PACKET_RETURN_HINT_MAX)
25
+ return;
26
+ if (!LITERAL_MARKER_RE.test(trimmed))
27
+ return;
28
+ if (seen.has(trimmed))
29
+ return;
30
+ seen.add(trimmed);
31
+ hints.push(trimmed);
32
+ }
33
+ function extractQuotedReturnHints(value, hints, seen) {
34
+ for (const match of value.matchAll(/"([^"\n]{1,180})"/g)) {
35
+ addReturnHint(hints, seen, match[1]);
36
+ if (hints.length >= PACKET_RETURN_HINT_COUNT_MAX)
37
+ return;
38
+ }
39
+ }
40
+ function extractPacketReturnHints(packet) {
41
+ const hints = [];
42
+ const seen = new Set();
43
+ const sourceRequest = typeof packet.payload.sourceRequest === "string" ? packet.payload.sourceRequest : "";
44
+ if (sourceRequest)
45
+ extractQuotedReturnHints(sourceRequest, hints, seen);
46
+ for (const [key, value] of Object.entries(packet.payload)) {
47
+ if (hints.length >= PACKET_RETURN_HINT_COUNT_MAX)
48
+ break;
49
+ if (key === "sourceRequest" || !RETURN_HINT_KEY_RE.test(key))
50
+ continue;
51
+ addReturnHint(hints, seen, value);
52
+ if (Array.isArray(value)) {
53
+ for (const item of value) {
54
+ addReturnHint(hints, seen, item);
55
+ if (hints.length >= PACKET_RETURN_HINT_COUNT_MAX)
56
+ break;
57
+ }
58
+ }
59
+ }
60
+ return hints;
61
+ }
62
+ function buildAttentionQueue(input) {
63
+ const { drainedPending, outstandingObligations, friendNameResolver, packetResolver } = input;
64
+ const seen = new Set();
65
+ const items = [];
66
+ const enrichPacket = (packetId) => {
67
+ if (!packetId || !packetResolver)
68
+ return {};
69
+ const packet = packetResolver(packetId);
70
+ if (!packet)
71
+ return { packetId };
72
+ return {
73
+ packetId,
74
+ packetKind: packet.kind,
75
+ packetObjective: packet.objective,
76
+ packetSummary: packet.summary,
77
+ packetSuccessCriteria: packet.successCriteria,
78
+ packetSourceRequest: typeof packet.payload.sourceRequest === "string" ? packet.payload.sourceRequest : undefined,
79
+ packetReturnHints: extractPacketReturnHints(packet),
80
+ };
81
+ };
82
+ // Source 1: drained pending messages with delegatedFrom (current-turn delegations)
83
+ for (const msg of drainedPending) {
84
+ if (!msg.delegatedFrom)
85
+ continue;
86
+ const { friendId, channel, key, bridgeId } = msg.delegatedFrom;
87
+ const oKey = originKey(friendId, channel, key);
88
+ seen.add(oKey);
89
+ const resolvedName = friendNameResolver(friendId);
90
+ items.push({
91
+ id: msg.obligationId ?? generateItemId(),
92
+ friendId,
93
+ friendName: resolvedName ?? friendId,
94
+ channel,
95
+ key,
96
+ ...(bridgeId ? { bridgeId } : {}),
97
+ delegatedContent: msg.content,
98
+ ...(msg.obligationId ? { obligationId: msg.obligationId } : {}),
99
+ ...enrichPacket(msg.packetId),
100
+ source: "drained",
101
+ timestamp: msg.timestamp,
102
+ });
103
+ }
104
+ // Source 2: outstanding obligations (crash recovery)
105
+ for (const obligation of outstandingObligations) {
106
+ const { friendId, channel, key, bridgeId } = obligation.origin;
107
+ const oKey = originKey(friendId, channel, key);
108
+ if (seen.has(oKey))
109
+ continue; // deduplicate: prefer drained version
110
+ seen.add(oKey);
111
+ const resolvedName = friendNameResolver(friendId);
112
+ items.push({
113
+ id: obligation.id,
114
+ friendId,
115
+ friendName: resolvedName ?? friendId,
116
+ channel,
117
+ key,
118
+ ...(bridgeId ? { bridgeId } : {}),
119
+ delegatedContent: obligation.delegatedContent,
120
+ obligationId: obligation.id,
121
+ ...enrichPacket(obligation.packetId),
122
+ source: "obligation-recovery",
123
+ timestamp: obligation.createdAt,
124
+ });
125
+ }
126
+ // Sort FIFO (oldest first)
127
+ items.sort((a, b) => a.timestamp - b.timestamp);
128
+ (0, runtime_1.emitNervesEvent)({
129
+ event: "senses.attention_queue_built",
130
+ component: "senses",
131
+ message: `attention queue built with ${items.length} item(s)`,
132
+ meta: {
133
+ drainedCount: items.filter((i) => i.source === "drained").length,
134
+ recoveredCount: items.filter((i) => i.source === "obligation-recovery").length,
135
+ },
136
+ });
137
+ return items;
138
+ }
139
+ // ── Queue operations ─────────────────────────────────────────────
140
+ function dequeueAttentionItem(queue, id) {
141
+ const index = queue.findIndex((item) => item.id === id);
142
+ if (index === -1)
143
+ return null;
144
+ return queue.splice(index, 1)[0];
145
+ }
146
+ function attentionQueueEmpty(queue) {
147
+ return queue.length === 0;
148
+ }
149
+ // ── Queue visibility ─────────────────────────────────────────────
150
+ const CONTENT_PREVIEW_MAX = 80;
151
+ const PACKET_SOURCE_PREVIEW_MAX = 240;
152
+ function preview(value, max) {
153
+ return value.length > max ? `${value.slice(0, max - 3)}...` : value;
154
+ }
155
+ function buildAttentionQueueSummary(queue) {
156
+ if (queue.length === 0)
157
+ return "";
158
+ const lines = [
159
+ "[internal: current held work items — not messages to send]",
160
+ "Only listed items are waiting now; older transcript mentions and completed returns/probes are not current pressure.",
161
+ "To return one, call surface with delegationId set to the bracketed id.",
162
+ "Return only the requested result; do not add commentary about prior attempts, old loops, or completed probes.",
163
+ "If literal return options are listed, copy the chosen option exactly, including suffixes and punctuation.",
164
+ ];
165
+ for (const item of queue) {
166
+ if (item.packetKind && item.packetObjective) {
167
+ lines.push(`- [${item.id}] ${item.friendName} -> ${item.packetKind}: ${item.packetObjective}`);
168
+ if (item.packetSuccessCriteria?.length) {
169
+ lines.push(` return criteria: ${item.packetSuccessCriteria.join("; ")}`);
170
+ }
171
+ if (item.packetReturnHints?.length) {
172
+ lines.push(` literal return options: ${item.packetReturnHints.map((hint) => `"${hint}"`).join("; ")}`);
173
+ }
174
+ const sourceRequest = item.packetSourceRequest ?? item.delegatedContent;
175
+ if (sourceRequest.trim().length > 0 && sourceRequest.trim() !== item.packetObjective.trim()) {
176
+ lines.push(` source request: "${preview(sourceRequest, PACKET_SOURCE_PREVIEW_MAX)}"`);
177
+ }
178
+ continue;
179
+ }
180
+ lines.push(`- [${item.id}] ${item.friendName} asked: "${preview(item.delegatedContent, CONTENT_PREVIEW_MAX)}"`);
181
+ }
182
+ return lines.join("\n");
183
+ }
184
+ function buildAttentionQueueStatusFrame(queue) {
185
+ return buildAttentionQueueSummary(queue);
186
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAwaitTurnMessage = buildAwaitTurnMessage;
4
+ const runtime_1 = require("../nerves/runtime");
5
+ function formatElapsed(ms) {
6
+ if (ms < 60_000)
7
+ return "<1m ago";
8
+ const minutes = Math.floor(ms / 60_000);
9
+ if (minutes < 60)
10
+ return `${minutes}m ago`;
11
+ const hours = Math.floor(minutes / 60);
12
+ if (hours < 24)
13
+ return `${hours}h ago`;
14
+ const days = Math.floor(hours / 24);
15
+ return `${days}d ago`;
16
+ }
17
+ function relativeAge(lastCheckedAt, now) {
18
+ if (!lastCheckedAt)
19
+ return null;
20
+ const lastMs = new Date(lastCheckedAt).getTime();
21
+ if (!Number.isFinite(lastMs))
22
+ return null;
23
+ return formatElapsed(now().getTime() - lastMs);
24
+ }
25
+ function buildAwaitTurnMessage(options) {
26
+ (0, runtime_1.emitNervesEvent)({
27
+ component: "senses",
28
+ event: "senses.await_turn_message_built",
29
+ message: "built await tick message",
30
+ meta: { awaitName: options.awaitName, checkedCount: options.checkedCount },
31
+ });
32
+ const lines = [];
33
+ lines.push(`await tick: ${options.awaitName} — ${options.condition}`);
34
+ if (options.body && options.body.trim().length > 0) {
35
+ lines.push("");
36
+ lines.push("what would count as ready:");
37
+ lines.push(options.body.trim());
38
+ }
39
+ const age = relativeAge(options.lastCheckedAt, options.now);
40
+ const obs = options.lastObservation && options.lastObservation.trim().length > 0
41
+ ? `last observation: "${options.lastObservation.trim()}"`
42
+ : "last observation: (none yet)";
43
+ if (options.checkedCount === 0) {
44
+ lines.push("");
45
+ lines.push("history: never checked. this is my first look.");
46
+ }
47
+ else {
48
+ lines.push("");
49
+ lines.push(`history: checked ${options.checkedCount}x so far. last checked ${age ?? "(unknown)"}. ${obs}.`);
50
+ }
51
+ if (options.checkpoint) {
52
+ lines.push("");
53
+ lines.push(`last checkpoint: ${options.checkpoint}`);
54
+ }
55
+ lines.push("");
56
+ lines.push("look around and decide. if the condition is met, call resolve_await with verdict='yes' and a one-line observation. otherwise call resolve_await with verdict='no' and a one-line observation of what i saw this tick.");
57
+ return lines.join("\n");
58
+ }
@@ -0,0 +1,216 @@
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.beginBlueBubblesActiveTurn = beginBlueBubblesActiveTurn;
37
+ exports.noteBlueBubblesActiveTurnVisibleActivity = noteBlueBubblesActiveTurnVisibleActivity;
38
+ exports.finishBlueBubblesActiveTurn = finishBlueBubblesActiveTurn;
39
+ exports.listBlueBubblesActiveTurns = listBlueBubblesActiveTurns;
40
+ exports.snapshotBlueBubblesActiveTurns = snapshotBlueBubblesActiveTurns;
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const config_1 = require("../../heart/config");
44
+ const identity_1 = require("../../heart/identity");
45
+ const runtime_1 = require("../../nerves/runtime");
46
+ function activeTurnsDir(agentName) {
47
+ return path.join((0, identity_1.getAgentRoot)(agentName), "state", "senses", "bluebubbles", "active-turns");
48
+ }
49
+ function activeTurnPath(agentName, turnId) {
50
+ return path.join(activeTurnsDir(agentName), `${(0, config_1.sanitizeKey)(turnId)}.json`);
51
+ }
52
+ function isPidAlive(pid) {
53
+ try {
54
+ process.kill(pid, 0);
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ function parseActiveTurn(raw) {
62
+ try {
63
+ const parsed = JSON.parse(raw);
64
+ if (!parsed.turnId || !parsed.messageGuid || !parsed.sessionKey || !parsed.startedAt)
65
+ return null;
66
+ if (typeof parsed.pid !== "number")
67
+ return null;
68
+ return {
69
+ turnId: parsed.turnId,
70
+ pid: parsed.pid,
71
+ startedAt: parsed.startedAt,
72
+ lastVisibleActivityAt: typeof parsed.lastVisibleActivityAt === "string"
73
+ ? parsed.lastVisibleActivityAt
74
+ : undefined,
75
+ messageGuid: parsed.messageGuid,
76
+ sessionKey: parsed.sessionKey,
77
+ chatGuid: parsed.chatGuid ?? null,
78
+ chatIdentifier: parsed.chatIdentifier ?? null,
79
+ };
80
+ }
81
+ catch {
82
+ return null;
83
+ }
84
+ }
85
+ function beginBlueBubblesActiveTurn(agentName, event) {
86
+ const turnId = `${event.chat.sessionKey}:${event.messageGuid}:${process.pid}`;
87
+ const entry = {
88
+ turnId,
89
+ pid: process.pid,
90
+ startedAt: new Date().toISOString(),
91
+ messageGuid: event.messageGuid,
92
+ sessionKey: event.chat.sessionKey,
93
+ chatGuid: event.chat.chatGuid ?? null,
94
+ chatIdentifier: event.chat.chatIdentifier ?? null,
95
+ };
96
+ const filePath = activeTurnPath(agentName, turnId);
97
+ try {
98
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
99
+ fs.writeFileSync(filePath, JSON.stringify(entry, null, 2) + "\n", "utf-8");
100
+ }
101
+ catch (error) {
102
+ (0, runtime_1.emitNervesEvent)({
103
+ level: "warn",
104
+ component: "senses",
105
+ event: "senses.bluebubbles_active_turn_write_error",
106
+ message: "failed to record active bluebubbles turn",
107
+ meta: {
108
+ agentName,
109
+ messageGuid: event.messageGuid,
110
+ sessionKey: event.chat.sessionKey,
111
+ /* v8 ignore next -- filesystem writes throw Error instances; stringify guard is defensive @preserve */
112
+ reason: error instanceof Error ? error.message : String(error),
113
+ },
114
+ });
115
+ }
116
+ return turnId;
117
+ }
118
+ function noteBlueBubblesActiveTurnVisibleActivity(agentName, turnId) {
119
+ const filePath = activeTurnPath(agentName, turnId);
120
+ let entry = null;
121
+ try {
122
+ entry = parseActiveTurn(fs.readFileSync(filePath, "utf-8"));
123
+ }
124
+ catch {
125
+ return;
126
+ }
127
+ if (!entry)
128
+ return;
129
+ try {
130
+ fs.writeFileSync(filePath, JSON.stringify({ ...entry, lastVisibleActivityAt: new Date().toISOString() }, null, 2) + "\n", "utf-8");
131
+ }
132
+ catch (error) {
133
+ (0, runtime_1.emitNervesEvent)({
134
+ level: "warn",
135
+ component: "senses",
136
+ event: "senses.bluebubbles_active_turn_write_error",
137
+ message: "failed to update active bluebubbles turn",
138
+ meta: {
139
+ agentName,
140
+ turnId,
141
+ /* v8 ignore next -- filesystem writes throw Error instances; stringify guard is defensive @preserve */
142
+ reason: error instanceof Error ? error.message : String(error),
143
+ },
144
+ });
145
+ }
146
+ }
147
+ function finishBlueBubblesActiveTurn(agentName, turnId) {
148
+ try {
149
+ fs.unlinkSync(activeTurnPath(agentName, turnId));
150
+ }
151
+ catch {
152
+ // Missing active-turn files are harmless: this is best-effort telemetry.
153
+ }
154
+ }
155
+ function listBlueBubblesActiveTurns(agentName) {
156
+ let files;
157
+ try {
158
+ files = fs.readdirSync(activeTurnsDir(agentName)).filter((name) => name.endsWith(".json")).sort();
159
+ }
160
+ catch {
161
+ return [];
162
+ }
163
+ const entries = [];
164
+ for (const file of files) {
165
+ const filePath = path.join(activeTurnsDir(agentName), file);
166
+ let entry = null;
167
+ try {
168
+ entry = parseActiveTurn(fs.readFileSync(filePath, "utf-8"));
169
+ }
170
+ catch {
171
+ entry = null;
172
+ }
173
+ if (!entry) {
174
+ try {
175
+ fs.unlinkSync(filePath);
176
+ }
177
+ catch { /* ignore corrupt cleanup races */ }
178
+ continue;
179
+ }
180
+ if (!isPidAlive(entry.pid)) {
181
+ try {
182
+ fs.unlinkSync(filePath);
183
+ }
184
+ catch { /* ignore stale cleanup races */ }
185
+ (0, runtime_1.emitNervesEvent)({
186
+ level: "warn",
187
+ component: "senses",
188
+ event: "senses.bluebubbles_active_turn_pruned",
189
+ message: "pruned stale bluebubbles active-turn marker",
190
+ meta: {
191
+ agentName,
192
+ messageGuid: entry.messageGuid,
193
+ sessionKey: entry.sessionKey,
194
+ pid: entry.pid,
195
+ },
196
+ });
197
+ continue;
198
+ }
199
+ entries.push(entry);
200
+ }
201
+ return entries;
202
+ }
203
+ function snapshotBlueBubblesActiveTurns(agentName, stalledAfterMs, nowMs = Date.now()) {
204
+ const entries = listBlueBubblesActiveTurns(agentName);
205
+ const started = entries
206
+ .map((entry) => ({ value: entry.startedAt, ms: Date.parse(entry.startedAt) }))
207
+ .filter((entry) => Number.isFinite(entry.ms))
208
+ .sort((left, right) => left.ms - right.ms);
209
+ const oldest = started[0];
210
+ return {
211
+ activeTurnCount: entries.length,
212
+ stalledTurnCount: started.filter((entry) => nowMs - entry.ms >= stalledAfterMs).length,
213
+ oldestActiveTurnStartedAt: oldest?.value,
214
+ oldestActiveTurnAgeMs: oldest ? Math.max(0, nowMs - oldest.ms) : undefined,
215
+ };
216
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cacheBlueBubblesAttachment = cacheBlueBubblesAttachment;
4
+ exports.lookupBlueBubblesAttachment = lookupBlueBubblesAttachment;
5
+ exports.resetBlueBubblesAttachmentCache = resetBlueBubblesAttachmentCache;
6
+ const runtime_1 = require("../../nerves/runtime");
7
+ /**
8
+ * Bounded process-local cache of recently-seen BlueBubbles attachment summaries.
9
+ *
10
+ * Populated at attachment-hydration time so the `describe_image` tool can
11
+ * look up a guid → summary later in the same turn (or a few turns later)
12
+ * and re-download the bytes on demand. Intentionally NOT persisted — per
13
+ * planning doc D4, session storage holds only the VLM description text,
14
+ * never the raw image bytes. The cache is cleared on daemon restart, which
15
+ * matches the product expectation that "describe_image works on recent
16
+ * messages in this session".
17
+ *
18
+ * Bounded at MAX_CACHED_ATTACHMENTS entries; oldest entries evict first
19
+ * when the limit is hit.
20
+ */
21
+ const MAX_CACHED_ATTACHMENTS = 50;
22
+ const cache = new Map();
23
+ function cacheBlueBubblesAttachment(summary) {
24
+ const guid = summary.guid?.trim();
25
+ if (!guid)
26
+ return;
27
+ // Re-insert to move to end (LRU behavior via Map insertion order).
28
+ if (cache.has(guid))
29
+ cache.delete(guid);
30
+ cache.set(guid, { ...summary });
31
+ while (cache.size > MAX_CACHED_ATTACHMENTS) {
32
+ // cache.size > 0 here, so keys().next().value is always defined.
33
+ const oldestKey = cache.keys().next().value;
34
+ cache.delete(oldestKey);
35
+ }
36
+ }
37
+ function lookupBlueBubblesAttachment(guid) {
38
+ const trimmed = guid?.trim();
39
+ if (!trimmed)
40
+ return undefined;
41
+ return cache.get(trimmed);
42
+ }
43
+ function resetBlueBubblesAttachmentCache() {
44
+ cache.clear();
45
+ }
46
+ /* v8 ignore start — module-level observability event */
47
+ (0, runtime_1.emitNervesEvent)({
48
+ component: "senses",
49
+ event: "senses.bluebubbles_attachment_cache_loaded",
50
+ message: "bluebubbles attachment cache module loaded",
51
+ meta: { maxEntries: MAX_CACHED_ATTACHMENTS },
52
+ });
53
+ /* v8 ignore stop */
@@ -0,0 +1,137 @@
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.isBlueBubblesImageAttachment = isBlueBubblesImageAttachment;
37
+ exports.downloadBlueBubblesAttachment = downloadBlueBubblesAttachment;
38
+ const path = __importStar(require("node:path"));
39
+ const image_normalize_1 = require("../../heart/attachments/image-normalize");
40
+ const runtime_1 = require("../../nerves/runtime");
41
+ const MAX_NON_IMAGE_ATTACHMENT_BYTES = 8 * 1024 * 1024;
42
+ const IMAGE_EXTENSIONS = new Set([".jpg", ".jpeg", ".png", ".gif", ".webp", ".heic", ".heif", ".tif", ".tiff", ".bmp"]);
43
+ function buildBlueBubblesApiUrl(baseUrl, endpoint, password) {
44
+ const root = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
45
+ const url = new URL(endpoint.replace(/^\//, ""), root);
46
+ url.searchParams.set("password", password);
47
+ return url.toString();
48
+ }
49
+ function inferContentType(attachment, responseType) {
50
+ const normalizedResponseType = responseType?.split(";")[0]?.trim().toLowerCase();
51
+ if (normalizedResponseType) {
52
+ return normalizedResponseType;
53
+ }
54
+ return attachment.mimeType?.trim().toLowerCase() || undefined;
55
+ }
56
+ function isBlueBubblesImageAttachment(attachment, contentType) {
57
+ if (contentType?.startsWith("image/"))
58
+ return true;
59
+ const normalizedMime = attachment.mimeType?.trim().toLowerCase();
60
+ if (normalizedMime?.startsWith("image/"))
61
+ return true;
62
+ const extension = path.extname(attachment.transferName ?? "").toLowerCase();
63
+ return IMAGE_EXTENSIONS.has(extension);
64
+ }
65
+ function maxDownloadBytesForAttachment(attachment, contentType) {
66
+ return isBlueBubblesImageAttachment(attachment, contentType)
67
+ ? image_normalize_1.MAX_ATTACHMENT_DOWNLOAD_BYTES_IMAGE
68
+ : MAX_NON_IMAGE_ATTACHMENT_BYTES;
69
+ }
70
+ async function downloadBlueBubblesAttachment(attachment, config, channelConfig, fetchImpl = fetch) {
71
+ const guid = attachment.guid?.trim();
72
+ if (!guid) {
73
+ (0, runtime_1.emitNervesEvent)({
74
+ level: "warn",
75
+ component: "senses",
76
+ event: "senses.bluebubbles_attachment_download_error",
77
+ message: "bluebubbles attachment download failed",
78
+ meta: { reason: "missing_guid" },
79
+ });
80
+ throw new Error("attachment guid missing");
81
+ }
82
+ const advertisedLimit = maxDownloadBytesForAttachment(attachment);
83
+ if (typeof attachment.totalBytes === "number" && attachment.totalBytes > advertisedLimit) {
84
+ (0, runtime_1.emitNervesEvent)({
85
+ level: "warn",
86
+ component: "senses",
87
+ event: "senses.bluebubbles_attachment_download_error",
88
+ message: "bluebubbles attachment download failed",
89
+ meta: { attachmentGuid: guid, reason: "advertised_limit_exceeded", advertisedLimit, totalBytes: attachment.totalBytes },
90
+ });
91
+ throw new Error(`attachment exceeds ${advertisedLimit} byte limit`);
92
+ }
93
+ const url = buildBlueBubblesApiUrl(config.serverUrl, `/api/v1/attachment/${encodeURIComponent(guid)}/download`, config.password);
94
+ (0, runtime_1.emitNervesEvent)({
95
+ component: "senses",
96
+ event: "senses.bluebubbles_attachment_download_start",
97
+ message: "bluebubbles attachment download started",
98
+ meta: { attachmentGuid: guid, advertisedLimit },
99
+ });
100
+ const response = await fetchImpl(url, {
101
+ method: "GET",
102
+ signal: AbortSignal.timeout(channelConfig.requestTimeoutMs),
103
+ });
104
+ if (!response.ok) {
105
+ (0, runtime_1.emitNervesEvent)({
106
+ level: "warn",
107
+ component: "senses",
108
+ event: "senses.bluebubbles_attachment_download_error",
109
+ message: "bluebubbles attachment download failed",
110
+ meta: { attachmentGuid: guid, reason: "http_error", status: response.status },
111
+ });
112
+ throw new Error(`HTTP ${response.status}`);
113
+ }
114
+ const contentType = inferContentType(attachment, response.headers.get("content-type"));
115
+ const buffer = Buffer.from(await response.arrayBuffer());
116
+ const actualLimit = maxDownloadBytesForAttachment(attachment, contentType);
117
+ if (buffer.length > actualLimit) {
118
+ (0, runtime_1.emitNervesEvent)({
119
+ level: "warn",
120
+ component: "senses",
121
+ event: "senses.bluebubbles_attachment_download_error",
122
+ message: "bluebubbles attachment download failed",
123
+ meta: { attachmentGuid: guid, reason: "actual_limit_exceeded", actualLimit, byteCount: buffer.length, contentType: contentType ?? null },
124
+ });
125
+ throw new Error(`attachment exceeds ${actualLimit} byte limit`);
126
+ }
127
+ (0, runtime_1.emitNervesEvent)({
128
+ component: "senses",
129
+ event: "senses.bluebubbles_attachment_download_end",
130
+ message: "bluebubbles attachment download completed",
131
+ meta: { attachmentGuid: guid, byteCount: buffer.length, contentType: contentType ?? null },
132
+ });
133
+ return {
134
+ buffer,
135
+ contentType,
136
+ };
137
+ }