@ouro.bot/cli 0.1.0-alpha.48 → 0.1.0-alpha.481

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 (358) hide show
  1. package/README.md +132 -19
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +3069 -0
  6. package/dist/arc/attention-types.js +8 -0
  7. package/dist/arc/cares.js +140 -0
  8. package/dist/arc/episodes.js +117 -0
  9. package/dist/arc/intentions.js +133 -0
  10. package/dist/arc/json-store.js +117 -0
  11. package/dist/arc/obligations.js +237 -0
  12. package/dist/arc/packets.js +193 -0
  13. package/dist/arc/presence.js +185 -0
  14. package/dist/arc/task-lifecycle.js +65 -0
  15. package/dist/heart/active-work.js +857 -0
  16. package/dist/heart/agent-entry.js +58 -3
  17. package/dist/heart/attachments/image-normalize.js +194 -0
  18. package/dist/heart/attachments/materialize.js +97 -0
  19. package/dist/heart/attachments/originals.js +88 -0
  20. package/dist/heart/attachments/render.js +29 -0
  21. package/dist/heart/attachments/sources/adapter.js +2 -0
  22. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  23. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  24. package/dist/heart/attachments/sources/index.js +16 -0
  25. package/dist/heart/attachments/store.js +103 -0
  26. package/dist/heart/attachments/types.js +93 -0
  27. package/dist/heart/auth/auth-flow.js +426 -0
  28. package/dist/heart/background-operations.js +234 -0
  29. package/dist/heart/bridges/manager.js +358 -0
  30. package/dist/heart/bridges/state-machine.js +135 -0
  31. package/dist/heart/bridges/store.js +123 -0
  32. package/dist/heart/bundle-state.js +168 -0
  33. package/dist/heart/commitments.js +111 -0
  34. package/dist/heart/config-registry.js +304 -0
  35. package/dist/heart/config.js +110 -128
  36. package/dist/heart/core.js +745 -227
  37. package/dist/heart/cross-chat-delivery.js +131 -0
  38. package/dist/heart/daemon/agent-config-check.js +490 -0
  39. package/dist/heart/daemon/agent-discovery.js +79 -3
  40. package/dist/heart/daemon/agent-service.js +360 -0
  41. package/dist/heart/daemon/agentic-repair.js +216 -0
  42. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  43. package/dist/heart/daemon/cadence.js +70 -0
  44. package/dist/heart/daemon/cli-defaults.js +640 -0
  45. package/dist/heart/daemon/cli-exec.js +6933 -0
  46. package/dist/heart/daemon/cli-help.js +487 -0
  47. package/dist/heart/daemon/cli-parse.js +1527 -0
  48. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  49. package/dist/heart/daemon/cli-render.js +561 -0
  50. package/dist/heart/daemon/cli-types.js +8 -0
  51. package/dist/heart/daemon/connect-bay.js +323 -0
  52. package/dist/heart/daemon/daemon-cli.js +29 -1616
  53. package/dist/heart/daemon/daemon-entry.js +345 -3
  54. package/dist/heart/daemon/daemon-health.js +141 -0
  55. package/dist/heart/daemon/daemon-runtime-sync.js +190 -12
  56. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  57. package/dist/heart/daemon/daemon.js +677 -58
  58. package/dist/heart/daemon/dns-workflow.js +394 -0
  59. package/dist/heart/daemon/doctor-types.js +8 -0
  60. package/dist/heart/daemon/doctor.js +486 -0
  61. package/dist/heart/daemon/health-monitor.js +92 -1
  62. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  63. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  64. package/dist/heart/daemon/http-health-probe.js +80 -0
  65. package/dist/heart/daemon/human-command-screens.js +234 -0
  66. package/dist/heart/daemon/human-readiness.js +114 -0
  67. package/dist/heart/daemon/inner-status.js +89 -0
  68. package/dist/heart/daemon/interactive-repair.js +394 -0
  69. package/dist/heart/daemon/launchd.js +25 -5
  70. package/dist/heart/daemon/log-tailer.js +82 -12
  71. package/dist/heart/daemon/logs-prune.js +110 -0
  72. package/dist/heart/daemon/message-router.js +2 -2
  73. package/dist/heart/daemon/os-cron-deps.js +134 -0
  74. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  75. package/dist/heart/daemon/ouro-entry.js +3 -1
  76. package/dist/heart/daemon/process-manager.js +214 -0
  77. package/dist/heart/daemon/provider-discovery.js +137 -0
  78. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  79. package/dist/heart/daemon/pulse.js +475 -0
  80. package/dist/heart/daemon/readiness-repair.js +365 -0
  81. package/dist/heart/daemon/run-hooks.js +2 -0
  82. package/dist/heart/daemon/runtime-logging.js +67 -16
  83. package/dist/heart/daemon/runtime-metadata.js +73 -0
  84. package/dist/heart/daemon/runtime-mode.js +67 -0
  85. package/dist/heart/daemon/safe-mode.js +161 -0
  86. package/dist/heart/daemon/sense-manager.js +178 -37
  87. package/dist/heart/daemon/session-id-resolver.js +131 -0
  88. package/dist/heart/daemon/skill-management-installer.js +94 -0
  89. package/dist/heart/daemon/socket-client.js +109 -4
  90. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  91. package/dist/heart/daemon/startup-tui.js +264 -0
  92. package/dist/heart/daemon/task-scheduler.js +3 -25
  93. package/dist/heart/daemon/terminal-ui.js +499 -0
  94. package/dist/heart/daemon/thoughts.js +149 -10
  95. package/dist/heart/daemon/up-progress.js +366 -0
  96. package/dist/heart/daemon/vault-items.js +56 -0
  97. package/dist/heart/delegation.js +62 -0
  98. package/dist/heart/habits/habit-migration.js +189 -0
  99. package/dist/heart/habits/habit-parser.js +140 -0
  100. package/dist/heart/habits/habit-runtime-state.js +100 -0
  101. package/dist/heart/habits/habit-scheduler.js +372 -0
  102. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  103. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  104. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  105. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  106. package/dist/heart/identity.js +201 -66
  107. package/dist/heart/kept-notes.js +357 -0
  108. package/dist/heart/kicks.js +1 -1
  109. package/dist/heart/machine-identity.js +161 -0
  110. package/dist/heart/mcp/mcp-server.js +653 -0
  111. package/dist/heart/migrate-config.js +100 -0
  112. package/dist/heart/model-capabilities.js +59 -0
  113. package/dist/heart/outlook/outlook-http-hooks.js +66 -0
  114. package/dist/heart/outlook/outlook-http-response.js +7 -0
  115. package/dist/heart/outlook/outlook-http-routes.js +244 -0
  116. package/dist/heart/outlook/outlook-http-static.js +99 -0
  117. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  118. package/dist/heart/outlook/outlook-http.js +99 -0
  119. package/dist/heart/outlook/outlook-read.js +31 -0
  120. package/dist/heart/outlook/outlook-types.js +27 -0
  121. package/dist/heart/outlook/outlook-view.js +195 -0
  122. package/dist/heart/outlook/readers/agent-machine.js +359 -0
  123. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  124. package/dist/heart/outlook/readers/mail.js +362 -0
  125. package/dist/heart/outlook/readers/runtime-readers.js +644 -0
  126. package/dist/heart/outlook/readers/sessions.js +232 -0
  127. package/dist/heart/outlook/readers/shared.js +111 -0
  128. package/dist/heart/platform.js +81 -0
  129. package/dist/heart/progress-story.js +42 -0
  130. package/dist/heart/provider-attempt.js +134 -0
  131. package/dist/heart/provider-binding-resolver.js +255 -0
  132. package/dist/heart/provider-credentials.js +424 -0
  133. package/dist/heart/provider-failover.js +266 -0
  134. package/dist/heart/provider-models.js +81 -0
  135. package/dist/heart/provider-ping.js +262 -0
  136. package/dist/heart/provider-state.js +216 -0
  137. package/dist/heart/provider-visibility.js +188 -0
  138. package/dist/heart/providers/anthropic-token.js +131 -0
  139. package/dist/heart/providers/anthropic.js +193 -55
  140. package/dist/heart/providers/azure.js +103 -12
  141. package/dist/heart/providers/error-classification.js +63 -0
  142. package/dist/heart/providers/github-copilot.js +145 -0
  143. package/dist/heart/providers/minimax-vlm.js +189 -0
  144. package/dist/heart/providers/minimax.js +29 -7
  145. package/dist/heart/providers/openai-codex.js +62 -38
  146. package/dist/heart/runtime-capability-check.js +170 -0
  147. package/dist/heart/runtime-credentials.js +260 -0
  148. package/dist/heart/sense-truth.js +11 -4
  149. package/dist/heart/session-activity.js +190 -0
  150. package/dist/heart/session-events.js +855 -0
  151. package/dist/heart/session-transcript.js +167 -0
  152. package/dist/heart/start-of-turn-packet.js +345 -0
  153. package/dist/heart/streaming.js +36 -27
  154. package/dist/heart/sync.js +332 -0
  155. package/dist/heart/target-resolution.js +127 -0
  156. package/dist/heart/tempo.js +93 -0
  157. package/dist/heart/temporal-view.js +41 -0
  158. package/dist/heart/tool-activity-callbacks.js +36 -0
  159. package/dist/heart/tool-description.js +135 -0
  160. package/dist/heart/tool-friction.js +55 -0
  161. package/dist/heart/tool-loop.js +200 -0
  162. package/dist/heart/turn-context.js +361 -0
  163. package/dist/heart/turn-coordinator.js +24 -1
  164. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  165. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  166. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  167. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  168. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  169. package/dist/heart/{daemon → versioning}/update-checker.js +5 -1
  170. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  171. package/dist/mailroom/attention.js +167 -0
  172. package/dist/mailroom/autonomy.js +209 -0
  173. package/dist/mailroom/blob-store.js +573 -0
  174. package/dist/mailroom/core.js +658 -0
  175. package/dist/mailroom/entry.js +160 -0
  176. package/dist/mailroom/file-store.js +400 -0
  177. package/dist/mailroom/mbox-import.js +341 -0
  178. package/dist/mailroom/outbound.js +380 -0
  179. package/dist/mailroom/policy.js +263 -0
  180. package/dist/mailroom/reader.js +197 -0
  181. package/dist/mailroom/smtp-ingress.js +176 -0
  182. package/dist/mailroom/source-state.js +176 -0
  183. package/dist/mailroom/travel-extract.js +89 -0
  184. package/dist/mind/bundle-manifest.js +7 -1
  185. package/dist/mind/context.js +132 -93
  186. package/dist/mind/diary-integrity.js +60 -0
  187. package/dist/mind/{memory.js → diary.js} +74 -93
  188. package/dist/mind/embedding-provider.js +60 -0
  189. package/dist/mind/file-state.js +179 -0
  190. package/dist/mind/friends/channel.js +30 -0
  191. package/dist/mind/friends/group-context.js +144 -0
  192. package/dist/mind/friends/resolver.js +38 -1
  193. package/dist/mind/friends/store-file.js +39 -3
  194. package/dist/mind/friends/trust-explanation.js +74 -0
  195. package/dist/mind/friends/types.js +2 -2
  196. package/dist/mind/journal-index.js +161 -0
  197. package/dist/mind/note-search.js +268 -0
  198. package/dist/mind/obligation-steering.js +221 -0
  199. package/dist/mind/pending.js +66 -7
  200. package/dist/mind/prompt-refresh.js +3 -2
  201. package/dist/mind/prompt.js +978 -169
  202. package/dist/mind/provenance-trust.js +26 -0
  203. package/dist/mind/scrutiny.js +173 -0
  204. package/dist/nerves/cli-logging.js +7 -1
  205. package/dist/nerves/coverage/audit-rules.js +15 -6
  206. package/dist/nerves/coverage/audit.js +28 -2
  207. package/dist/nerves/coverage/cli.js +1 -1
  208. package/dist/nerves/coverage/contract.js +5 -5
  209. package/dist/nerves/coverage/file-completeness.js +84 -5
  210. package/dist/nerves/coverage/run-artifacts.js +1 -1
  211. package/dist/nerves/event-buffer.js +111 -0
  212. package/dist/nerves/index.js +224 -4
  213. package/dist/nerves/observation.js +20 -0
  214. package/dist/nerves/redact.js +79 -0
  215. package/dist/nerves/runtime.js +5 -1
  216. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  217. package/dist/outlook-ui/assets/index-CPfhbn13.js +61 -0
  218. package/dist/outlook-ui/index.html +15 -0
  219. package/dist/repertoire/ado-client.js +15 -56
  220. package/dist/repertoire/ado-semantic.js +11 -10
  221. package/dist/repertoire/api-client.js +97 -0
  222. package/dist/repertoire/bitwarden-store.js +774 -0
  223. package/dist/repertoire/bundle-templates.js +72 -0
  224. package/dist/repertoire/bw-installer.js +180 -0
  225. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  226. package/dist/repertoire/coding/context-pack.js +330 -0
  227. package/dist/repertoire/coding/feedback.js +197 -30
  228. package/dist/repertoire/coding/manager.js +158 -9
  229. package/dist/repertoire/coding/spawner.js +55 -9
  230. package/dist/repertoire/coding/tools.js +170 -7
  231. package/dist/repertoire/commerce-errors.js +109 -0
  232. package/dist/repertoire/commerce-self-test.js +156 -0
  233. package/dist/repertoire/credential-access.js +111 -0
  234. package/dist/repertoire/duffel-client.js +185 -0
  235. package/dist/repertoire/github-client.js +14 -55
  236. package/dist/repertoire/graph-client.js +11 -52
  237. package/dist/repertoire/guardrails.js +396 -0
  238. package/dist/repertoire/mcp-client.js +255 -0
  239. package/dist/repertoire/mcp-manager.js +305 -0
  240. package/dist/repertoire/mcp-tools.js +63 -0
  241. package/dist/repertoire/shell-sessions.js +133 -0
  242. package/dist/repertoire/skills.js +15 -24
  243. package/dist/repertoire/stripe-client.js +131 -0
  244. package/dist/repertoire/tasks/board.js +43 -5
  245. package/dist/repertoire/tasks/fix.js +182 -0
  246. package/dist/repertoire/tasks/index.js +37 -4
  247. package/dist/repertoire/tasks/lifecycle.js +2 -2
  248. package/dist/repertoire/tasks/parser.js +3 -2
  249. package/dist/repertoire/tasks/scanner.js +194 -37
  250. package/dist/repertoire/tasks/transitions.js +16 -78
  251. package/dist/repertoire/tool-results.js +29 -0
  252. package/dist/repertoire/tools-attachments.js +317 -0
  253. package/dist/repertoire/tools-base.js +44 -740
  254. package/dist/repertoire/tools-bluebubbles.js +1 -0
  255. package/dist/repertoire/tools-bridge.js +141 -0
  256. package/dist/repertoire/tools-bundle.js +984 -0
  257. package/dist/repertoire/tools-config.js +185 -0
  258. package/dist/repertoire/tools-continuity.js +248 -0
  259. package/dist/repertoire/tools-credential.js +381 -0
  260. package/dist/repertoire/tools-files.js +342 -0
  261. package/dist/repertoire/tools-flight.js +224 -0
  262. package/dist/repertoire/tools-flow.js +105 -0
  263. package/dist/repertoire/tools-github.js +1 -7
  264. package/dist/repertoire/tools-mail.js +896 -0
  265. package/dist/repertoire/tools-notes.js +376 -0
  266. package/dist/repertoire/tools-session.js +746 -0
  267. package/dist/repertoire/tools-shell.js +120 -0
  268. package/dist/repertoire/tools-stripe.js +180 -0
  269. package/dist/repertoire/tools-surface.js +243 -0
  270. package/dist/repertoire/tools-teams.js +9 -39
  271. package/dist/repertoire/tools-travel.js +125 -0
  272. package/dist/repertoire/tools-user-profile.js +144 -0
  273. package/dist/repertoire/tools-vault.js +40 -0
  274. package/dist/repertoire/tools.js +144 -113
  275. package/dist/repertoire/travel-api-client.js +360 -0
  276. package/dist/repertoire/user-profile.js +131 -0
  277. package/dist/repertoire/vault-setup.js +246 -0
  278. package/dist/repertoire/vault-unlock.js +561 -0
  279. package/dist/scripts/claude-code-hook.js +41 -0
  280. package/dist/scripts/claude-code-stop-hook.js +47 -0
  281. package/dist/senses/attention-queue.js +116 -0
  282. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  283. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  284. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  285. package/dist/senses/bluebubbles/entry.js +73 -0
  286. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +7 -3
  287. package/dist/senses/{bluebubbles.js → bluebubbles/index.js} +705 -116
  288. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  289. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  290. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  291. package/dist/senses/bluebubbles/replay.js +129 -0
  292. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
  293. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  294. package/dist/senses/cli/bracketed-paste.js +82 -0
  295. package/dist/senses/cli/image-paste.js +287 -0
  296. package/dist/senses/cli/image-ref-navigation.js +75 -0
  297. package/dist/senses/cli/ink-app.js +156 -0
  298. package/dist/senses/cli/inline-diff.js +64 -0
  299. package/dist/senses/cli/input-keys.js +174 -0
  300. package/dist/senses/cli/kill-ring.js +86 -0
  301. package/dist/senses/cli/message-list.js +51 -0
  302. package/dist/senses/cli/ouro-tui.js +605 -0
  303. package/dist/senses/cli/spinner-imperative.js +135 -0
  304. package/dist/senses/cli/spinner.js +101 -0
  305. package/dist/senses/cli/status-line.js +60 -0
  306. package/dist/senses/cli/streaming-markdown.js +526 -0
  307. package/dist/senses/cli/tool-display.js +83 -0
  308. package/dist/senses/cli/tool-render.js +85 -0
  309. package/dist/senses/cli/tui-store.js +240 -0
  310. package/dist/senses/cli/virtual-list.js +35 -0
  311. package/dist/senses/cli-entry.js +60 -8
  312. package/dist/senses/cli-layout.js +187 -0
  313. package/dist/senses/cli.js +516 -211
  314. package/dist/senses/commands.js +66 -3
  315. package/dist/senses/habit-turn-message.js +108 -0
  316. package/dist/senses/inner-dialog-worker.js +97 -17
  317. package/dist/senses/inner-dialog.js +404 -14
  318. package/dist/senses/mail-entry.js +66 -0
  319. package/dist/senses/mail.js +232 -0
  320. package/dist/senses/pipeline.js +533 -72
  321. package/dist/senses/proactive-content-guard.js +51 -0
  322. package/dist/senses/shared-turn.js +205 -0
  323. package/dist/senses/surface-tool.js +68 -0
  324. package/dist/senses/teams-entry.js +60 -8
  325. package/dist/senses/teams.js +413 -163
  326. package/dist/senses/trust-gate.js +5 -5
  327. package/package.json +37 -7
  328. package/skills/agent-commerce.md +106 -0
  329. package/skills/browser-navigation.md +117 -0
  330. package/skills/commerce-setup-guide.md +116 -0
  331. package/skills/commerce-setup.md +84 -0
  332. package/skills/configure-dev-tools.md +101 -0
  333. package/skills/travel-planning.md +138 -0
  334. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  335. package/dist/heart/daemon/subagent-installer.js +0 -166
  336. package/dist/mind/associative-recall.js +0 -209
  337. package/dist/senses/bluebubbles-entry.js +0 -13
  338. package/dist/senses/debug-activity.js +0 -127
  339. package/subagents/README.md +0 -86
  340. package/subagents/work-doer.md +0 -237
  341. package/subagents/work-merger.md +0 -618
  342. package/subagents/work-planner.md +0 -390
  343. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  344. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  345. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  346. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  347. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  348. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  349. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  350. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  351. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  352. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  353. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  354. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  355. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  356. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  357. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  358. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -4,12 +4,257 @@
4
4
  // resolve friend -> trust gate -> load session -> drain pending -> runAgent -> postTurn -> token accumulation.
5
5
  //
6
6
  // Transport-level concerns (BB API calls, Teams cards, readline) stay in sense adapters.
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
7
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.emitObligationTransitionEpisodes = emitObligationTransitionEpisodes;
8
42
  exports.handleInboundTurn = handleInboundTurn;
43
+ const fs = __importStar(require("fs"));
44
+ const path = __importStar(require("path"));
9
45
  const runtime_1 = require("../nerves/runtime");
46
+ const commands_1 = require("./commands");
10
47
  const continuity_1 = require("./continuity");
48
+ const manager_1 = require("../heart/bridges/manager");
49
+ const identity_1 = require("../heart/identity");
50
+ const socket_client_1 = require("../heart/daemon/socket-client");
51
+ const active_work_1 = require("../heart/active-work");
52
+ const delegation_1 = require("../heart/delegation");
53
+ const obligations_1 = require("../arc/obligations");
54
+ const provider_failover_1 = require("../heart/provider-failover");
55
+ const provider_state_1 = require("../heart/provider-state");
56
+ const tempo_1 = require("../heart/tempo");
57
+ const temporal_view_1 = require("../heart/temporal-view");
58
+ const start_of_turn_packet_1 = require("../heart/start-of-turn-packet");
59
+ const bundle_state_1 = require("../heart/bundle-state");
60
+ const sync_1 = require("../heart/sync");
61
+ const config_1 = require("../heart/config");
62
+ const session_events_1 = require("../heart/session-events");
63
+ const presence_1 = require("../arc/presence");
64
+ const episodes_1 = require("../arc/episodes");
65
+ const turn_context_1 = require("../heart/turn-context");
66
+ const provider_visibility_1 = require("../heart/provider-visibility");
67
+ /**
68
+ * Emit episodes for obligation state transitions detected during a turn.
69
+ * Exported for direct testability (avoids v8 coverage merge issues in multi-file test suites).
70
+ */
71
+ function emitObligationTransitionEpisodes(agentRoot, preTurnObligationIds, postTurnObligations, preTurnObligations) {
72
+ const postTurnObligationIds = new Set(postTurnObligations.map((ob) => `${ob.id}:${ob.status}`));
73
+ for (const key of preTurnObligationIds) {
74
+ if (!postTurnObligationIds.has(key)) {
75
+ const [obId] = key.split(":");
76
+ const matchedOb = postTurnObligations.find((ob) => ob.id === obId) ?? preTurnObligations.find((ob) => ob.id === obId);
77
+ (0, episodes_1.emitEpisode)(agentRoot, {
78
+ kind: "obligation_shift",
79
+ summary: `obligation "${matchedOb?.content ?? obId}" status changed`,
80
+ whyItMattered: "obligation state transition detected during turn",
81
+ relatedEntities: [`obligation:${obId}`],
82
+ salience: "medium",
83
+ });
84
+ }
85
+ }
86
+ }
87
+ function providerLaneForChannel(channel) {
88
+ return channel === "inner" ? "inner" : "outward";
89
+ }
90
+ function resolveCurrentFailoverBinding(agentName, lane) {
91
+ const stateResult = (0, provider_state_1.readProviderState)((0, identity_1.getAgentRoot)(agentName));
92
+ if (stateResult.ok) {
93
+ const binding = stateResult.state.lanes[lane];
94
+ return { provider: binding.provider, model: binding.model };
95
+ }
96
+ const agentConfig = (0, identity_1.loadAgentConfig)();
97
+ const fallback = lane === "inner" ? agentConfig.agentFacing : agentConfig.humanFacing;
98
+ return { provider: fallback.provider, model: fallback.model };
99
+ }
100
+ function writeFailoverProviderStateSwitch(agentName, action) {
101
+ const agentRoot = (0, identity_1.getAgentRoot)(agentName);
102
+ const stateResult = (0, provider_state_1.readProviderState)(agentRoot);
103
+ if (!stateResult.ok) {
104
+ throw new Error(`Cannot switch ${action.lane} lane for ${agentName}: ${stateResult.error}`);
105
+ }
106
+ const updatedAt = new Date().toISOString();
107
+ const lanes = { ...stateResult.state.lanes };
108
+ lanes[action.lane] = {
109
+ provider: action.provider,
110
+ model: action.model,
111
+ source: "local",
112
+ updatedAt,
113
+ };
114
+ const readiness = { ...stateResult.state.readiness };
115
+ readiness[action.lane] = {
116
+ status: "ready",
117
+ provider: action.provider,
118
+ model: action.model,
119
+ checkedAt: updatedAt,
120
+ ...(action.credentialRevision ? { credentialRevision: action.credentialRevision } : {}),
121
+ };
122
+ (0, provider_state_1.writeProviderState)(agentRoot, {
123
+ ...stateResult.state,
124
+ updatedAt,
125
+ lanes,
126
+ readiness,
127
+ });
128
+ }
129
+ function formatFailoverSwitchLabel(action) {
130
+ const provenance = (0, provider_failover_1.formatCredentialProvenanceLabel)(action);
131
+ return `${action.provider} (${action.model}${provenance ? `; ${provenance}` : ""})`;
132
+ }
133
+ function prependTurnSections(message, sections) {
134
+ /* v8 ignore next -- defensive: only user messages with non-empty sections reach here @preserve */
135
+ if (message.role !== "user" || sections.length === 0)
136
+ return message;
137
+ const prefix = sections.join("\n\n");
138
+ /* v8 ignore start -- defensive: multipart content branch; non-string user messages are rare @preserve */
139
+ if (typeof message.content === "string") {
140
+ return {
141
+ ...message,
142
+ content: `${prefix}\n\n${message.content}`,
143
+ };
144
+ }
145
+ return {
146
+ ...message,
147
+ content: [
148
+ { type: "text", text: `${prefix}\n\n` },
149
+ ...message.content,
150
+ ],
151
+ };
152
+ /* v8 ignore stop */
153
+ }
11
154
  // ── Pipeline ──────────────────────────────────────────────────────
155
+ let _lastSessionKey = null;
12
156
  async function handleInboundTurn(input) {
157
+ // Reset session-scoped state when the session changes
158
+ const sessionKey = `${input.channel}/${input.sessionKey ?? "session"}`;
159
+ if (sessionKey !== _lastSessionKey) {
160
+ _lastSessionKey = sessionKey;
161
+ // Reset file-state cache and scrutiny tracking for the new session
162
+ const { fileStateCache } = await Promise.resolve().then(() => __importStar(require("../mind/file-state")));
163
+ const { resetSessionModifiedFiles } = await Promise.resolve().then(() => __importStar(require("../mind/scrutiny")));
164
+ fileStateCache.clear();
165
+ resetSessionModifiedFiles();
166
+ }
167
+ // Step 0: Check for pending failover reply
168
+ if (input.failoverState?.pending) {
169
+ const userText = input.messages
170
+ .filter((m) => m.role === "user")
171
+ .map((m) => typeof m.content === "string" ? m.content : /* v8 ignore next -- defensive: multipart content fallback @preserve */ "")
172
+ .join(" ")
173
+ .trim();
174
+ const pendingContext = input.failoverState.pending;
175
+ const failoverAction = (0, provider_failover_1.handleFailoverReply)(userText, pendingContext);
176
+ const failoverAgentName = pendingContext.agentName;
177
+ input.failoverState.pending = null; // always clear before acting
178
+ if (failoverAction.action === "switch") {
179
+ let switchSucceeded = false;
180
+ try {
181
+ writeFailoverProviderStateSwitch(failoverAgentName, failoverAction);
182
+ switchSucceeded = true;
183
+ /* v8 ignore start -- defensive: write failure during provider switch @preserve */
184
+ }
185
+ catch (switchError) {
186
+ (0, runtime_1.emitNervesEvent)({
187
+ level: "error",
188
+ component: "senses",
189
+ event: "senses.failover_switch_error",
190
+ message: `failed to switch ${failoverAction.lane} provider lane to ${failoverAction.provider}`,
191
+ meta: { agentName: failoverAgentName, lane: failoverAction.lane, provider: failoverAction.provider, model: failoverAction.model, error: switchError instanceof Error ? switchError.message : String(switchError) },
192
+ });
193
+ }
194
+ /* v8 ignore stop */
195
+ /* v8 ignore next -- false branch: write-failure fallthrough @preserve */
196
+ if (switchSucceeded) {
197
+ (0, runtime_1.emitNervesEvent)({
198
+ component: "senses",
199
+ event: "senses.failover_switch",
200
+ message: `switched ${failoverAction.lane} provider lane to ${failoverAction.provider} via failover`,
201
+ meta: {
202
+ agentName: failoverAgentName,
203
+ lane: failoverAction.lane,
204
+ provider: failoverAction.provider,
205
+ model: failoverAction.model,
206
+ credentialRevision: failoverAction.credentialRevision,
207
+ source: failoverAction.source,
208
+ },
209
+ });
210
+ // Replace "switch to <provider>" with a context message for the agent.
211
+ // The session already has the user's original question from the failed turn.
212
+ // The agent needs to know what happened so it can respond appropriately.
213
+ const newProviderLabel = formatFailoverSwitchLabel(failoverAction);
214
+ input.messages = [{
215
+ role: "user",
216
+ content: `[provider switch: ${pendingContext.errorSummary}. switched ${failoverAction.lane} lane to ${newProviderLabel}. your conversation history is intact — respond to the user's last message.]`,
217
+ }];
218
+ input.switchedProvider = failoverAction.provider;
219
+ }
220
+ // Switch failed OR succeeded — either way, fall through to normal processing.
221
+ }
222
+ }
223
+ // Step 0b: Slash command interception (before friend resolution / agent turn)
224
+ {
225
+ const firstUserMsg = input.messages.find((m) => m.role === "user");
226
+ const userText = firstUserMsg
227
+ ? (typeof firstUserMsg.content === "string"
228
+ ? firstUserMsg.content
229
+ : Array.isArray(firstUserMsg.content)
230
+ ? firstUserMsg.content.find((p) => p.type === "text")?.text ?? ""
231
+ : /* v8 ignore next -- defensive: content is always string or array @preserve */ "")
232
+ : "";
233
+ const parsed = (0, commands_1.parseSlashCommand)(userText);
234
+ if (parsed) {
235
+ const registry = (0, commands_1.getSharedCommandRegistry)();
236
+ const dispatchResult = registry.dispatch(parsed.command, { channel: input.channel });
237
+ if (dispatchResult.handled && dispatchResult.result) {
238
+ (0, runtime_1.emitNervesEvent)({
239
+ component: "senses",
240
+ event: "senses.pipeline_command",
241
+ message: `slash command intercepted: /${parsed.command}`,
242
+ meta: { command: parsed.command, channel: input.channel },
243
+ });
244
+ if (dispatchResult.result.message) {
245
+ input.callbacks.onTextChunk(dispatchResult.result.message);
246
+ }
247
+ // Return a minimal result — no agent turn, no session write
248
+ const resolvedContext = await input.friendResolver.resolve();
249
+ return {
250
+ resolvedContext,
251
+ gateResult: { allowed: true },
252
+ turnOutcome: "command",
253
+ commandAction: dispatchResult.result.action,
254
+ };
255
+ }
256
+ }
257
+ }
13
258
  // Step 1: Resolve friend
14
259
  const resolvedContext = await input.friendResolver.resolve();
15
260
  (0, runtime_1.emitNervesEvent)({
@@ -55,87 +300,303 @@ async function handleInboundTurn(input) {
55
300
  // Step 3: Load/create session
56
301
  const session = await input.sessionLoader.loadOrCreate();
57
302
  const sessionMessages = session.messages;
303
+ const sessionEvents = session.events ?? [];
58
304
  let mustResolveBeforeHandoff = (0, continuity_1.resolveMustResolveBeforeHandoff)(session.state?.mustResolveBeforeHandoff === true, input.continuityIngressTexts);
305
+ const lastFriendActivityAt = input.channel === "inner"
306
+ ? session.state?.lastFriendActivityAt
307
+ : new Date().toISOString();
59
308
  const currentObligation = input.continuityIngressTexts
60
309
  ?.map((text) => text.trim())
61
310
  .filter((text) => text.length > 0)
62
311
  .at(-1);
63
- // Step 4: Drain pending messages
64
- const pending = input.drainPending(input.pendingDir);
65
- // Assemble messages: session messages + pending (formatted) + inbound user messages
66
- if (pending.length > 0) {
67
- // Format pending messages and prepend to the user content
68
- const pendingSection = pending
69
- .map((msg) => `[pending from ${msg.from}]: ${msg.content}`)
70
- .join("\n");
71
- // If there are inbound user messages, prepend pending to the first one
72
- if (input.messages.length > 0) {
73
- const firstMsg = input.messages[0];
74
- if (firstMsg.role === "user") {
75
- if (typeof firstMsg.content === "string") {
76
- input.messages[0] = {
77
- ...firstMsg,
78
- content: `## pending messages\n${pendingSection}\n\n${firstMsg.content}`,
79
- };
312
+ const currentSession = {
313
+ friendId: resolvedContext.friend.id,
314
+ channel: input.channel,
315
+ key: input.sessionKey ?? "session",
316
+ sessionPath: session.sessionPath,
317
+ };
318
+ const currentSessionTiming = (0, session_events_1.describeCurrentSessionTiming)(sessionEvents);
319
+ // Step 3b: Pre-turn sync pull (opt-in) — MUST happen before any continuity state reads
320
+ // so that obligations, episodes, cares, etc. reflect the latest remote state.
321
+ let syncFailure;
322
+ let syncConfig = { enabled: false, remote: "origin" };
323
+ try {
324
+ syncConfig = (0, config_1.getSyncConfig)();
325
+ }
326
+ catch { /* config not available */ }
327
+ // Wrap the turn body in try/finally so postTurnPush always runs — even on
328
+ // error or early-return failover paths.
329
+ try {
330
+ /* v8 ignore start -- sync-enabled branches tested in sync.test.ts, pipeline tests mock at module boundary @preserve */
331
+ if (syncConfig.enabled) {
332
+ const pullResult = (0, sync_1.preTurnPull)((0, identity_1.getAgentRoot)(), syncConfig);
333
+ if (!pullResult.ok) {
334
+ syncFailure = pullResult.error;
335
+ }
336
+ // Check for pending-sync from a prior failed push
337
+ if (!syncFailure) {
338
+ const pendingSyncPath = path.join((0, identity_1.getAgentRoot)(), "state", "pending-sync.json");
339
+ try {
340
+ if (fs.existsSync(pendingSyncPath)) {
341
+ const pendingSync = JSON.parse(fs.readFileSync(pendingSyncPath, "utf-8"));
342
+ syncFailure = `prior sync push failed: ${pendingSync.error ?? "unknown"}`;
343
+ fs.unlinkSync(pendingSyncPath);
344
+ }
80
345
  }
81
- else {
82
- input.messages[0] = {
83
- ...firstMsg,
84
- content: [
85
- { type: "text", text: `## pending messages\n${pendingSection}\n\n` },
86
- ...firstMsg.content,
87
- ],
88
- };
346
+ catch {
347
+ // Ignore read errors for pending-sync
89
348
  }
90
349
  }
91
350
  }
92
- }
93
- // Append user messages from the inbound turn
94
- for (const msg of input.messages) {
95
- sessionMessages.push(msg);
96
- }
97
- // Step 5: runAgent
98
- const existingToolContext = input.runAgentOptions?.toolContext;
99
- const runAgentOptions = {
100
- ...input.runAgentOptions,
101
- currentObligation,
102
- mustResolveBeforeHandoff,
103
- setMustResolveBeforeHandoff: (value) => {
104
- mustResolveBeforeHandoff = value;
105
- },
106
- toolContext: {
107
- /* v8 ignore next -- default no-op signin satisfies interface; real signin injected by sense adapter @preserve */
108
- signin: async () => undefined,
109
- ...existingToolContext,
110
- context: resolvedContext,
351
+ /* v8 ignore stop */
352
+ // Build the turn context snapshot centralizes all state reads
353
+ const ctx = await (0, turn_context_1.buildTurnContext)({
354
+ currentSession,
355
+ channel: input.channel,
111
356
  friendStore: input.friendStore,
112
- },
113
- };
114
- const result = await input.runAgent(sessionMessages, input.callbacks, input.channel, input.signal, runAgentOptions);
115
- // Step 6: postTurn
116
- const nextState = result.outcome === "complete" || result.outcome === "blocked" || result.outcome === "superseded"
117
- ? undefined
118
- : mustResolveBeforeHandoff
119
- ? { mustResolveBeforeHandoff: true }
120
- : undefined;
121
- input.postTurn(sessionMessages, session.sessionPath, result.usage, undefined, nextState);
122
- // Step 7: Token accumulation
123
- await input.accumulateFriendTokens(input.friendStore, resolvedContext.friend.id, result.usage);
124
- (0, runtime_1.emitNervesEvent)({
125
- component: "senses",
126
- event: "senses.pipeline_end",
127
- message: "inbound turn pipeline completed",
128
- meta: {
357
+ });
358
+ // Propagate sync failure from pre-turn pull
359
+ ctx.syncFailure = syncFailure;
360
+ const { activeBridges, sessionActivity, pendingObligations, codingSessions, otherCodingSessions } = ctx;
361
+ const bridgeContext = (0, manager_1.formatBridgeContext)(activeBridges) || undefined;
362
+ const activeWorkFrame = (0, active_work_1.buildActiveWorkFrame)({
363
+ currentSession,
364
+ currentObligation,
365
+ mustResolveBeforeHandoff,
366
+ inner: ctx.innerWorkState,
367
+ bridges: activeBridges,
368
+ codingSessions,
369
+ otherCodingSessions,
370
+ pendingObligations,
371
+ taskBoard: ctx.taskBoard,
372
+ friendActivity: sessionActivity,
373
+ targetCandidates: ctx.targetCandidates,
374
+ innerReturnObligations: ctx.returnObligations,
375
+ });
376
+ const delegationDecision = (0, delegation_1.decideDelegation)({
129
377
  channel: input.channel,
130
- friendId: resolvedContext.friend.id,
131
- },
132
- });
133
- return {
134
- resolvedContext,
135
- gateResult,
136
- usage: result.usage,
137
- turnOutcome: result.outcome,
138
- sessionPath: session.sessionPath,
139
- messages: sessionMessages,
140
- };
378
+ ingressTexts: input.continuityIngressTexts ?? [],
379
+ activeWork: activeWorkFrame,
380
+ mustResolveBeforeHandoff,
381
+ });
382
+ // Step 4: Drain deferred friend returns, then ordinary per-session pending.
383
+ const deferredReturns = input.channel === "inner"
384
+ ? []
385
+ : (input.drainDeferredReturns?.(resolvedContext.friend.id) ?? []);
386
+ const sessionPending = input.drainPending(input.pendingDir);
387
+ const pending = [...deferredReturns, ...sessionPending];
388
+ // Assemble messages: session messages + pending + inbound user messages
389
+ // NOTE: live world-state checkpoint and pending messages are rendered via buildSystem (system prompt sections)
390
+ const extraPrefixSections = input.onPendingDrained?.(pending) ?? [];
391
+ // extraPrefixSections from onPendingDrained still prepend to user message (e.g., inner dialog wakes)
392
+ if (extraPrefixSections.length > 0 && input.messages.length > 0) {
393
+ input.messages[0] = prependTurnSections(input.messages[0], extraPrefixSections);
394
+ }
395
+ // Append user messages from the inbound turn
396
+ for (const msg of input.messages) {
397
+ (0, session_events_1.stampIngressTime)(msg);
398
+ sessionMessages.push(msg);
399
+ }
400
+ // Step 4b: Continuity pipeline — derive tempo, build start-of-turn packet, snapshot obligations
401
+ let renderedStartOfTurnPacket;
402
+ const preTurnObligationIds = new Set(pendingObligations.map((ob) => `${ob.id}:${ob.status}`));
403
+ try {
404
+ const agentRoot = (0, identity_1.getAgentRoot)();
405
+ const agentName = (0, identity_1.getAgentName)();
406
+ const { recentEpisodes, activeCares } = ctx;
407
+ const tempoState = (0, tempo_1.deriveTempo)({
408
+ activeSessions: sessionActivity.length + 1,
409
+ openObligations: pendingObligations.length,
410
+ recentEpisodeCount: recentEpisodes.length,
411
+ lastActivityAgeMs: sessionActivity.length > 0
412
+ ? Date.now() - new Date(sessionActivity[0].lastActivityAt).getTime()
413
+ : 0,
414
+ hasBlockers: false, // obligations use specific statuses, not "blocked"
415
+ highSalienceEpisodes: recentEpisodes.filter((ep) => ep.salience === "high" || ep.salience === "critical").length,
416
+ activeCareCount: activeCares.length,
417
+ atRiskCareCount: activeCares.filter((c) => c.currentRisk != null).length,
418
+ });
419
+ const temporalView = (0, temporal_view_1.buildTemporalView)(agentRoot, {
420
+ tempo: tempoState.mode,
421
+ preloaded: {
422
+ recentEpisodes,
423
+ activeObligations: pendingObligations,
424
+ activeCares,
425
+ },
426
+ });
427
+ const startOfTurnPacket = (0, start_of_turn_packet_1.buildStartOfTurnPacket)(temporalView, {
428
+ canonicalObligations: {
429
+ primary: activeWorkFrame.primaryObligation,
430
+ all: activeWorkFrame.pendingObligations,
431
+ },
432
+ currentSessionTiming,
433
+ });
434
+ /* v8 ignore next 3 -- syncFailure propagation tested in sync.test.ts @preserve */
435
+ if (syncFailure) {
436
+ startOfTurnPacket.syncFailure = syncFailure;
437
+ }
438
+ if (ctx.providerVisibility) {
439
+ startOfTurnPacket.providerState = (0, provider_visibility_1.formatAgentProviderVisibilityForStartOfTurn)(ctx.providerVisibility);
440
+ }
441
+ // Structured bundle state detection — surfaces discrete issues the
442
+ // agent can remediate via the bundle_* tools. Runs independently of
443
+ // syncFailure so the two signals coexist during the transition away
444
+ // from the legacy free-form syncFailure string. Always assigned; the
445
+ // packet renderer's empty-filter handles the empty-array case without
446
+ // a separate branch here.
447
+ startOfTurnPacket.bundleState = (0, bundle_state_1.detectBundleState)(agentRoot);
448
+ const capabilities = (0, start_of_turn_packet_1.buildCapabilitiesSection)(agentRoot);
449
+ if (capabilities) {
450
+ startOfTurnPacket.capabilities = capabilities;
451
+ }
452
+ renderedStartOfTurnPacket = (0, start_of_turn_packet_1.renderStartOfTurnPacket)(startOfTurnPacket);
453
+ if (!renderedStartOfTurnPacket)
454
+ renderedStartOfTurnPacket = undefined;
455
+ // Update self-presence
456
+ const presence = (0, presence_1.derivePresence)(agentRoot, agentName, {
457
+ activeSessions: sessionActivity.length + 1,
458
+ openObligations: pendingObligations.length,
459
+ activeBridges: activeBridges.length,
460
+ codingLanes: codingSessions.length,
461
+ currentTempo: tempoState.mode,
462
+ });
463
+ (0, presence_1.writePresence)(agentRoot, agentName, presence);
464
+ }
465
+ catch (continuityError) {
466
+ (0, runtime_1.emitNervesEvent)({
467
+ level: "warn",
468
+ component: "senses",
469
+ event: "senses.continuity_error",
470
+ message: "continuity pipeline failed, continuing without start-of-turn packet",
471
+ meta: { error: continuityError instanceof Error ? continuityError.message : String(continuityError) },
472
+ });
473
+ }
474
+ // Step 5: runAgent
475
+ const existingToolContext = input.runAgentOptions?.toolContext;
476
+ const runAgentOptions = {
477
+ ...input.runAgentOptions,
478
+ bridgeContext,
479
+ activeWorkFrame,
480
+ delegationDecision,
481
+ startOfTurnPacket: renderedStartOfTurnPacket,
482
+ pendingMessages: pending.length > 0 ? pending.map((msg) => ({ from: msg.from, content: msg.content })) : undefined,
483
+ currentSessionKey: currentSession.key,
484
+ currentObligation,
485
+ mustResolveBeforeHandoff,
486
+ setMustResolveBeforeHandoff: (value) => {
487
+ mustResolveBeforeHandoff = value;
488
+ },
489
+ // Pre-read state from TurnContext for prompt assembly
490
+ daemonRunning: ctx.daemonRunning,
491
+ senseStatusLines: ctx.senseStatusLines,
492
+ bundleMeta: ctx.bundleMeta,
493
+ daemonHealth: ctx.daemonHealth,
494
+ journalFiles: ctx.journalFiles,
495
+ ...(ctx.providerVisibility ? { providerVisibility: ctx.providerVisibility } : {}),
496
+ toolContext: {
497
+ /* v8 ignore next -- default no-op signin satisfies interface; real signin injected by sense adapter @preserve */
498
+ signin: async () => undefined,
499
+ ...existingToolContext,
500
+ context: resolvedContext,
501
+ friendStore: input.friendStore,
502
+ currentSession,
503
+ activeBridges,
504
+ },
505
+ };
506
+ const result = await input.runAgent(sessionMessages, input.callbacks, input.channel, input.signal, runAgentOptions);
507
+ // Step 5b: Failover on terminal error
508
+ if (result.outcome === "errored" && input.failoverState) {
509
+ try {
510
+ const agentName = (0, identity_1.getAgentName)();
511
+ const currentLane = providerLaneForChannel(input.channel);
512
+ const currentBinding = resolveCurrentFailoverBinding(agentName, currentLane);
513
+ const currentProvider = currentBinding.provider;
514
+ /* v8 ignore next -- defensive: errorClassification always set when errored @preserve */
515
+ const classification = result.errorClassification ?? "unknown";
516
+ const inventory = await (0, provider_failover_1.runMachineProviderFailoverInventory)(agentName, currentProvider);
517
+ const failoverContext = (0, provider_failover_1.buildFailoverContext)(
518
+ /* v8 ignore next -- defensive: error always set when errored @preserve */
519
+ result.error?.message ?? "unknown error", classification, currentProvider, currentBinding.model, agentName, inventory, {}, { currentLane });
520
+ input.failoverState.pending = failoverContext;
521
+ input.postTurn(sessionMessages, session.sessionPath, result.usage);
522
+ return {
523
+ resolvedContext,
524
+ gateResult,
525
+ usage: result.usage,
526
+ turnOutcome: result.outcome,
527
+ sessionPath: session.sessionPath,
528
+ messages: sessionMessages,
529
+ drainedPending: pending,
530
+ failoverMessage: failoverContext.userMessage,
531
+ };
532
+ /* v8 ignore start -- failover catch: tested via pipeline failover sequence throws test but v8 under-reports catch coverage @preserve */
533
+ }
534
+ catch (failoverError) {
535
+ (0, runtime_1.emitNervesEvent)({
536
+ level: "warn",
537
+ component: "senses",
538
+ event: "senses.failover_error",
539
+ message: "failover sequence failed, falling through",
540
+ meta: { error: failoverError instanceof Error ? failoverError.message : String(failoverError) },
541
+ });
542
+ }
543
+ /* v8 ignore stop */
544
+ }
545
+ // Step 5c: Emit episodes for obligation state transitions
546
+ try {
547
+ const agentRoot = (0, identity_1.getAgentRoot)();
548
+ const postTurnObligations = (0, obligations_1.readPendingObligations)(agentRoot);
549
+ emitObligationTransitionEpisodes(agentRoot, preTurnObligationIds, postTurnObligations, pendingObligations);
550
+ }
551
+ catch {
552
+ // Episode emission is non-fatal
553
+ }
554
+ // Step 6: postTurn
555
+ const continuingState = {
556
+ ...(mustResolveBeforeHandoff ? { mustResolveBeforeHandoff: true } : {}),
557
+ ...(typeof lastFriendActivityAt === "string" ? { lastFriendActivityAt } : {}),
558
+ };
559
+ const nextState = result.outcome === "settled" || result.outcome === "blocked" || result.outcome === "superseded" || result.outcome === "observed"
560
+ ? (typeof lastFriendActivityAt === "string"
561
+ ? { lastFriendActivityAt }
562
+ : undefined)
563
+ : (Object.keys(continuingState).length > 0 ? continuingState : undefined);
564
+ input.postTurn(sessionMessages, session.sessionPath, result.usage, undefined, nextState);
565
+ // Step 7: Token accumulation
566
+ await input.accumulateFriendTokens(input.friendStore, resolvedContext.friend.id, result.usage);
567
+ (0, runtime_1.emitNervesEvent)({
568
+ component: "senses",
569
+ event: "senses.pipeline_end",
570
+ message: "inbound turn pipeline completed",
571
+ meta: {
572
+ channel: input.channel,
573
+ friendId: resolvedContext.friend.id,
574
+ },
575
+ });
576
+ // DRY cross-session awareness: notify inner dialog that activity happened on another channel
577
+ // Inner dialog's next checkpoint will include this session's state
578
+ if (input.channel !== "inner") {
579
+ try {
580
+ (0, socket_client_1.requestInnerWake)((0, identity_1.getAgentName)()).catch(/* v8 ignore next */ () => { });
581
+ }
582
+ catch { /* getAgentName may fail in test environments */ }
583
+ }
584
+ return {
585
+ resolvedContext,
586
+ gateResult,
587
+ usage: result.usage,
588
+ turnOutcome: result.outcome,
589
+ completion: result.completion,
590
+ sessionPath: session.sessionPath,
591
+ messages: sessionMessages,
592
+ drainedPending: pending,
593
+ ...(input.switchedProvider ? { switchedProvider: input.switchedProvider } : {}),
594
+ };
595
+ }
596
+ finally {
597
+ // Step 6b: Post-turn sync push (opt-in, git-status-based discovery).
598
+ if (syncConfig.enabled) {
599
+ (0, sync_1.postTurnPush)((0, identity_1.getAgentRoot)(), syncConfig);
600
+ }
601
+ }
141
602
  }