@ouro.bot/cli 0.1.0-alpha.49 → 0.1.0-alpha.491

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 (365) hide show
  1. package/README.md +133 -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 +3126 -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 +989 -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 +281 -0
  29. package/dist/heart/bridges/manager.js +37 -0
  30. package/dist/heart/bridges/state-machine.js +20 -0
  31. package/dist/heart/bundle-state.js +168 -0
  32. package/dist/heart/commitments.js +111 -0
  33. package/dist/heart/config-registry.js +304 -0
  34. package/dist/heart/config.js +119 -129
  35. package/dist/heart/core.js +845 -229
  36. package/dist/heart/cross-chat-delivery.js +131 -0
  37. package/dist/heart/daemon/agent-config-check.js +490 -0
  38. package/dist/heart/daemon/agent-discovery.js +79 -3
  39. package/dist/heart/daemon/agent-service.js +360 -0
  40. package/dist/heart/daemon/agentic-repair.js +216 -0
  41. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  42. package/dist/heart/daemon/cadence.js +70 -0
  43. package/dist/heart/daemon/cli-defaults.js +640 -0
  44. package/dist/heart/daemon/cli-exec.js +7239 -0
  45. package/dist/heart/daemon/cli-help.js +493 -0
  46. package/dist/heart/daemon/cli-parse.js +1533 -0
  47. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  48. package/dist/heart/daemon/cli-render.js +561 -0
  49. package/dist/heart/daemon/cli-types.js +8 -0
  50. package/dist/heart/daemon/connect-bay.js +323 -0
  51. package/dist/heart/daemon/daemon-cli.js +29 -1616
  52. package/dist/heart/daemon/daemon-entry.js +345 -3
  53. package/dist/heart/daemon/daemon-health.js +141 -0
  54. package/dist/heart/daemon/daemon-runtime-sync.js +190 -12
  55. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  56. package/dist/heart/daemon/daemon.js +677 -58
  57. package/dist/heart/daemon/dns-workflow.js +394 -0
  58. package/dist/heart/daemon/doctor-types.js +8 -0
  59. package/dist/heart/daemon/doctor.js +486 -0
  60. package/dist/heart/daemon/health-monitor.js +92 -1
  61. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  62. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  63. package/dist/heart/daemon/http-health-probe.js +80 -0
  64. package/dist/heart/daemon/human-command-screens.js +234 -0
  65. package/dist/heart/daemon/human-readiness.js +114 -0
  66. package/dist/heart/daemon/inner-status.js +89 -0
  67. package/dist/heart/daemon/interactive-repair.js +394 -0
  68. package/dist/heart/daemon/launchd.js +25 -5
  69. package/dist/heart/daemon/log-tailer.js +82 -12
  70. package/dist/heart/daemon/logs-prune.js +110 -0
  71. package/dist/heart/daemon/message-router.js +2 -2
  72. package/dist/heart/daemon/os-cron-deps.js +134 -0
  73. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  74. package/dist/heart/daemon/ouro-entry.js +3 -1
  75. package/dist/heart/daemon/process-manager.js +214 -0
  76. package/dist/heart/daemon/provider-discovery.js +137 -0
  77. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  78. package/dist/heart/daemon/pulse.js +475 -0
  79. package/dist/heart/daemon/readiness-repair.js +365 -0
  80. package/dist/heart/daemon/run-hooks.js +2 -0
  81. package/dist/heart/daemon/runtime-logging.js +67 -16
  82. package/dist/heart/daemon/runtime-metadata.js +73 -0
  83. package/dist/heart/daemon/runtime-mode.js +67 -0
  84. package/dist/heart/daemon/safe-mode.js +161 -0
  85. package/dist/heart/daemon/sense-manager.js +178 -37
  86. package/dist/heart/daemon/session-id-resolver.js +131 -0
  87. package/dist/heart/daemon/skill-management-installer.js +94 -0
  88. package/dist/heart/daemon/socket-client.js +109 -4
  89. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  90. package/dist/heart/daemon/startup-tui.js +264 -0
  91. package/dist/heart/daemon/task-scheduler.js +3 -25
  92. package/dist/heart/daemon/terminal-ui.js +499 -0
  93. package/dist/heart/daemon/thoughts.js +162 -17
  94. package/dist/heart/daemon/up-progress.js +366 -0
  95. package/dist/heart/daemon/vault-items.js +56 -0
  96. package/dist/heart/delegation.js +62 -0
  97. package/dist/heart/habits/habit-migration.js +189 -0
  98. package/dist/heart/habits/habit-parser.js +140 -0
  99. package/dist/heart/habits/habit-runtime-state.js +100 -0
  100. package/dist/heart/habits/habit-scheduler.js +372 -0
  101. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  102. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  103. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  104. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  105. package/dist/heart/identity.js +201 -66
  106. package/dist/heart/kept-notes.js +357 -0
  107. package/dist/heart/kicks.js +1 -1
  108. package/dist/heart/machine-identity.js +161 -0
  109. package/dist/heart/mail-import-discovery.js +353 -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 +103 -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 +382 -0
  123. package/dist/heart/outlook/readers/continuity-readers.js +336 -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 +301 -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 +104 -13
  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 +63 -39
  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 +981 -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 +48 -28
  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 +372 -0
  163. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  164. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  165. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  166. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  167. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  168. package/dist/heart/{daemon → versioning}/update-checker.js +5 -1
  169. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  170. package/dist/mailroom/attention.js +167 -0
  171. package/dist/mailroom/autonomy.js +209 -0
  172. package/dist/mailroom/blob-store.js +600 -0
  173. package/dist/mailroom/core.js +658 -0
  174. package/dist/mailroom/entry.js +160 -0
  175. package/dist/mailroom/file-store.js +426 -0
  176. package/dist/mailroom/mbox-import.js +382 -0
  177. package/dist/mailroom/outbound.js +380 -0
  178. package/dist/mailroom/policy.js +263 -0
  179. package/dist/mailroom/reader.js +219 -0
  180. package/dist/mailroom/search-cache.js +182 -0
  181. package/dist/mailroom/search-relevance.js +319 -0
  182. package/dist/mailroom/smtp-ingress.js +176 -0
  183. package/dist/mailroom/source-state.js +176 -0
  184. package/dist/mailroom/travel-extract.js +89 -0
  185. package/dist/mind/bundle-manifest.js +7 -1
  186. package/dist/mind/context.js +164 -93
  187. package/dist/mind/diary-integrity.js +60 -0
  188. package/dist/mind/{memory.js → diary.js} +74 -93
  189. package/dist/mind/embedding-provider.js +60 -0
  190. package/dist/mind/file-state.js +179 -0
  191. package/dist/mind/friends/channel.js +30 -0
  192. package/dist/mind/friends/group-context.js +144 -0
  193. package/dist/mind/friends/resolver.js +54 -2
  194. package/dist/mind/friends/store-file.js +39 -3
  195. package/dist/mind/friends/trust-explanation.js +74 -0
  196. package/dist/mind/friends/types.js +2 -2
  197. package/dist/mind/journal-index.js +161 -0
  198. package/dist/mind/note-search.js +268 -0
  199. package/dist/mind/obligation-steering.js +221 -0
  200. package/dist/mind/pending.js +56 -8
  201. package/dist/mind/prompt-refresh.js +3 -2
  202. package/dist/mind/prompt.js +973 -168
  203. package/dist/mind/provenance-trust.js +26 -0
  204. package/dist/mind/scrutiny.js +173 -0
  205. package/dist/nerves/cli-logging.js +7 -1
  206. package/dist/nerves/coverage/audit-rules.js +15 -6
  207. package/dist/nerves/coverage/audit.js +28 -2
  208. package/dist/nerves/coverage/cli.js +1 -1
  209. package/dist/nerves/coverage/contract.js +5 -5
  210. package/dist/nerves/coverage/file-completeness.js +93 -5
  211. package/dist/nerves/coverage/run-artifacts.js +1 -1
  212. package/dist/nerves/event-buffer.js +111 -0
  213. package/dist/nerves/index.js +224 -4
  214. package/dist/nerves/observation.js +20 -0
  215. package/dist/nerves/redact.js +79 -0
  216. package/dist/nerves/runtime.js +5 -1
  217. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  218. package/dist/outlook-ui/assets/index-Cm51CY9W.js +61 -0
  219. package/dist/outlook-ui/index.html +15 -0
  220. package/dist/repertoire/ado-client.js +15 -56
  221. package/dist/repertoire/ado-semantic.js +11 -10
  222. package/dist/repertoire/api-client.js +97 -0
  223. package/dist/repertoire/bitwarden-store.js +774 -0
  224. package/dist/repertoire/bundle-templates.js +72 -0
  225. package/dist/repertoire/bw-installer.js +180 -0
  226. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  227. package/dist/repertoire/coding/context-pack.js +330 -0
  228. package/dist/repertoire/coding/feedback.js +197 -30
  229. package/dist/repertoire/coding/manager.js +158 -9
  230. package/dist/repertoire/coding/spawner.js +55 -9
  231. package/dist/repertoire/coding/tools.js +170 -7
  232. package/dist/repertoire/commerce-errors.js +109 -0
  233. package/dist/repertoire/commerce-self-test.js +156 -0
  234. package/dist/repertoire/credential-access.js +111 -0
  235. package/dist/repertoire/duffel-client.js +185 -0
  236. package/dist/repertoire/github-client.js +14 -55
  237. package/dist/repertoire/graph-client.js +11 -52
  238. package/dist/repertoire/guardrails.js +396 -0
  239. package/dist/repertoire/mcp-client.js +255 -0
  240. package/dist/repertoire/mcp-manager.js +305 -0
  241. package/dist/repertoire/mcp-tools.js +63 -0
  242. package/dist/repertoire/shell-sessions.js +133 -0
  243. package/dist/repertoire/skills.js +15 -24
  244. package/dist/repertoire/stripe-client.js +131 -0
  245. package/dist/repertoire/tasks/board.js +31 -5
  246. package/dist/repertoire/tasks/fix.js +182 -0
  247. package/dist/repertoire/tasks/index.js +16 -4
  248. package/dist/repertoire/tasks/lifecycle.js +2 -2
  249. package/dist/repertoire/tasks/parser.js +3 -2
  250. package/dist/repertoire/tasks/scanner.js +194 -37
  251. package/dist/repertoire/tasks/transitions.js +16 -78
  252. package/dist/repertoire/tool-results.js +29 -0
  253. package/dist/repertoire/tools-attachments.js +317 -0
  254. package/dist/repertoire/tools-base.js +46 -842
  255. package/dist/repertoire/tools-bluebubbles.js +1 -0
  256. package/dist/repertoire/tools-bridge.js +141 -0
  257. package/dist/repertoire/tools-bundle.js +984 -0
  258. package/dist/repertoire/tools-config.js +185 -0
  259. package/dist/repertoire/tools-continuity.js +248 -0
  260. package/dist/repertoire/tools-credential.js +381 -0
  261. package/dist/repertoire/tools-files.js +342 -0
  262. package/dist/repertoire/tools-flight.js +224 -0
  263. package/dist/repertoire/tools-flow.js +105 -0
  264. package/dist/repertoire/tools-github.js +1 -7
  265. package/dist/repertoire/tools-mail.js +1281 -0
  266. package/dist/repertoire/tools-notes.js +376 -0
  267. package/dist/repertoire/tools-session.js +749 -0
  268. package/dist/repertoire/tools-shell.js +120 -0
  269. package/dist/repertoire/tools-stripe.js +180 -0
  270. package/dist/repertoire/tools-surface.js +243 -0
  271. package/dist/repertoire/tools-teams.js +9 -39
  272. package/dist/repertoire/tools-travel.js +125 -0
  273. package/dist/repertoire/tools-trip.js +356 -0
  274. package/dist/repertoire/tools-user-profile.js +144 -0
  275. package/dist/repertoire/tools-vault.js +40 -0
  276. package/dist/repertoire/tools.js +144 -115
  277. package/dist/repertoire/travel-api-client.js +360 -0
  278. package/dist/repertoire/user-profile.js +131 -0
  279. package/dist/repertoire/vault-setup.js +246 -0
  280. package/dist/repertoire/vault-unlock.js +561 -0
  281. package/dist/scripts/claude-code-hook.js +41 -0
  282. package/dist/scripts/claude-code-stop-hook.js +47 -0
  283. package/dist/senses/attention-queue.js +116 -0
  284. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  285. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  286. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  287. package/dist/senses/bluebubbles/entry.js +73 -0
  288. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  289. package/dist/senses/bluebubbles/index.js +1835 -0
  290. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  291. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  292. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  293. package/dist/senses/bluebubbles/processed-log.js +111 -0
  294. package/dist/senses/bluebubbles/replay.js +129 -0
  295. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
  296. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  297. package/dist/senses/cli/bracketed-paste.js +82 -0
  298. package/dist/senses/cli/image-paste.js +287 -0
  299. package/dist/senses/cli/image-ref-navigation.js +75 -0
  300. package/dist/senses/cli/ink-app.js +156 -0
  301. package/dist/senses/cli/inline-diff.js +64 -0
  302. package/dist/senses/cli/input-keys.js +174 -0
  303. package/dist/senses/cli/kill-ring.js +86 -0
  304. package/dist/senses/cli/message-list.js +51 -0
  305. package/dist/senses/cli/ouro-tui.js +605 -0
  306. package/dist/senses/cli/spinner-imperative.js +135 -0
  307. package/dist/senses/cli/spinner.js +101 -0
  308. package/dist/senses/cli/status-line.js +60 -0
  309. package/dist/senses/cli/streaming-markdown.js +526 -0
  310. package/dist/senses/cli/tool-display.js +83 -0
  311. package/dist/senses/cli/tool-render.js +85 -0
  312. package/dist/senses/cli/tui-store.js +240 -0
  313. package/dist/senses/cli/virtual-list.js +35 -0
  314. package/dist/senses/cli-entry.js +60 -8
  315. package/dist/senses/cli-layout.js +187 -0
  316. package/dist/senses/cli.js +515 -211
  317. package/dist/senses/commands.js +66 -3
  318. package/dist/senses/habit-turn-message.js +108 -0
  319. package/dist/senses/inner-dialog-worker.js +110 -20
  320. package/dist/senses/inner-dialog.js +408 -21
  321. package/dist/senses/mail-entry.js +66 -0
  322. package/dist/senses/mail.js +379 -0
  323. package/dist/senses/pipeline.js +588 -81
  324. package/dist/senses/proactive-content-guard.js +51 -0
  325. package/dist/senses/shared-turn.js +248 -0
  326. package/dist/senses/surface-tool.js +68 -0
  327. package/dist/senses/teams-entry.js +60 -8
  328. package/dist/senses/teams.js +412 -163
  329. package/dist/senses/trust-gate.js +100 -5
  330. package/dist/trips/core.js +138 -0
  331. package/dist/trips/store.js +146 -0
  332. package/package.json +37 -7
  333. package/skills/agent-commerce.md +106 -0
  334. package/skills/browser-navigation.md +117 -0
  335. package/skills/commerce-setup-guide.md +116 -0
  336. package/skills/commerce-setup.md +84 -0
  337. package/skills/configure-dev-tools.md +101 -0
  338. package/skills/travel-planning.md +138 -0
  339. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  340. package/dist/heart/daemon/subagent-installer.js +0 -166
  341. package/dist/heart/session-recall.js +0 -116
  342. package/dist/mind/associative-recall.js +0 -209
  343. package/dist/senses/bluebubbles-entry.js +0 -13
  344. package/dist/senses/bluebubbles.js +0 -1032
  345. package/dist/senses/debug-activity.js +0 -127
  346. package/subagents/README.md +0 -86
  347. package/subagents/work-doer.md +0 -237
  348. package/subagents/work-merger.md +0 -618
  349. package/subagents/work-planner.md +0 -390
  350. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  351. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  352. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  353. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  354. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  355. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  356. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  357. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  358. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  359. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  360. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  361. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  362. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  363. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  364. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  365. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FinalAnswerStreamer = exports.FinalAnswerParser = void 0;
3
+ exports.RESPONSES_FUNCTION_CALL_OUTPUT_CAP = exports.SettleStreamer = exports.SettleParser = void 0;
4
+ exports.truncateResponsesFunctionCallOutput = truncateResponsesFunctionCallOutput;
4
5
  exports.toResponsesInput = toResponsesInput;
5
6
  exports.toResponsesTools = toResponsesTools;
6
7
  exports.streamChatCompletion = streamChatCompletion;
7
8
  exports.streamResponsesApi = streamResponsesApi;
8
9
  const runtime_1 = require("../nerves/runtime");
9
10
  // Character-level state machine that extracts the answer value from
10
- // `final_answer` tool call JSON arguments as they stream in.
11
+ // `settle` tool call JSON arguments as they stream in.
11
12
  // Scans for prefix `"answer":"` or `"answer": "` in the character stream,
12
13
  // then emits text handling JSON escapes, stopping at unescaped closing `"`.
13
- class FinalAnswerParser {
14
+ class SettleParser {
14
15
  // Possible prefixes to match (with and without space after colon)
15
16
  static PREFIXES = ['"answer":"', '"answer": "'];
16
17
  // Buffer of characters seen so far (pre-activation only)
@@ -29,7 +30,7 @@ class FinalAnswerParser {
29
30
  if (!this._active) {
30
31
  this.buf += ch;
31
32
  // Check if any prefix has been fully matched in the buffer
32
- for (const prefix of FinalAnswerParser.PREFIXES) {
33
+ for (const prefix of SettleParser.PREFIXES) {
33
34
  if (this.buf.endsWith(prefix)) {
34
35
  this._active = true;
35
36
  break;
@@ -76,21 +77,25 @@ class FinalAnswerParser {
76
77
  return out;
77
78
  }
78
79
  }
79
- exports.FinalAnswerParser = FinalAnswerParser;
80
- // Shared helper: wraps FinalAnswerParser with onClearText + onTextChunk wiring.
80
+ exports.SettleParser = SettleParser;
81
+ // Shared helper: wraps SettleParser with onClearText + onTextChunk wiring.
81
82
  // Used by all streaming providers (Chat Completions, Responses API, Anthropic)
82
- // so the eager-match streaming pattern lives in one place.
83
- class FinalAnswerStreamer {
84
- parser = new FinalAnswerParser();
83
+ // so the eager-match settle streaming pattern lives in one place.
84
+ class SettleStreamer {
85
+ parser = new SettleParser();
85
86
  _detected = false;
86
87
  callbacks;
87
- constructor(callbacks) {
88
+ enabled;
89
+ constructor(callbacks, enabled = true) {
88
90
  this.callbacks = callbacks;
91
+ this.enabled = enabled;
89
92
  }
90
93
  get detected() { return this._detected; }
91
94
  get streamed() { return this.parser.active; }
92
- /** Mark final_answer as detected. Calls onClearText on the callbacks. */
95
+ /** Mark settle as detected. Calls onClearText on the callbacks. */
93
96
  activate() {
97
+ if (!this.enabled)
98
+ return;
94
99
  if (this._detected)
95
100
  return;
96
101
  this._detected = true;
@@ -98,6 +103,8 @@ class FinalAnswerStreamer {
98
103
  }
99
104
  /** Feed an argument delta through the parser. Emits text via onTextChunk. */
100
105
  processDelta(delta) {
106
+ if (!this.enabled)
107
+ return;
101
108
  if (!this._detected)
102
109
  return;
103
110
  const text = this.parser.process(delta);
@@ -105,7 +112,17 @@ class FinalAnswerStreamer {
105
112
  this.callbacks.onTextChunk(text);
106
113
  }
107
114
  }
108
- exports.FinalAnswerStreamer = FinalAnswerStreamer;
115
+ exports.SettleStreamer = SettleStreamer;
116
+ exports.RESPONSES_FUNCTION_CALL_OUTPUT_CAP = 200_000;
117
+ function truncateResponsesFunctionCallOutput(output, maxChars = exports.RESPONSES_FUNCTION_CALL_OUTPUT_CAP) {
118
+ if (output.length <= maxChars)
119
+ return output;
120
+ const marker = `\n\n[truncated — function_call_output exceeded ${maxChars} chars; original length ${output.length} chars]\n\n`;
121
+ const remainingBudget = Math.max(0, maxChars - marker.length);
122
+ const headLength = Math.ceil(remainingBudget * 0.75);
123
+ const tailLength = Math.max(0, remainingBudget - headLength);
124
+ return `${output.slice(0, headLength)}${marker}${output.slice(-tailLength)}`;
125
+ }
109
126
  function toResponsesUserContent(content) {
110
127
  if (typeof content === "string") {
111
128
  return content;
@@ -185,7 +202,10 @@ function toResponsesInput(messages) {
185
202
  }
186
203
  }
187
204
  if (a.content) {
188
- input.push({ role: "assistant", content: typeof a.content === "string" ? a.content : "" });
205
+ const assistantItem = { role: "assistant", content: typeof a.content === "string" ? a.content : "" };
206
+ if (a.phase)
207
+ assistantItem.phase = a.phase;
208
+ input.push(assistantItem);
189
209
  }
190
210
  if (a.tool_calls) {
191
211
  for (const tc of a.tool_calls) {
@@ -208,7 +228,7 @@ function toResponsesInput(messages) {
208
228
  input.push({
209
229
  type: "function_call_output",
210
230
  call_id: t.tool_call_id,
211
- output: typeof t.content === "string" ? t.content : "",
231
+ output: truncateResponsesFunctionCallOutput(typeof t.content === "string" ? t.content : ""),
212
232
  });
213
233
  continue;
214
234
  }
@@ -224,7 +244,7 @@ function toResponsesTools(ccTools) {
224
244
  strict: false,
225
245
  }));
226
246
  }
227
- async function streamChatCompletion(client, createParams, callbacks, signal) {
247
+ async function streamChatCompletion(client, createParams, callbacks, signal, eagerSettleStreaming = true) {
228
248
  (0, runtime_1.emitNervesEvent)({
229
249
  component: "engine",
230
250
  event: "engine.stream_start",
@@ -238,7 +258,7 @@ async function streamChatCompletion(client, createParams, callbacks, signal) {
238
258
  let toolCalls = {};
239
259
  let streamStarted = false;
240
260
  let usage;
241
- const answerStreamer = new FinalAnswerStreamer(callbacks);
261
+ const answerStreamer = new SettleStreamer(callbacks, eagerSettleStreaming);
242
262
  // State machine for parsing inline <think> tags (MiniMax pattern)
243
263
  let contentBuf = "";
244
264
  let inThinkTag = false;
@@ -353,19 +373,19 @@ async function streamChatCompletion(client, createParams, callbacks, signal) {
353
373
  toolCalls[tc.index].id = tc.id;
354
374
  if (tc.function?.name) {
355
375
  toolCalls[tc.index].name = tc.function.name;
356
- // Detect final_answer tool call on first name delta.
376
+ // Detect settle tool call on first name delta.
357
377
  // Only activate streaming if this is the sole tool call (index 0
358
378
  // and no other indices seen). Mixed calls are rejected by core.ts.
359
- if (tc.function.name === "final_answer" && !answerStreamer.detected
379
+ if (tc.function.name === "settle" && !answerStreamer.detected
360
380
  && tc.index === 0 && Object.keys(toolCalls).length === 1) {
361
381
  answerStreamer.activate();
362
382
  }
363
383
  }
364
384
  if (tc.function?.arguments) {
365
385
  toolCalls[tc.index].arguments += tc.function.arguments;
366
- // Feed final_answer argument deltas to the parser for progressive
386
+ // Feed settle argument deltas to the parser for progressive
367
387
  // streaming, but only when it appears to be the sole tool call.
368
- if (answerStreamer.detected && toolCalls[tc.index].name === "final_answer"
388
+ if (answerStreamer.detected && toolCalls[tc.index].name === "settle"
369
389
  && Object.keys(toolCalls).length === 1) {
370
390
  answerStreamer.processDelta(tc.function.arguments);
371
391
  }
@@ -381,10 +401,10 @@ async function streamChatCompletion(client, createParams, callbacks, signal) {
381
401
  toolCalls: Object.values(toolCalls),
382
402
  outputItems: [],
383
403
  usage,
384
- finalAnswerStreamed: answerStreamer.streamed,
404
+ settleStreamed: answerStreamer.streamed,
385
405
  };
386
406
  }
387
- async function streamResponsesApi(client, createParams, callbacks, signal) {
407
+ async function streamResponsesApi(client, createParams, callbacks, signal, eagerSettleStreaming = true) {
388
408
  (0, runtime_1.emitNervesEvent)({
389
409
  component: "engine",
390
410
  event: "engine.stream_start",
@@ -399,7 +419,7 @@ async function streamResponsesApi(client, createParams, callbacks, signal) {
399
419
  const outputItems = [];
400
420
  let currentToolCall = null;
401
421
  let usage;
402
- const answerStreamer = new FinalAnswerStreamer(callbacks);
422
+ const answerStreamer = new SettleStreamer(callbacks, eagerSettleStreaming);
403
423
  let functionCallCount = 0;
404
424
  for await (const event of response) {
405
425
  if (signal?.aborted)
@@ -429,10 +449,10 @@ async function streamResponsesApi(client, createParams, callbacks, signal) {
429
449
  name: String(event.item.name),
430
450
  arguments: "",
431
451
  };
432
- // Detect final_answer function call -- clear any streamed noise.
452
+ // Detect settle function call -- clear any streamed noise.
433
453
  // Only activate when this is the first (and so far only) function call.
434
454
  // Mixed calls are rejected by core.ts; no need to stream their args.
435
- if (String(event.item.name) === "final_answer" && functionCallCount === 1) {
455
+ if (String(event.item.name) === "settle" && functionCallCount === 1) {
436
456
  answerStreamer.activate();
437
457
  }
438
458
  }
@@ -441,9 +461,9 @@ async function streamResponsesApi(client, createParams, callbacks, signal) {
441
461
  case "response.function_call_arguments.delta": {
442
462
  if (currentToolCall) {
443
463
  currentToolCall.arguments += event.delta;
444
- // Feed final_answer argument deltas to the parser for progressive
464
+ // Feed settle argument deltas to the parser for progressive
445
465
  // streaming, but only when it appears to be the sole function call.
446
- if (answerStreamer.detected && currentToolCall.name === "final_answer"
466
+ if (answerStreamer.detected && currentToolCall.name === "settle"
447
467
  && functionCallCount === 1) {
448
468
  answerStreamer.processDelta(String(event.delta));
449
469
  }
@@ -485,6 +505,6 @@ async function streamResponsesApi(client, createParams, callbacks, signal) {
485
505
  toolCalls,
486
506
  outputItems,
487
507
  usage,
488
- finalAnswerStreamed: answerStreamer.streamed,
508
+ settleStreamed: answerStreamer.streamed,
489
509
  };
490
510
  }
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.preTurnPull = preTurnPull;
37
+ exports.postTurnPush = postTurnPush;
38
+ const child_process_1 = require("child_process");
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const runtime_1 = require("../nerves/runtime");
42
+ function writePendingSync(agentRoot, error, classification, conflictFiles) {
43
+ const pendingSyncPath = path.join(agentRoot, "state", "pending-sync.json");
44
+ fs.mkdirSync(path.join(agentRoot, "state"), { recursive: true });
45
+ const record = {
46
+ error,
47
+ failedAt: new Date().toISOString(),
48
+ classification,
49
+ conflictFiles,
50
+ };
51
+ fs.writeFileSync(pendingSyncPath, JSON.stringify(record, null, 2), "utf-8");
52
+ }
53
+ function collectRebaseConflictFiles(agentRoot) {
54
+ try {
55
+ const output = (0, child_process_1.execFileSync)("git", ["status", "--porcelain=v1"], {
56
+ cwd: agentRoot,
57
+ stdio: "pipe",
58
+ timeout: 5000,
59
+ }).toString();
60
+ const files = [];
61
+ for (const line of output.split("\n")) {
62
+ // Unmerged paths in porcelain v1 are prefixed with UU/AA/DD/AU/UA/DU/UD
63
+ if (/^(UU|AA|DD|AU|UA|DU|UD) /.test(line)) {
64
+ files.push(line.slice(3).trim());
65
+ }
66
+ }
67
+ return files;
68
+ }
69
+ catch {
70
+ /* v8 ignore next -- git status --porcelain failure inside a repo would require a corrupt repo @preserve */
71
+ return [];
72
+ }
73
+ }
74
+ /**
75
+ * Check whether the bundle is initialized as a git repo.
76
+ * Used by both pre-turn pull and post-turn push to surface a clear,
77
+ * actionable error when sync is enabled but the user never ran `git init`
78
+ * inside their bundle. This error is propagated all the way into the
79
+ * agent's start-of-turn packet as a Sync warning, so the agent can
80
+ * either ask the user or run `git init` itself.
81
+ */
82
+ function ensureGitRepo(agentRoot) {
83
+ if (fs.existsSync(path.join(agentRoot, ".git"))) {
84
+ return { ok: true };
85
+ }
86
+ const error = `bundle is not a git repo; run \`git init\` inside ${agentRoot} to enable sync (or disable sync in agent.json)`;
87
+ return { ok: false, error };
88
+ }
89
+ /**
90
+ * Pre-turn pull: sync the agent bundle from remote before assembling the start-of-turn packet.
91
+ *
92
+ * If the bundle has no git remote configured, the pull is skipped and the function
93
+ * returns ok — matching the no-remote behavior of postTurnPush. This supports the
94
+ * "local-only sync" mode where the bundle accumulates a commit log without ever
95
+ * pushing or pulling from a remote.
96
+ */
97
+ function preTurnPull(agentRoot, config) {
98
+ (0, runtime_1.emitNervesEvent)({
99
+ component: "heart",
100
+ event: "heart.sync_pull_start",
101
+ message: "pre-turn pull starting",
102
+ meta: { agentRoot, remote: config.remote },
103
+ });
104
+ // Check that the bundle is actually a git repo before touching git at all.
105
+ // Surfaces a clear, actionable error via syncFailure → start-of-turn packet
106
+ // so the agent can propose running `git init` (or just do it).
107
+ const repoCheck = ensureGitRepo(agentRoot);
108
+ if (!repoCheck.ok) {
109
+ (0, runtime_1.emitNervesEvent)({
110
+ level: "warn",
111
+ component: "heart",
112
+ event: "heart.sync_not_a_repo",
113
+ message: "pre-turn pull failed: bundle is not a git repo",
114
+ meta: { agentRoot },
115
+ });
116
+ return repoCheck;
117
+ }
118
+ // Check if any remote is configured. If not, skip the pull (local-only mode).
119
+ try {
120
+ const remoteOutput = (0, child_process_1.execFileSync)("git", ["remote"], {
121
+ cwd: agentRoot,
122
+ stdio: "pipe",
123
+ timeout: 5000,
124
+ }).toString().trim();
125
+ if (remoteOutput.length === 0) {
126
+ (0, runtime_1.emitNervesEvent)({
127
+ component: "heart",
128
+ event: "heart.sync_pull_end",
129
+ message: "pre-turn pull skipped: no remote configured",
130
+ meta: { agentRoot },
131
+ });
132
+ return { ok: true };
133
+ }
134
+ }
135
+ catch (err) {
136
+ const error = err instanceof Error ? err.message : String(err);
137
+ (0, runtime_1.emitNervesEvent)({
138
+ component: "heart",
139
+ event: "heart.sync_pull_error",
140
+ message: "pre-turn pull failed: git remote check failed",
141
+ meta: { agentRoot, error },
142
+ });
143
+ return { ok: false, error };
144
+ }
145
+ try {
146
+ (0, child_process_1.execFileSync)("git", ["pull", config.remote], {
147
+ cwd: agentRoot,
148
+ stdio: "pipe",
149
+ timeout: 30000,
150
+ });
151
+ (0, runtime_1.emitNervesEvent)({
152
+ component: "heart",
153
+ event: "heart.sync_pull_end",
154
+ message: "pre-turn pull complete",
155
+ meta: { agentRoot },
156
+ });
157
+ return { ok: true };
158
+ }
159
+ catch (err) {
160
+ const error = err instanceof Error ? err.message : String(err);
161
+ (0, runtime_1.emitNervesEvent)({
162
+ component: "heart",
163
+ event: "heart.sync_pull_error",
164
+ message: "pre-turn pull failed",
165
+ meta: { agentRoot, error },
166
+ });
167
+ return { ok: false, error };
168
+ }
169
+ }
170
+ /**
171
+ * Post-turn push: discover dirty files via `git status`, commit, and push.
172
+ * Uses git-status-based discovery instead of explicit path tracking, ensuring
173
+ * all file writers are captured regardless of whether they call a tracking API.
174
+ */
175
+ function postTurnPush(agentRoot, config) {
176
+ (0, runtime_1.emitNervesEvent)({
177
+ component: "heart",
178
+ event: "heart.sync_push_start",
179
+ message: "post-turn push starting",
180
+ meta: { agentRoot, remote: config.remote },
181
+ });
182
+ // Same git-repo check as preTurnPull. This is the more common failure path
183
+ // since postTurnPush runs after every turn while preTurnPull only runs on
184
+ // user-initiated turns. Prior to this guard, an un-init'd bundle would fail
185
+ // the git-status invocation below with a generic "not a git repository"
186
+ // error; now we catch it explicitly with an actionable message.
187
+ const repoCheck = ensureGitRepo(agentRoot);
188
+ if (!repoCheck.ok) {
189
+ (0, runtime_1.emitNervesEvent)({
190
+ level: "warn",
191
+ component: "heart",
192
+ event: "heart.sync_not_a_repo",
193
+ message: "post-turn push failed: bundle is not a git repo",
194
+ meta: { agentRoot },
195
+ });
196
+ return repoCheck;
197
+ }
198
+ let statusOutput;
199
+ try {
200
+ statusOutput = (0, child_process_1.execFileSync)("git", ["status", "--porcelain"], {
201
+ cwd: agentRoot,
202
+ stdio: "pipe",
203
+ timeout: 10000,
204
+ }).toString().trim();
205
+ }
206
+ catch (err) {
207
+ const error = err instanceof Error ? err.message : String(err);
208
+ (0, runtime_1.emitNervesEvent)({
209
+ component: "heart",
210
+ event: "heart.sync_push_error",
211
+ message: "post-turn push: git status failed",
212
+ meta: { agentRoot, error },
213
+ });
214
+ return { ok: false, error };
215
+ }
216
+ if (statusOutput.length === 0) {
217
+ (0, runtime_1.emitNervesEvent)({
218
+ component: "heart",
219
+ event: "heart.sync_push_end",
220
+ message: "post-turn push: no changes to sync",
221
+ meta: { agentRoot },
222
+ });
223
+ return { ok: true };
224
+ }
225
+ const changedCount = statusOutput.split("\n").length;
226
+ try {
227
+ (0, child_process_1.execFileSync)("git", ["add", "-A"], {
228
+ cwd: agentRoot,
229
+ stdio: "pipe",
230
+ timeout: 10000,
231
+ });
232
+ (0, child_process_1.execFileSync)("git", ["commit", "-m", "sync: post-turn update"], {
233
+ cwd: agentRoot,
234
+ stdio: "pipe",
235
+ timeout: 10000,
236
+ });
237
+ // Check if a remote exists
238
+ const remoteOutput = (0, child_process_1.execFileSync)("git", ["remote"], {
239
+ cwd: agentRoot,
240
+ stdio: "pipe",
241
+ timeout: 5000,
242
+ }).toString().trim();
243
+ if (remoteOutput.length === 0) {
244
+ (0, runtime_1.emitNervesEvent)({
245
+ component: "heart",
246
+ event: "heart.sync_push_end",
247
+ message: "post-turn push: committed locally, no remote configured",
248
+ meta: { agentRoot, changedCount },
249
+ });
250
+ return { ok: true };
251
+ }
252
+ try {
253
+ (0, child_process_1.execFileSync)("git", ["push", config.remote], {
254
+ cwd: agentRoot,
255
+ stdio: "pipe",
256
+ timeout: 30000,
257
+ });
258
+ }
259
+ catch {
260
+ // Push rejected -- try pull-rebase-push
261
+ let rebaseError = null;
262
+ try {
263
+ (0, child_process_1.execFileSync)("git", ["pull", "--rebase", config.remote], {
264
+ cwd: agentRoot,
265
+ stdio: "pipe",
266
+ timeout: 30000,
267
+ });
268
+ }
269
+ catch (err) {
270
+ rebaseError = err instanceof Error ? err.message : String(err);
271
+ }
272
+ if (rebaseError === null) {
273
+ try {
274
+ (0, child_process_1.execFileSync)("git", ["push", config.remote], {
275
+ cwd: agentRoot,
276
+ stdio: "pipe",
277
+ timeout: 30000,
278
+ });
279
+ // rebase + retry push both succeeded — fall through to success
280
+ (0, runtime_1.emitNervesEvent)({
281
+ component: "heart",
282
+ event: "heart.sync_push_end",
283
+ message: "post-turn push complete after rebase retry",
284
+ meta: { agentRoot, changedCount },
285
+ });
286
+ return { ok: true };
287
+ }
288
+ catch (retryErr) {
289
+ // Second push rejected — remote advanced again during rebase
290
+ const retryError = retryErr instanceof Error ? retryErr.message : /* v8 ignore next -- defensive non-Error catch @preserve */ String(retryErr);
291
+ writePendingSync(agentRoot, retryError, "push_rejected", []);
292
+ (0, runtime_1.emitNervesEvent)({
293
+ component: "heart",
294
+ event: "heart.sync_push_error",
295
+ message: "post-turn push failed after retry: push_rejected",
296
+ meta: { agentRoot, error: retryError, classification: "push_rejected" },
297
+ });
298
+ return { ok: false, error: retryError };
299
+ }
300
+ }
301
+ // Rebase failed — detect conflict files via git status. Preserve
302
+ // the original rebase error message so callers see the real cause.
303
+ const conflictFiles = collectRebaseConflictFiles(agentRoot);
304
+ const classification = conflictFiles.length > 0 ? "pull_rebase_conflict" : "unknown";
305
+ writePendingSync(agentRoot, rebaseError, classification, conflictFiles);
306
+ (0, runtime_1.emitNervesEvent)({
307
+ component: "heart",
308
+ event: "heart.sync_push_error",
309
+ message: `post-turn push failed: ${classification}`,
310
+ meta: { agentRoot, error: rebaseError, classification, conflictFiles },
311
+ });
312
+ return { ok: false, error: rebaseError };
313
+ }
314
+ (0, runtime_1.emitNervesEvent)({
315
+ component: "heart",
316
+ event: "heart.sync_push_end",
317
+ message: "post-turn push complete",
318
+ meta: { agentRoot, changedCount },
319
+ });
320
+ return { ok: true };
321
+ }
322
+ catch (err) {
323
+ const error = err instanceof Error ? err.message : String(err);
324
+ (0, runtime_1.emitNervesEvent)({
325
+ component: "heart",
326
+ event: "heart.sync_push_error",
327
+ message: "post-turn push failed",
328
+ meta: { agentRoot, error },
329
+ });
330
+ return { ok: false, error };
331
+ }
332
+ }
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listTargetSessionCandidates = listTargetSessionCandidates;
4
+ exports.formatTargetSessionCandidates = formatTargetSessionCandidates;
5
+ const session_transcript_1 = require("./session-transcript");
6
+ const session_activity_1 = require("./session-activity");
7
+ const trust_explanation_1 = require("../mind/friends/trust-explanation");
8
+ const runtime_1 = require("../nerves/runtime");
9
+ function synthesizeFriendRecord(candidate) {
10
+ return {
11
+ id: candidate.friendId,
12
+ name: candidate.friendName,
13
+ role: "stranger",
14
+ trustLevel: "stranger",
15
+ connections: [],
16
+ externalIds: [],
17
+ tenantMemberships: [],
18
+ toolPreferences: {},
19
+ notes: {},
20
+ totalTokens: 0,
21
+ createdAt: new Date(0).toISOString(),
22
+ updatedAt: new Date(0).toISOString(),
23
+ schemaVersion: 1,
24
+ };
25
+ }
26
+ function deliveryPriority(mode) {
27
+ if (mode === "deliver_now")
28
+ return 0;
29
+ if (mode === "queue_only")
30
+ return 1;
31
+ return 2;
32
+ }
33
+ function activityPriority(source) {
34
+ return source === "friend-facing" ? 0 : 1;
35
+ }
36
+ function describeDelivery(candidate) {
37
+ if (candidate.channel === "mcp") {
38
+ // MCP can't push (no proactive API), but can queue — dev tool picks up via check_response
39
+ return { mode: "queue_only", reason: "MCP session — message queued for dev tool to pick up via check_response" };
40
+ }
41
+ if (candidate.channel !== "bluebubbles" && candidate.channel !== "teams") {
42
+ return { mode: "blocked", reason: "this channel does not support proactive outward delivery yet" };
43
+ }
44
+ if (candidate.trust.level === "family" || candidate.trust.level === "friend") {
45
+ return { mode: "deliver_now", reason: "directly trusted target on a proactive-delivery channel" };
46
+ }
47
+ return { mode: "queue_only", reason: "visible as a live chat, but immediate delivery still needs explicit cross-chat authorization" };
48
+ }
49
+ async function listTargetSessionCandidates(input) {
50
+ (0, runtime_1.emitNervesEvent)({
51
+ component: "engine",
52
+ event: "engine.target_resolution_start",
53
+ message: "listing live target session candidates",
54
+ meta: {
55
+ sessionsDir: input.sessionsDir,
56
+ currentSession: input.currentSession
57
+ ? `${input.currentSession.friendId}/${input.currentSession.channel}/${input.currentSession.key}`
58
+ : null,
59
+ },
60
+ });
61
+ const activity = (0, session_activity_1.listSessionActivity)({
62
+ sessionsDir: input.sessionsDir,
63
+ friendsDir: input.friendsDir,
64
+ agentName: input.agentName,
65
+ currentSession: input.currentSession ?? null,
66
+ }).filter((entry) => entry.channel !== "inner");
67
+ const candidates = [];
68
+ for (const entry of activity) {
69
+ const friend = await input.friendStore.get(entry.friendId) ?? synthesizeFriendRecord(entry);
70
+ const trust = (0, trust_explanation_1.describeTrustContext)({
71
+ friend,
72
+ channel: entry.channel,
73
+ });
74
+ const sessionTail = await (0, session_transcript_1.summarizeSessionTail)({
75
+ sessionPath: entry.sessionPath,
76
+ friendId: entry.friendId,
77
+ channel: entry.channel,
78
+ key: entry.key,
79
+ messageCount: 6,
80
+ summarize: input.summarize,
81
+ trustLevel: trust.level,
82
+ });
83
+ const snapshot = sessionTail.kind === "ok"
84
+ ? sessionTail.snapshot
85
+ : sessionTail.kind === "empty"
86
+ ? "recent focus: no recent visible messages"
87
+ : "recent focus: session transcript unavailable";
88
+ const delivery = describeDelivery({
89
+ channel: entry.channel,
90
+ trust,
91
+ });
92
+ candidates.push({
93
+ friendId: entry.friendId,
94
+ friendName: entry.friendName,
95
+ channel: entry.channel,
96
+ key: entry.key,
97
+ sessionPath: entry.sessionPath,
98
+ snapshot,
99
+ trust,
100
+ delivery,
101
+ lastActivityAt: entry.lastActivityAt,
102
+ lastActivityMs: entry.lastActivityMs,
103
+ activitySource: entry.activitySource,
104
+ });
105
+ }
106
+ return candidates.sort((a, b) => {
107
+ const deliveryDiff = deliveryPriority(a.delivery.mode) - deliveryPriority(b.delivery.mode);
108
+ if (deliveryDiff !== 0)
109
+ return deliveryDiff;
110
+ const sourceDiff = activityPriority(a.activitySource) - activityPriority(b.activitySource);
111
+ if (sourceDiff !== 0)
112
+ return sourceDiff;
113
+ return b.lastActivityMs - a.lastActivityMs;
114
+ });
115
+ }
116
+ function formatTargetSessionCandidates(candidates) {
117
+ if (candidates.length === 0)
118
+ return "";
119
+ const lines = ["## candidate target chats"];
120
+ for (const candidate of candidates) {
121
+ lines.push(`- ${candidate.friendName} [${candidate.friendId}] via ${candidate.channel}/${candidate.key}`);
122
+ lines.push(` trust: ${candidate.trust.level} (${candidate.trust.basis}) — ${candidate.trust.summary}`);
123
+ lines.push(` delivery: ${candidate.delivery.mode} — ${candidate.delivery.reason}`);
124
+ lines.push(` snapshot: ${candidate.snapshot}`);
125
+ }
126
+ return lines.join("\n");
127
+ }