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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/README.md +127 -23
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  6. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  7. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  8. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  9. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  12. package/changelog.json +3857 -0
  13. package/dist/arc/attention-types.js +8 -0
  14. package/dist/arc/cares.js +140 -0
  15. package/dist/arc/episodes.js +117 -0
  16. package/dist/arc/intentions.js +133 -0
  17. package/dist/arc/json-store.js +117 -0
  18. package/dist/arc/obligations.js +254 -0
  19. package/dist/arc/packets.js +193 -0
  20. package/dist/arc/presence.js +185 -0
  21. package/dist/arc/task-lifecycle.js +65 -0
  22. package/dist/heart/active-work.js +837 -26
  23. package/dist/heart/agent-entry.js +69 -3
  24. package/dist/heart/attachments/image-normalize.js +194 -0
  25. package/dist/heart/attachments/materialize.js +97 -0
  26. package/dist/heart/attachments/originals.js +88 -0
  27. package/dist/heart/attachments/render.js +29 -0
  28. package/dist/heart/attachments/sources/adapter.js +2 -0
  29. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  30. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  31. package/dist/heart/attachments/sources/index.js +16 -0
  32. package/dist/heart/attachments/store.js +103 -0
  33. package/dist/heart/attachments/types.js +93 -0
  34. package/dist/heart/auth/auth-flow.js +479 -0
  35. package/dist/heart/awaiting/await-alert.js +146 -0
  36. package/dist/heart/awaiting/await-expiry.js +108 -0
  37. package/dist/heart/awaiting/await-loader.js +91 -0
  38. package/dist/heart/awaiting/await-parser.js +141 -0
  39. package/dist/heart/awaiting/await-runtime-state.js +97 -0
  40. package/dist/heart/awaiting/await-scheduler.js +377 -0
  41. package/dist/heart/background-operations.js +281 -0
  42. package/dist/heart/bundle-state.js +168 -0
  43. package/dist/heart/commitments.js +142 -0
  44. package/dist/heart/config-registry.js +322 -0
  45. package/dist/heart/config.js +114 -119
  46. package/dist/heart/core.js +909 -246
  47. package/dist/heart/cross-chat-delivery.js +3 -18
  48. package/dist/heart/daemon/agent-config-check.js +419 -0
  49. package/dist/heart/daemon/agent-discovery.js +102 -3
  50. package/dist/heart/daemon/agent-service.js +522 -0
  51. package/dist/heart/daemon/agentic-repair.js +547 -0
  52. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  53. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  54. package/dist/heart/daemon/cadence.js +70 -0
  55. package/dist/heart/daemon/cli-defaults.js +776 -0
  56. package/dist/heart/daemon/cli-exec.js +7571 -0
  57. package/dist/heart/daemon/cli-help.js +498 -0
  58. package/dist/heart/daemon/cli-parse.js +1599 -0
  59. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  60. package/dist/heart/daemon/cli-render.js +763 -0
  61. package/dist/heart/daemon/cli-types.js +8 -0
  62. package/dist/heart/daemon/connect-bay.js +323 -0
  63. package/dist/heart/daemon/daemon-cli.js +29 -1703
  64. package/dist/heart/daemon/daemon-entry.js +485 -2
  65. package/dist/heart/daemon/daemon-health.js +176 -0
  66. package/dist/heart/daemon/daemon-rollup.js +57 -0
  67. package/dist/heart/daemon/daemon-runtime-sync.js +88 -13
  68. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  69. package/dist/heart/daemon/daemon.js +842 -69
  70. package/dist/heart/daemon/dns-workflow.js +394 -0
  71. package/dist/heart/daemon/doctor-types.js +8 -0
  72. package/dist/heart/daemon/doctor.js +873 -0
  73. package/dist/heart/daemon/health-monitor.js +122 -1
  74. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  75. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  76. package/dist/heart/daemon/http-health-probe.js +80 -0
  77. package/dist/heart/daemon/human-command-screens.js +234 -0
  78. package/dist/heart/daemon/human-readiness.js +114 -0
  79. package/dist/heart/daemon/inner-status.js +89 -0
  80. package/dist/heart/daemon/interactive-repair.js +394 -0
  81. package/dist/heart/daemon/launchd.js +37 -8
  82. package/dist/heart/daemon/log-tailer.js +78 -9
  83. package/dist/heart/daemon/logs-prune.js +110 -0
  84. package/dist/heart/daemon/mcp-canary.js +297 -0
  85. package/dist/heart/daemon/os-cron-deps.js +135 -0
  86. package/dist/heart/daemon/os-cron.js +14 -12
  87. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  88. package/dist/heart/daemon/ouro-entry.js +3 -1
  89. package/dist/heart/daemon/process-manager.js +375 -33
  90. package/dist/heart/daemon/provider-discovery.js +137 -0
  91. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  92. package/dist/heart/daemon/pulse.js +475 -0
  93. package/dist/heart/daemon/readiness-repair.js +365 -0
  94. package/dist/heart/daemon/run-hooks.js +2 -0
  95. package/dist/heart/daemon/runtime-logging.js +10 -2
  96. package/dist/heart/daemon/runtime-metadata.js +2 -30
  97. package/dist/heart/daemon/safe-mode.js +161 -0
  98. package/dist/heart/daemon/sense-manager.js +462 -38
  99. package/dist/heart/daemon/session-id-resolver.js +131 -0
  100. package/dist/heart/daemon/skill-management-installer.js +94 -0
  101. package/dist/heart/daemon/socket-client.js +158 -11
  102. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  103. package/dist/heart/daemon/startup-tui.js +330 -0
  104. package/dist/heart/daemon/task-scheduler.js +3 -25
  105. package/dist/heart/daemon/terminal-ui.js +499 -0
  106. package/dist/heart/daemon/thoughts.js +162 -17
  107. package/dist/heart/daemon/up-progress.js +366 -0
  108. package/dist/heart/daemon/vault-items.js +56 -0
  109. package/dist/heart/delegation.js +1 -1
  110. package/dist/heart/habits/habit-migration.js +189 -0
  111. package/dist/heart/habits/habit-parser.js +140 -0
  112. package/dist/heart/habits/habit-runtime-state.js +100 -0
  113. package/dist/heart/habits/habit-scheduler.js +372 -0
  114. package/dist/heart/{daemon → hatch}/hatch-flow.js +32 -56
  115. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  116. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  117. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  118. package/dist/heart/identity.js +166 -55
  119. package/dist/heart/kept-notes.js +357 -0
  120. package/dist/heart/kicks.js +1 -1
  121. package/dist/heart/machine-identity.js +161 -0
  122. package/dist/heart/mail-import-discovery.js +353 -0
  123. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  124. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  125. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  126. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  127. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  128. package/dist/heart/mailbox/mailbox-http.js +99 -0
  129. package/dist/heart/mailbox/mailbox-read.js +31 -0
  130. package/dist/heart/mailbox/mailbox-types.js +27 -0
  131. package/dist/heart/mailbox/mailbox-view.js +195 -0
  132. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  133. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  134. package/dist/heart/mailbox/readers/mail.js +367 -0
  135. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  136. package/dist/heart/mailbox/readers/sessions.js +232 -0
  137. package/dist/heart/mailbox/readers/shared.js +111 -0
  138. package/dist/heart/mcp/mcp-server.js +656 -0
  139. package/dist/heart/migrate-config.js +100 -0
  140. package/dist/heart/model-capabilities.js +19 -0
  141. package/dist/heart/platform.js +81 -0
  142. package/dist/heart/provider-attempt.js +134 -0
  143. package/dist/heart/provider-binding-resolver.js +267 -0
  144. package/dist/heart/provider-credentials.js +425 -0
  145. package/dist/heart/provider-failover.js +301 -0
  146. package/dist/heart/provider-models.js +81 -0
  147. package/dist/heart/provider-ping.js +262 -0
  148. package/dist/heart/provider-readiness-cache.js +40 -0
  149. package/dist/heart/provider-visibility.js +188 -0
  150. package/dist/heart/providers/anthropic-token.js +131 -0
  151. package/dist/heart/providers/anthropic.js +139 -52
  152. package/dist/heart/providers/azure.js +23 -11
  153. package/dist/heart/providers/error-classification.js +127 -0
  154. package/dist/heart/providers/github-copilot.js +145 -0
  155. package/dist/heart/providers/minimax-vlm.js +189 -0
  156. package/dist/heart/providers/minimax.js +26 -8
  157. package/dist/heart/providers/openai-codex.js +55 -40
  158. package/dist/heart/runtime-capability-check.js +170 -0
  159. package/dist/heart/runtime-credentials.js +367 -0
  160. package/dist/heart/runtime-cwd.js +87 -0
  161. package/dist/heart/sense-truth.js +13 -4
  162. package/dist/heart/session-activity.js +43 -22
  163. package/dist/heart/session-events.js +1149 -0
  164. package/dist/heart/session-playback-cli-main.js +5 -0
  165. package/dist/heart/session-playback-cli.js +36 -0
  166. package/dist/heart/session-playback.js +231 -0
  167. package/dist/heart/session-stats-cli-main.js +5 -0
  168. package/dist/heart/session-stats.js +182 -0
  169. package/dist/heart/session-transcript.js +243 -0
  170. package/dist/heart/start-of-turn-packet.js +345 -0
  171. package/dist/heart/streaming.js +44 -27
  172. package/dist/heart/sync-classification.js +176 -0
  173. package/dist/heart/sync.js +449 -0
  174. package/dist/heart/target-resolution.js +9 -5
  175. package/dist/heart/tempo.js +93 -0
  176. package/dist/heart/temporal-view.js +41 -0
  177. package/dist/heart/timeouts.js +101 -0
  178. package/dist/heart/tool-activity-callbacks.js +59 -0
  179. package/dist/heart/tool-description.js +143 -0
  180. package/dist/heart/tool-friction.js +55 -0
  181. package/dist/heart/tool-loop.js +200 -0
  182. package/dist/heart/turn-context.js +421 -0
  183. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  184. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  185. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  186. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  187. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  188. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  189. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  190. package/dist/mailbox-ui/assets/index-B-461hes.js +61 -0
  191. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  192. package/dist/mailbox-ui/index.html +15 -0
  193. package/dist/mailroom/attention.js +167 -0
  194. package/dist/mailroom/autonomy.js +209 -0
  195. package/dist/mailroom/blob-store.js +700 -0
  196. package/dist/mailroom/body-cache.js +61 -0
  197. package/dist/mailroom/core.js +788 -0
  198. package/dist/mailroom/entry.js +160 -0
  199. package/dist/mailroom/file-store.js +457 -0
  200. package/dist/mailroom/mbox-import.js +393 -0
  201. package/dist/mailroom/migration.js +164 -0
  202. package/dist/mailroom/outbound.js +380 -0
  203. package/dist/mailroom/policy.js +263 -0
  204. package/dist/mailroom/reader.js +233 -0
  205. package/dist/mailroom/search-cache.js +268 -0
  206. package/dist/mailroom/search-relevance.js +319 -0
  207. package/dist/mailroom/smtp-ingress.js +176 -0
  208. package/dist/mailroom/source-state.js +176 -0
  209. package/dist/mailroom/thread.js +109 -0
  210. package/dist/mailroom/travel-extract.js +89 -0
  211. package/dist/mind/bundle-manifest.js +7 -1
  212. package/dist/mind/context.js +165 -101
  213. package/dist/mind/diary-integrity.js +60 -0
  214. package/dist/mind/{memory.js → diary.js} +62 -75
  215. package/dist/mind/embedding-provider.js +60 -0
  216. package/dist/mind/file-state.js +179 -0
  217. package/dist/mind/friends/channel.js +39 -0
  218. package/dist/mind/friends/resolver.js +54 -2
  219. package/dist/mind/friends/store-file.js +39 -3
  220. package/dist/mind/friends/types.js +2 -2
  221. package/dist/mind/journal-index.js +161 -0
  222. package/dist/mind/note-search.js +268 -0
  223. package/dist/mind/obligation-steering.js +221 -0
  224. package/dist/mind/pending.js +4 -0
  225. package/dist/mind/prompt-refresh.js +3 -2
  226. package/dist/mind/prompt.js +1050 -135
  227. package/dist/mind/provenance-trust.js +26 -0
  228. package/dist/mind/scrutiny.js +173 -0
  229. package/dist/nerves/cli-logging.js +7 -1
  230. package/dist/nerves/coverage/audit-rules.js +15 -6
  231. package/dist/nerves/coverage/audit.js +28 -2
  232. package/dist/nerves/coverage/cli.js +1 -1
  233. package/dist/nerves/coverage/contract.js +5 -5
  234. package/dist/nerves/coverage/file-completeness.js +129 -5
  235. package/dist/nerves/event-buffer.js +111 -0
  236. package/dist/nerves/index.js +224 -4
  237. package/dist/nerves/observation.js +20 -0
  238. package/dist/nerves/redact.js +79 -0
  239. package/dist/nerves/review/cli-main.js +5 -0
  240. package/dist/nerves/review/cli.js +156 -0
  241. package/dist/nerves/review/core.js +152 -0
  242. package/dist/nerves/runtime.js +5 -1
  243. package/dist/repertoire/ado-client.js +15 -56
  244. package/dist/repertoire/ado-semantic.js +11 -10
  245. package/dist/repertoire/api-client.js +97 -0
  246. package/dist/repertoire/bitwarden-store.js +997 -0
  247. package/dist/repertoire/bundle-templates.js +72 -0
  248. package/dist/repertoire/bw-installer.js +180 -0
  249. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  250. package/dist/repertoire/coding/context-pack.js +330 -0
  251. package/dist/repertoire/coding/feedback.js +197 -30
  252. package/dist/repertoire/coding/manager.js +158 -9
  253. package/dist/repertoire/coding/spawner.js +55 -9
  254. package/dist/repertoire/coding/tools.js +170 -7
  255. package/dist/repertoire/commerce-errors.js +109 -0
  256. package/dist/repertoire/commerce-self-test.js +156 -0
  257. package/dist/repertoire/credential-access.js +178 -0
  258. package/dist/repertoire/duffel-client.js +185 -0
  259. package/dist/repertoire/github-client.js +14 -55
  260. package/dist/repertoire/graph-client.js +11 -52
  261. package/dist/repertoire/guardrails.js +396 -0
  262. package/dist/repertoire/mcp-client.js +295 -0
  263. package/dist/repertoire/mcp-manager.js +362 -0
  264. package/dist/repertoire/mcp-tools.js +63 -0
  265. package/dist/repertoire/shell-sessions.js +133 -0
  266. package/dist/repertoire/skills.js +15 -24
  267. package/dist/repertoire/stripe-client.js +131 -0
  268. package/dist/repertoire/tasks/board.js +31 -5
  269. package/dist/repertoire/tasks/fix.js +182 -0
  270. package/dist/repertoire/tasks/index.js +16 -4
  271. package/dist/repertoire/tasks/lifecycle.js +2 -2
  272. package/dist/repertoire/tasks/parser.js +3 -2
  273. package/dist/repertoire/tasks/scanner.js +194 -37
  274. package/dist/repertoire/tasks/transitions.js +16 -78
  275. package/dist/repertoire/tool-results.js +29 -0
  276. package/dist/repertoire/tools-attachments.js +317 -0
  277. package/dist/repertoire/tools-awaiting.js +360 -0
  278. package/dist/repertoire/tools-base.js +53 -1082
  279. package/dist/repertoire/tools-bluebubbles.js +1 -0
  280. package/dist/repertoire/tools-bridge.js +142 -0
  281. package/dist/repertoire/tools-bundle.js +984 -0
  282. package/dist/repertoire/tools-config.js +185 -0
  283. package/dist/repertoire/tools-continuity.js +248 -0
  284. package/dist/repertoire/tools-credential.js +381 -0
  285. package/dist/repertoire/tools-files.js +342 -0
  286. package/dist/repertoire/tools-flight.js +224 -0
  287. package/dist/repertoire/tools-flow.js +119 -0
  288. package/dist/repertoire/tools-github.js +1 -7
  289. package/dist/repertoire/tools-mail.js +1916 -0
  290. package/dist/repertoire/tools-notes.js +421 -0
  291. package/dist/repertoire/tools-obligations.js +142 -0
  292. package/dist/repertoire/tools-runtime.js +61 -0
  293. package/dist/repertoire/tools-session.js +809 -0
  294. package/dist/repertoire/tools-shell.js +120 -0
  295. package/dist/repertoire/tools-stripe.js +180 -0
  296. package/dist/repertoire/tools-surface.js +345 -0
  297. package/dist/repertoire/tools-teams.js +9 -39
  298. package/dist/repertoire/tools-travel.js +125 -0
  299. package/dist/repertoire/tools-trip.js +604 -0
  300. package/dist/repertoire/tools-user-profile.js +144 -0
  301. package/dist/repertoire/tools-vault.js +40 -0
  302. package/dist/repertoire/tools-voice.js +144 -0
  303. package/dist/repertoire/tools.js +115 -103
  304. package/dist/repertoire/travel-api-client.js +360 -0
  305. package/dist/repertoire/user-profile.js +131 -0
  306. package/dist/repertoire/vault-setup.js +246 -0
  307. package/dist/repertoire/vault-unlock.js +594 -0
  308. package/dist/scripts/claude-code-hook.js +41 -0
  309. package/dist/scripts/claude-code-stop-hook.js +47 -0
  310. package/dist/senses/attention-queue.js +116 -0
  311. package/dist/senses/await-turn-message.js +58 -0
  312. package/dist/senses/bluebubbles/active-turns.js +216 -0
  313. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  314. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  315. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  316. package/dist/senses/bluebubbles/entry.js +77 -0
  317. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  318. package/dist/senses/bluebubbles/index.js +2548 -0
  319. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -71
  320. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  321. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  322. package/dist/senses/bluebubbles/processed-log.js +133 -0
  323. package/dist/senses/bluebubbles/replay.js +137 -0
  324. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  325. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  326. package/dist/senses/bluebubbles-meta-guard.js +40 -0
  327. package/dist/senses/cli/bracketed-paste.js +82 -0
  328. package/dist/senses/cli/image-paste.js +287 -0
  329. package/dist/senses/cli/image-ref-navigation.js +75 -0
  330. package/dist/senses/cli/ink-app.js +156 -0
  331. package/dist/senses/cli/inline-diff.js +64 -0
  332. package/dist/senses/cli/input-keys.js +174 -0
  333. package/dist/senses/cli/kill-ring.js +86 -0
  334. package/dist/senses/cli/message-list.js +51 -0
  335. package/dist/senses/cli/ouro-tui.js +607 -0
  336. package/dist/senses/cli/spinner-imperative.js +135 -0
  337. package/dist/senses/cli/spinner.js +101 -0
  338. package/dist/senses/cli/status-line.js +60 -0
  339. package/dist/senses/cli/streaming-markdown.js +526 -0
  340. package/dist/senses/cli/tool-display.js +85 -0
  341. package/dist/senses/cli/tool-render.js +85 -0
  342. package/dist/senses/cli/tui-store.js +240 -0
  343. package/dist/senses/cli/virtual-list.js +35 -0
  344. package/dist/senses/cli-entry.js +60 -8
  345. package/dist/senses/cli-layout.js +100 -0
  346. package/dist/senses/cli.js +516 -204
  347. package/dist/senses/commands.js +66 -3
  348. package/dist/senses/habit-turn-message.js +108 -0
  349. package/dist/senses/inner-dialog-worker.js +185 -21
  350. package/dist/senses/inner-dialog.js +372 -27
  351. package/dist/senses/mail-entry.js +66 -0
  352. package/dist/senses/mail.js +379 -0
  353. package/dist/senses/pipeline.js +654 -181
  354. package/dist/senses/proactive-content-guard.js +51 -0
  355. package/dist/senses/shared-turn.js +392 -0
  356. package/dist/senses/surface-tool.js +70 -0
  357. package/dist/senses/teams-entry.js +60 -8
  358. package/dist/senses/teams.js +387 -98
  359. package/dist/senses/trust-gate.js +100 -5
  360. package/dist/senses/voice/audio-playback.js +237 -0
  361. package/dist/senses/voice/audio-routing.js +119 -0
  362. package/dist/senses/voice/elevenlabs.js +202 -0
  363. package/dist/senses/voice/floor-control.js +431 -0
  364. package/dist/senses/voice/floor-controller.js +115 -0
  365. package/dist/senses/voice/golden-path.js +116 -0
  366. package/dist/senses/voice/index.js +29 -0
  367. package/dist/senses/voice/meeting.js +113 -0
  368. package/dist/senses/voice/outbound.js +190 -0
  369. package/dist/senses/voice/phone.js +33 -0
  370. package/dist/senses/voice/playback.js +139 -0
  371. package/dist/senses/voice/realtime-eval.js +496 -0
  372. package/dist/senses/voice/realtime-trace.js +531 -0
  373. package/dist/senses/voice/transcript.js +70 -0
  374. package/dist/senses/voice/turn.js +191 -0
  375. package/dist/senses/voice/twilio-phone-runtime.js +807 -0
  376. package/dist/senses/voice/twilio-phone.js +5077 -0
  377. package/dist/senses/voice/types.js +2 -0
  378. package/dist/senses/voice/whisper.js +161 -0
  379. package/dist/senses/voice-entry.js +81 -0
  380. package/dist/senses/voice-realtime-eval-command.js +99 -0
  381. package/dist/senses/voice-realtime-eval-entry.js +21 -0
  382. package/dist/senses/voice-twilio-entry.js +87 -0
  383. package/dist/trips/core.js +138 -0
  384. package/dist/trips/store.js +265 -0
  385. package/package.json +41 -7
  386. package/skills/agent-commerce.md +106 -0
  387. package/skills/browser-navigation.md +117 -0
  388. package/skills/commerce-setup-guide.md +116 -0
  389. package/skills/commerce-setup.md +84 -0
  390. package/skills/configure-dev-tools.md +99 -0
  391. package/skills/travel-planning.md +138 -0
  392. package/dist/heart/daemon/auth-flow.js +0 -351
  393. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  394. package/dist/heart/daemon/subagent-installer.js +0 -166
  395. package/dist/heart/safe-workspace.js +0 -228
  396. package/dist/heart/session-recall.js +0 -116
  397. package/dist/mind/associative-recall.js +0 -209
  398. package/dist/senses/bluebubbles-entry.js +0 -13
  399. package/dist/senses/bluebubbles.js +0 -1177
  400. package/dist/senses/debug-activity.js +0 -148
  401. package/subagents/README.md +0 -86
  402. package/subagents/work-doer.md +0 -237
  403. package/subagents/work-merger.md +0 -618
  404. package/subagents/work-planner.md +0 -390
  405. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  406. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  407. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  408. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  409. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  410. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  411. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  412. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  413. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  414. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  415. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  416. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  417. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  418. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  419. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  420. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -41,6 +41,9 @@ exports.readTaskFile = readTaskFile;
41
41
  exports.buildTaskTriggeredMessage = buildTaskTriggeredMessage;
42
42
  exports.deriveResumeCheckpoint = deriveResumeCheckpoint;
43
43
  exports.innerDialogSessionPath = innerDialogSessionPath;
44
+ exports.enrichDelegatedFromWithBridge = enrichDelegatedFromWithBridge;
45
+ exports.routeDelegatedCompletion = routeDelegatedCompletion;
46
+ exports.buildParseErrorNudge = buildParseErrorNudge;
44
47
  exports.runInnerDialogTurn = runInnerDialogTurn;
45
48
  const fs = __importStar(require("fs"));
46
49
  const path = __importStar(require("path"));
@@ -49,8 +52,13 @@ const core_1 = require("../heart/core");
49
52
  const identity_1 = require("../heart/identity");
50
53
  const context_1 = require("../mind/context");
51
54
  const prompt_1 = require("../mind/prompt");
55
+ const mcp_manager_1 = require("../repertoire/mcp-manager");
56
+ const tools_1 = require("../repertoire/tools");
52
57
  const bundle_manifest_1 = require("../mind/bundle-manifest");
53
58
  const pending_1 = require("../mind/pending");
59
+ const obligations_1 = require("../arc/obligations");
60
+ const attention_queue_1 = require("./attention-queue");
61
+ const packets_1 = require("../arc/packets");
54
62
  const channel_1 = require("../mind/friends/channel");
55
63
  const trust_gate_1 = require("./trust-gate");
56
64
  const tokens_1 = require("../mind/friends/tokens");
@@ -60,6 +68,15 @@ const runtime_1 = require("../nerves/runtime");
60
68
  const manager_1 = require("../heart/bridges/manager");
61
69
  const session_activity_1 = require("../heart/session-activity");
62
70
  const bluebubbles_1 = require("./bluebubbles");
71
+ const habit_turn_message_1 = require("./habit-turn-message");
72
+ const await_turn_message_1 = require("./await-turn-message");
73
+ const await_parser_1 = require("../heart/awaiting/await-parser");
74
+ const await_runtime_state_1 = require("../heart/awaiting/await-runtime-state");
75
+ const journal_index_1 = require("../mind/journal-index");
76
+ const habit_parser_1 = require("../heart/habits/habit-parser");
77
+ const habit_runtime_state_1 = require("../heart/habits/habit-runtime-state");
78
+ const cadence_1 = require("../heart/daemon/cadence");
79
+ const daemon_health_1 = require("../heart/daemon/daemon-health");
63
80
  const DEFAULT_INNER_DIALOG_INSTINCTS = [
64
81
  {
65
82
  id: "heartbeat_checkin",
@@ -98,23 +115,31 @@ function buildNonCanonicalCleanupNudge(nonCanonicalPaths) {
98
115
  }
99
116
  return [
100
117
  "## canonical cleanup nudge",
101
- "I found non-canonical files in my bundle. I should distill anything valuable into your memory system and remove these files.",
118
+ "I found non-canonical files in my bundle. I should distill anything valuable into my diary and remove these files.",
102
119
  ...listed,
103
120
  ].join("\n");
104
121
  }
122
+ function displayCheckpoint(checkpoint) {
123
+ const trimmed = checkpoint?.trim();
124
+ if (!trimmed || trimmed === "no prior checkpoint recorded") {
125
+ return undefined;
126
+ }
127
+ return trimmed;
128
+ }
105
129
  function buildInstinctUserMessage(instincts, _reason, state) {
106
130
  const active = instincts.find((instinct) => instinct.enabled !== false) ?? DEFAULT_INNER_DIALOG_INSTINCTS[0];
107
- const checkpoint = state.checkpoint?.trim();
131
+ const checkpoint = displayCheckpoint(state.checkpoint);
108
132
  const lines = [active.prompt];
109
133
  if (checkpoint) {
110
- lines.push(`\nlast i remember: ${checkpoint}`);
134
+ lines.push(`\nlast checkpoint: ${checkpoint}`);
111
135
  }
112
136
  return lines.join("\n");
113
137
  }
114
138
  function readTaskFile(agentRoot, taskId) {
115
- // Task files live in collection subdirectories (one-shots, ongoing, habits).
139
+ // Task files live in collection subdirectories (one-shots, ongoing).
116
140
  // Try each collection, then fall back to root tasks/ for legacy layout.
117
- const collections = ["one-shots", "ongoing", "habits", ""];
141
+ // Habits are no longer in tasks/ — they live at bundle root habits/.
142
+ const collections = ["one-shots", "ongoing", ""];
118
143
  for (const collection of collections) {
119
144
  try {
120
145
  return fs.readFileSync(path.join(agentRoot, "tasks", collection, `${taskId}.md`), "utf8").trim();
@@ -133,8 +158,9 @@ function buildTaskTriggeredMessage(taskId, taskContent, checkpoint) {
133
158
  else {
134
159
  lines.push("", `## task: ${taskId}`, "(task file not found)");
135
160
  }
136
- if (checkpoint) {
137
- lines.push("", `last i remember: ${checkpoint}`);
161
+ const renderedCheckpoint = displayCheckpoint(checkpoint);
162
+ if (renderedCheckpoint) {
163
+ lines.push("", `last checkpoint: ${renderedCheckpoint}`);
138
164
  }
139
165
  return lines.join("\n");
140
166
  }
@@ -164,19 +190,17 @@ function deriveResumeCheckpoint(messages) {
164
190
  const assistantText = contentToText(lastAssistant.content);
165
191
  if (!assistantText)
166
192
  return "no prior checkpoint recorded";
167
- const explicitCheckpoint = assistantText
193
+ const cleanedLines = assistantText
168
194
  .split("\n")
169
- .map((line) => line.trim())
195
+ .map((line) => line.replace(/<\/?think>/gi, "").trim())
196
+ .filter((line) => line.length > 0);
197
+ const explicitCheckpoint = cleanedLines
170
198
  .find((line) => /^checkpoint\s*:/i.test(line));
171
199
  if (explicitCheckpoint) {
172
200
  const parsed = explicitCheckpoint.replace(/^checkpoint\s*:\s*/i, "").trim();
173
201
  return parsed || "no prior checkpoint recorded";
174
202
  }
175
- const firstLine = assistantText
176
- .split("\n")
177
- .map((line) => line.trim())
178
- .find((line) => line.length > 0);
179
- /* v8 ignore next -- unreachable: contentToText().trim() guarantees a non-empty line @preserve */
203
+ const firstLine = cleanedLines[0];
180
204
  if (!firstLine)
181
205
  return "no prior checkpoint recorded";
182
206
  if (firstLine.length <= 220)
@@ -247,6 +271,7 @@ function writeInnerDialogRuntimeState(sessionFilePath, state) {
247
271
  });
248
272
  }
249
273
  }
274
+ /* v8 ignore start -- routing helpers: called from routing functions which are integration paths @preserve */
250
275
  function writePendingEnvelope(pendingDir, message) {
251
276
  fs.mkdirSync(pendingDir, { recursive: true });
252
277
  const fileName = `${message.timestamp}-${Math.random().toString(36).slice(2, 10)}.json`;
@@ -258,6 +283,8 @@ function sessionMatchesActivity(activity, session) {
258
283
  && activity.channel === session.channel
259
284
  && activity.key === session.key;
260
285
  }
286
+ /* v8 ignore stop */
287
+ /* v8 ignore start -- routing: delivery now inline via surface tool; routing functions preserved for reuse @preserve */
261
288
  function resolveBridgePreferredSession(delegatedFrom, sessionActivity) {
262
289
  if (!delegatedFrom.bridgeId)
263
290
  return null;
@@ -277,15 +304,82 @@ async function tryDeliverDelegatedCompletion(target, outboundEnvelope) {
277
304
  friendId: target.friendId,
278
305
  sessionKey: target.key,
279
306
  text: outboundEnvelope.content,
307
+ intent: "explicit_cross_chat",
280
308
  });
281
309
  return result.delivered;
282
310
  }
311
+ function enrichDelegatedFromWithBridge(delegatedFrom) {
312
+ if (delegatedFrom.bridgeId) {
313
+ return delegatedFrom;
314
+ }
315
+ const bridgeManager = (0, manager_1.createBridgeManager)();
316
+ const originBridges = bridgeManager.findBridgesForSession({
317
+ friendId: delegatedFrom.friendId,
318
+ channel: delegatedFrom.channel,
319
+ key: delegatedFrom.key,
320
+ });
321
+ const activeBridge = originBridges.find((b) => b.lifecycle === "active");
322
+ if (activeBridge) {
323
+ return { ...delegatedFrom, bridgeId: activeBridge.id };
324
+ }
325
+ return delegatedFrom;
326
+ }
327
+ function advanceObligationQuietly(agentName, obligationId, update) {
328
+ if (!obligationId)
329
+ return;
330
+ try {
331
+ (0, obligations_1.advanceReturnObligation)(agentName, obligationId, update);
332
+ /* v8 ignore start -- best-effort: obligation fs errors must never block return routing @preserve */
333
+ }
334
+ catch {
335
+ // swallowed
336
+ }
337
+ /* v8 ignore stop */
338
+ }
283
339
  async function routeDelegatedCompletion(agentRoot, agentName, completion, drainedPending, timestamp) {
284
340
  const delegated = (drainedPending ?? []).find((message) => message.delegatedFrom);
285
341
  if (!delegated?.delegatedFrom || !completion?.answer?.trim()) {
286
342
  return;
287
343
  }
288
- const delegatedFrom = delegated.delegatedFrom;
344
+ const delegatedFrom = enrichDelegatedFromWithBridge(delegated.delegatedFrom);
345
+ const obligationId = delegated.obligationId;
346
+ // Advance any inner return obligations from queued -> running (they were drained this turn).
347
+ // drainedPending is guaranteed non-null here (we found delegated above).
348
+ for (const msg of drainedPending) {
349
+ if (msg.obligationId) {
350
+ advanceObligationQuietly(agentName, msg.obligationId, {
351
+ status: "running",
352
+ startedAt: timestamp,
353
+ });
354
+ }
355
+ }
356
+ if (delegated.obligationStatus === "pending") {
357
+ // Fulfill the persistent obligation in the store
358
+ try {
359
+ const pending = (0, obligations_1.findPendingObligationForOrigin)(agentRoot, {
360
+ friendId: delegatedFrom.friendId,
361
+ channel: delegatedFrom.channel,
362
+ key: delegatedFrom.key,
363
+ });
364
+ /* v8 ignore next 2 -- obligation fulfillment tested via obligations.test.ts; integration requires real disk state @preserve */
365
+ if (pending) {
366
+ (0, obligations_1.fulfillObligation)(agentRoot, pending.id);
367
+ }
368
+ }
369
+ catch {
370
+ /* v8 ignore next -- defensive: obligation store read failure should not break delivery @preserve */
371
+ }
372
+ (0, runtime_1.emitNervesEvent)({
373
+ event: "senses.obligation_fulfilled",
374
+ component: "senses",
375
+ message: "obligation fulfilled via delegated completion",
376
+ meta: {
377
+ friendId: delegatedFrom.friendId,
378
+ channel: delegatedFrom.channel,
379
+ key: delegatedFrom.key,
380
+ },
381
+ });
382
+ }
289
383
  const outboundEnvelope = {
290
384
  from: agentName,
291
385
  friendId: delegatedFrom.friendId,
@@ -294,36 +388,62 @@ async function routeDelegatedCompletion(agentRoot, agentName, completion, draine
294
388
  content: completion.answer.trim(),
295
389
  timestamp,
296
390
  delegatedFrom,
391
+ ...(obligationId ? { obligationId } : {}),
297
392
  };
298
393
  const sessionActivity = (0, session_activity_1.listSessionActivity)({
299
394
  sessionsDir: path.join(agentRoot, "state", "sessions"),
300
395
  friendsDir: path.join(agentRoot, "friends"),
301
396
  agentName,
302
397
  });
398
+ // Priority 1: Bridge-preferred session (if delegation was within a bridge).
303
399
  const bridgeTarget = resolveBridgePreferredSession(delegatedFrom, sessionActivity);
304
400
  if (bridgeTarget) {
305
401
  if (await tryDeliverDelegatedCompletion(bridgeTarget, outboundEnvelope)) {
402
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
306
403
  return;
307
404
  }
308
405
  writePendingEnvelope((0, pending_1.getPendingDir)(agentName, bridgeTarget.friendId, bridgeTarget.channel, bridgeTarget.key), outboundEnvelope);
406
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "bridge-session" });
407
+ return;
408
+ }
409
+ // Priority 1.5: Direct return to originating session (ponder without bridge).
410
+ // When delegatedFrom has specific channel+key, route directly there instead of searching for freshest.
411
+ if (delegatedFrom.channel && delegatedFrom.key && delegatedFrom.channel !== "inner") {
412
+ const directTarget = sessionActivity.find((a) => a.friendId === delegatedFrom.friendId && a.channel === delegatedFrom.channel && a.key === delegatedFrom.key);
413
+ if (directTarget) {
414
+ if (await tryDeliverDelegatedCompletion(directTarget, outboundEnvelope)) {
415
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
416
+ return;
417
+ }
418
+ }
419
+ // Even if session isn't in activity list (might have ended), queue to its pending dir
420
+ writePendingEnvelope((0, pending_1.getPendingDir)(agentName, delegatedFrom.friendId, delegatedFrom.channel, delegatedFrom.key), outboundEnvelope);
421
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "direct-originator" });
309
422
  return;
310
423
  }
311
- const freshest = (0, session_activity_1.findFreshestFriendSession)({
424
+ // Priority 2: Freshest active friend session.
425
+ // For BB, prefer DM sessions (;-;) over group chats (;+;) — proactive outreach should never land in groups.
426
+ const allFriendSessions = (0, session_activity_1.listSessionActivity)({
312
427
  sessionsDir: path.join(agentRoot, "state", "sessions"),
313
428
  friendsDir: path.join(agentRoot, "friends"),
314
429
  agentName,
315
- friendId: delegatedFrom.friendId,
316
- activeOnly: true,
317
- });
318
- if (freshest && freshest.channel !== "inner") {
430
+ }).filter((s) => s.friendId === delegatedFrom.friendId && s.channel !== "inner");
431
+ const bbDm = allFriendSessions.find((s) => s.channel === "bluebubbles" && s.key.includes(";-;"));
432
+ const freshest = bbDm ?? allFriendSessions.find((s) => s.channel !== "bluebubbles" || s.key.includes(";-;")) ?? allFriendSessions[0];
433
+ if (freshest) {
319
434
  if (await tryDeliverDelegatedCompletion(freshest, outboundEnvelope)) {
435
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
320
436
  return;
321
437
  }
322
438
  writePendingEnvelope((0, pending_1.getPendingDir)(agentName, freshest.friendId, freshest.channel, freshest.key), outboundEnvelope);
439
+ advanceObligationQuietly(agentName, obligationId, { status: "returned", returnedAt: timestamp, returnTarget: "freshest-session" });
323
440
  return;
324
441
  }
442
+ // Priority 3: Deferred return queue.
325
443
  writePendingEnvelope((0, pending_1.getDeferredReturnDir)(agentName, delegatedFrom.friendId), outboundEnvelope);
444
+ advanceObligationQuietly(agentName, obligationId, { status: "deferred", returnedAt: timestamp, returnTarget: "deferred" });
326
445
  }
446
+ /* v8 ignore stop */
327
447
  // Self-referencing friend record for inner dialog (agent talking to itself).
328
448
  // No real friend to resolve -- this satisfies the pipeline's friend resolver contract.
329
449
  function createSelfFriend(agentName) {
@@ -350,12 +470,59 @@ function createNoOpFriendStore() {
350
470
  findByExternalId: async () => null,
351
471
  };
352
472
  }
473
+ function buildParseErrorNudge(parseErrors) {
474
+ if (parseErrors.length === 0)
475
+ return "";
476
+ const lines = parseErrors.map((e) => `I noticed my habit file \`${e.file}\` has invalid frontmatter — I should fix it. (${e.error})`);
477
+ return lines.join("\n");
478
+ }
479
+ function buildAlsoDueLine(agentRoot, currentHabitName, now) {
480
+ const habitsDir = path.join(agentRoot, "habits");
481
+ let files;
482
+ try {
483
+ files = fs.readdirSync(habitsDir);
484
+ }
485
+ catch {
486
+ return "";
487
+ }
488
+ const nowMs = now().getTime();
489
+ const alsoDue = [];
490
+ for (const file of files) {
491
+ if (!file.endsWith(".md"))
492
+ continue;
493
+ const stem = file.replace(/\.md$/, "");
494
+ if (stem === currentHabitName)
495
+ continue;
496
+ try {
497
+ const content = fs.readFileSync(path.join(habitsDir, file), "utf-8");
498
+ const habit = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(content, path.join(habitsDir, file)));
499
+ if (habit.status !== "active" || !habit.cadence)
500
+ continue;
501
+ const cadenceMs = (0, cadence_1.parseCadenceToMs)(habit.cadence);
502
+ if (cadenceMs === null)
503
+ continue;
504
+ if (habit.lastRun === null) {
505
+ alsoDue.push(stem);
506
+ continue;
507
+ }
508
+ const lastRunMs = new Date(habit.lastRun).getTime();
509
+ if (nowMs - lastRunMs >= cadenceMs) {
510
+ alsoDue.push(stem);
511
+ }
512
+ }
513
+ catch {
514
+ // skip unreadable habits
515
+ }
516
+ }
517
+ if (alsoDue.length === 0)
518
+ return "";
519
+ return `also due: ${alsoDue.join(", ")}`;
520
+ }
353
521
  async function runInnerDialogTurn(options) {
354
522
  const now = options?.now ?? (() => new Date());
355
- const reason = options?.reason ?? "heartbeat";
523
+ const reason = options?.reason ?? "instinct";
356
524
  const sessionFilePath = innerDialogSessionPath();
357
525
  const agentName = (0, identity_1.getAgentName)();
358
- const agentRoot = (0, identity_1.getAgentRoot)();
359
526
  writeInnerDialogRuntimeState(sessionFilePath, {
360
527
  status: "running",
361
528
  reason,
@@ -372,6 +539,8 @@ async function runInnerDialogTurn(options) {
372
539
  };
373
540
  // ── Adapter concern: build user message ──────────────────────────
374
541
  let userContent;
542
+ let habitTools;
543
+ let habitParsedSuccessfully = false;
375
544
  if (existingMessages.length === 0) {
376
545
  // Fresh session: bootstrap message with non-canonical cleanup nudge
377
546
  const aspirations = readAspirations((0, identity_1.getAgentRoot)());
@@ -391,6 +560,113 @@ async function runInnerDialogTurn(options) {
391
560
  const taskContent = readTaskFile((0, identity_1.getAgentRoot)(), options.taskId);
392
561
  userContent = buildTaskTriggeredMessage(options.taskId, taskContent, state.checkpoint);
393
562
  }
563
+ else if (reason === "habit" && options?.habitName) {
564
+ const agentRoot = (0, identity_1.getAgentRoot)();
565
+ const habitName = options.habitName;
566
+ const habitFilePath = path.join(agentRoot, "habits", `${habitName}.md`);
567
+ // Read and parse the habit file
568
+ let habitBody;
569
+ let habitTitle = habitName;
570
+ let habitLastRun = null;
571
+ try {
572
+ const habitContent = fs.readFileSync(habitFilePath, "utf-8");
573
+ const parsed = (0, habit_runtime_state_1.applyHabitRuntimeState)(agentRoot, (0, habit_parser_1.parseHabitFile)(habitContent, habitFilePath));
574
+ habitBody = parsed.body || undefined;
575
+ habitTitle = parsed.title || habitName;
576
+ habitLastRun = parsed.lastRun;
577
+ habitTools = parsed.tools;
578
+ }
579
+ catch {
580
+ // Habit file missing or unreadable
581
+ }
582
+ // If the habit file couldn't be read at all (no body, no title parsed), error message
583
+ if (habitBody === undefined && habitTitle === habitName) {
584
+ userContent = `habit "${habitName}" could not be read (file not found or unreadable). check habits/${habitName}.md exists.`;
585
+ }
586
+ else {
587
+ habitParsedSuccessfully = true;
588
+ // Unified path: gather context for ALL habits (heartbeat included)
589
+ const obligations = (0, obligations_1.listActiveReturnObligations)(agentName);
590
+ const nowMs = now().getTime();
591
+ const staleObligations = obligations.map((o) => ({
592
+ friendName: o.origin.friendId,
593
+ content: o.delegatedContent,
594
+ stalenessMs: nowMs - o.createdAt,
595
+ }));
596
+ const alsoDue = buildAlsoDueLine(agentRoot, habitName, now);
597
+ // Degraded state (best-effort: never crash)
598
+ let degradedComponents = [];
599
+ try {
600
+ const health = (0, daemon_health_1.readHealth)((0, daemon_health_1.getDefaultHealthPath)());
601
+ if (health && health.degraded.length > 0) {
602
+ degradedComponents = health.degraded.map((d) => ({ component: d.component, reason: d.reason }));
603
+ }
604
+ }
605
+ catch {
606
+ // Best-effort: missing file or parse error -> empty array, no crash
607
+ }
608
+ userContent = (0, habit_turn_message_1.buildHabitTurnMessage)({
609
+ habitName,
610
+ habitTitle,
611
+ habitBody,
612
+ lastRun: habitLastRun,
613
+ checkpoint: displayCheckpoint(state.checkpoint),
614
+ alsoDue: alsoDue || undefined,
615
+ staleObligations,
616
+ parseErrors: options?.parseErrors ?? [],
617
+ degradedComponents,
618
+ now,
619
+ });
620
+ // Piggyback journal embedding indexing (best-effort, fire-and-forget)
621
+ const journalDir = path.join(agentRoot, "journal");
622
+ /* v8 ignore start -- journal indexing piggyback: embedding provider may not be available; tested via journal-index unit tests @preserve */
623
+ void (0, journal_index_1.indexJournalFiles)(journalDir, path.join(journalDir, ".index.json"), {
624
+ embed: async () => [],
625
+ }).catch(() => {
626
+ // swallowed: indexing failure must never block habit turn
627
+ });
628
+ /* v8 ignore stop */
629
+ }
630
+ }
631
+ else if (reason === "await" && options?.awaitName) {
632
+ const agentRoot = (0, identity_1.getAgentRoot)();
633
+ const awaitName = options.awaitName;
634
+ const awaitFilePath = path.join(agentRoot, "awaiting", `${awaitName}.md`);
635
+ let awaitBody;
636
+ let condition = null;
637
+ let lastCheckedAt = null;
638
+ let lastObservation = null;
639
+ let checkedCount = 0;
640
+ let awaitFound = false;
641
+ try {
642
+ const awaitContent = fs.readFileSync(awaitFilePath, "utf-8");
643
+ const parsed = (0, await_runtime_state_1.applyAwaitRuntimeState)(agentRoot, (0, await_parser_1.parseAwaitFile)(awaitContent, awaitFilePath));
644
+ awaitFound = true;
645
+ awaitBody = parsed.body || undefined;
646
+ condition = parsed.condition;
647
+ lastCheckedAt = parsed.last_checked ?? null;
648
+ lastObservation = parsed.last_observation ?? null;
649
+ checkedCount = parsed.checked_count ?? 0;
650
+ }
651
+ catch {
652
+ // file missing — fall through to error message
653
+ }
654
+ if (!awaitFound || !condition) {
655
+ userContent = `await "${awaitName}" could not be read (file not found or no condition). check awaiting/${awaitName}.md.`;
656
+ }
657
+ else {
658
+ userContent = (0, await_turn_message_1.buildAwaitTurnMessage)({
659
+ awaitName,
660
+ condition,
661
+ body: awaitBody,
662
+ lastCheckedAt,
663
+ lastObservation,
664
+ checkedCount,
665
+ checkpoint: displayCheckpoint(state.checkpoint),
666
+ now,
667
+ });
668
+ }
669
+ }
394
670
  else {
395
671
  userContent = buildInstinctUserMessage(instincts, reason, state);
396
672
  }
@@ -401,15 +677,43 @@ async function runInnerDialogTurn(options) {
401
677
  const pendingDir = (0, pending_1.getInnerDialogPendingDir)(agentName);
402
678
  const selfFriend = createSelfFriend(agentName);
403
679
  const selfContext = { friend: selfFriend, channel: innerCapabilities };
680
+ const mcpManager = await (0, mcp_manager_1.getSharedMcpManager)() ?? undefined;
681
+ // ── Habit tool enforcement ───────────────────────────────────────
682
+ let habitToolsResolved;
683
+ if (habitTools !== undefined) {
684
+ const fullTools = (0, tools_1.getToolsForChannel)(innerCapabilities);
685
+ habitToolsResolved = fullTools.filter((t) => habitTools.includes(t.function.name));
686
+ (0, runtime_1.emitNervesEvent)({
687
+ event: "habit.tools_restricted",
688
+ component: "senses",
689
+ message: "habit running with restricted tools",
690
+ meta: {
691
+ habitName: options?.habitName,
692
+ declared: habitTools,
693
+ resolved: habitToolsResolved.map((t) => t.function.name),
694
+ },
695
+ });
696
+ }
697
+ else if (reason === "habit" && options?.habitName && habitParsedSuccessfully) {
698
+ (0, runtime_1.emitNervesEvent)({
699
+ event: "habit.tools_unrestricted",
700
+ component: "senses",
701
+ message: "habit running with full tool repertoire",
702
+ meta: { habitName: options.habitName },
703
+ });
704
+ }
404
705
  const sessionLoader = {
405
706
  loadOrCreate: async () => {
406
707
  if (existingMessages.length > 0) {
407
- return { messages: existingMessages, sessionPath: sessionFilePath };
708
+ return {
709
+ messages: existingMessages,
710
+ sessionPath: sessionFilePath,
711
+ };
408
712
  }
409
713
  // Fresh session: build system prompt
410
714
  const systemPrompt = await (0, prompt_1.buildSystem)("inner", { toolChoiceRequired: true });
411
715
  return {
412
- messages: [{ role: "system", content: systemPrompt }],
716
+ messages: [{ role: "system", content: (0, prompt_1.flattenSystemPrompt)(systemPrompt) }],
413
717
  sessionPath: sessionFilePath,
414
718
  };
415
719
  },
@@ -417,6 +721,8 @@ async function runInnerDialogTurn(options) {
417
721
  // ── Call shared pipeline ──────────────────────────────────────────
418
722
  const callbacks = createInnerDialogCallbacks();
419
723
  const traceId = (0, nerves_1.createTraceId)();
724
+ // Attention queue: built when pending messages are drained, shared with tool context
725
+ let attentionQueue = [];
420
726
  const result = await (0, pipeline_1.handleInboundTurn)({
421
727
  channel: "inner",
422
728
  sessionKey: "dialog",
@@ -431,16 +737,55 @@ async function runInnerDialogTurn(options) {
431
737
  enforceTrustGate: trust_gate_1.enforceTrustGate,
432
738
  drainPending: pending_1.drainPending,
433
739
  runAgent: core_1.runAgent,
434
- postTurn: context_1.postTurn,
740
+ postTurn: (turnMessages, sessionPathArg, usage, hooks, state) => {
741
+ const prepared = (0, context_1.postTurnTrim)(turnMessages, usage, hooks);
742
+ (0, context_1.deferPostTurnPersist)(sessionPathArg, prepared, usage, state);
743
+ },
435
744
  accumulateFriendTokens: tokens_1.accumulateFriendTokens,
436
745
  signal: options?.signal,
746
+ /* v8 ignore start -- attention queue: callback invoked by pipeline during pending drain; tested via attention-queue unit tests @preserve */
747
+ onPendingDrained: (drained) => {
748
+ const outstandingObligations = (0, obligations_1.listActiveReturnObligations)(agentName);
749
+ attentionQueue = (0, attention_queue_1.buildAttentionQueue)({
750
+ drainedPending: drained,
751
+ outstandingObligations,
752
+ friendNameResolver: (friendId) => {
753
+ try {
754
+ const raw = fs.readFileSync(path.join((0, identity_1.getAgentRoot)(agentName), "friends", friendId + ".json"), "utf-8");
755
+ const parsed = JSON.parse(raw);
756
+ return typeof parsed.name === "string" ? parsed.name : null;
757
+ }
758
+ catch {
759
+ return null;
760
+ }
761
+ },
762
+ packetResolver: (packetId) => {
763
+ try {
764
+ return (0, packets_1.readPonderPacket)((0, identity_1.getAgentRoot)(agentName), packetId);
765
+ }
766
+ catch {
767
+ return null;
768
+ }
769
+ },
770
+ });
771
+ const summary = (0, attention_queue_1.buildAttentionQueueSummary)(attentionQueue);
772
+ return summary ? [summary] : [];
773
+ },
774
+ /* v8 ignore stop */
437
775
  runAgentOptions: {
438
776
  traceId,
439
777
  toolChoiceRequired: true,
440
- skipConfirmation: true,
778
+ mcpManager,
779
+ ...(habitToolsResolved !== undefined && { tools: habitToolsResolved }),
780
+ toolContext: {
781
+ signin: async () => undefined,
782
+ delegatedOrigins: attentionQueue,
783
+ },
441
784
  },
442
785
  });
443
- await routeDelegatedCompletion(agentRoot, agentName, result.completion, result.drainedPending, now().getTime());
786
+ // Post-turn routeDelegatedCompletion removed: delivery is now inline via surface tool.
787
+ // settle in inner dialog produces no CompletionMetadata, so routeDelegatedCompletion
788
+ // would be a no-op. The routing infrastructure is reused by the surface handler.
444
789
  const resultMessages = result.messages ?? [];
445
790
  const assistantPreview = extractAssistantPreview(resultMessages);
446
791
  const toolCalls = extractToolCallNames(resultMessages);
@@ -0,0 +1,66 @@
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
+ const agentArgIndex = process.argv.indexOf("--agent");
37
+ const agentName = agentArgIndex >= 0 ? process.argv[agentArgIndex + 1] : undefined;
38
+ if (!agentName) {
39
+ // eslint-disable-next-line no-console -- pre-boot guard: --agent check before imports
40
+ console.error("Missing required --agent <name> argument.\nUsage: node dist/senses/mail-entry.js --agent ouroboros");
41
+ process.exit(1);
42
+ }
43
+ const runtime_logging_1 = require("../heart/daemon/runtime-logging");
44
+ const runtime_1 = require("../nerves/runtime");
45
+ (0, runtime_logging_1.configureDaemonRuntimeLogger)("mail");
46
+ (0, runtime_1.emitNervesEvent)({
47
+ component: "senses",
48
+ event: "senses.entry_boot",
49
+ message: "booting Mail entrypoint",
50
+ meta: { entry: "mail", agentName },
51
+ });
52
+ Promise.resolve().then(() => __importStar(require("./mail"))).then(async ({ startMailSenseApp }) => {
53
+ await startMailSenseApp({ agentName });
54
+ })
55
+ .catch((error) => {
56
+ (0, runtime_1.emitNervesEvent)({
57
+ level: "error",
58
+ component: "senses",
59
+ event: "senses.entry_error",
60
+ message: "Mail entrypoint failed",
61
+ meta: { entry: "mail", agentName, error: error instanceof Error ? error.message : String(error) },
62
+ });
63
+ // eslint-disable-next-line no-console -- fatal startup guard for sense process
64
+ console.error(error instanceof Error ? error.message : String(error));
65
+ process.exit(1);
66
+ });