@ouro.bot/cli 0.1.0-alpha.51 → 0.1.0-alpha.510

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 (372) 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 +3245 -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 +867 -35
  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/bundle-state.js +168 -0
  30. package/dist/heart/commitments.js +111 -0
  31. package/dist/heart/config-registry.js +304 -0
  32. package/dist/heart/config.js +119 -129
  33. package/dist/heart/core.js +878 -244
  34. package/dist/heart/cross-chat-delivery.js +131 -0
  35. package/dist/heart/daemon/agent-config-check.js +490 -0
  36. package/dist/heart/daemon/agent-discovery.js +79 -3
  37. package/dist/heart/daemon/agent-service.js +360 -0
  38. package/dist/heart/daemon/agentic-repair.js +216 -0
  39. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  40. package/dist/heart/daemon/cadence.js +70 -0
  41. package/dist/heart/daemon/cli-defaults.js +640 -0
  42. package/dist/heart/daemon/cli-exec.js +7239 -0
  43. package/dist/heart/daemon/cli-help.js +493 -0
  44. package/dist/heart/daemon/cli-parse.js +1533 -0
  45. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  46. package/dist/heart/daemon/cli-render.js +561 -0
  47. package/dist/heart/daemon/cli-types.js +8 -0
  48. package/dist/heart/daemon/connect-bay.js +323 -0
  49. package/dist/heart/daemon/daemon-cli.js +29 -1631
  50. package/dist/heart/daemon/daemon-entry.js +345 -3
  51. package/dist/heart/daemon/daemon-health.js +141 -0
  52. package/dist/heart/daemon/daemon-runtime-sync.js +190 -12
  53. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  54. package/dist/heart/daemon/daemon.js +677 -58
  55. package/dist/heart/daemon/dns-workflow.js +394 -0
  56. package/dist/heart/daemon/doctor-types.js +8 -0
  57. package/dist/heart/daemon/doctor.js +750 -0
  58. package/dist/heart/daemon/health-monitor.js +92 -1
  59. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  60. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  61. package/dist/heart/daemon/http-health-probe.js +80 -0
  62. package/dist/heart/daemon/human-command-screens.js +234 -0
  63. package/dist/heart/daemon/human-readiness.js +114 -0
  64. package/dist/heart/daemon/inner-status.js +89 -0
  65. package/dist/heart/daemon/interactive-repair.js +394 -0
  66. package/dist/heart/daemon/launchd.js +25 -5
  67. package/dist/heart/daemon/log-tailer.js +82 -12
  68. package/dist/heart/daemon/logs-prune.js +110 -0
  69. package/dist/heart/daemon/message-router.js +2 -2
  70. package/dist/heart/daemon/os-cron-deps.js +134 -0
  71. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  72. package/dist/heart/daemon/ouro-entry.js +3 -1
  73. package/dist/heart/daemon/process-manager.js +214 -0
  74. package/dist/heart/daemon/provider-discovery.js +137 -0
  75. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  76. package/dist/heart/daemon/pulse.js +475 -0
  77. package/dist/heart/daemon/readiness-repair.js +365 -0
  78. package/dist/heart/daemon/run-hooks.js +2 -0
  79. package/dist/heart/daemon/runtime-logging.js +67 -16
  80. package/dist/heart/daemon/runtime-metadata.js +73 -0
  81. package/dist/heart/daemon/runtime-mode.js +67 -0
  82. package/dist/heart/daemon/safe-mode.js +161 -0
  83. package/dist/heart/daemon/sense-manager.js +178 -37
  84. package/dist/heart/daemon/session-id-resolver.js +131 -0
  85. package/dist/heart/daemon/skill-management-installer.js +94 -0
  86. package/dist/heart/daemon/socket-client.js +109 -4
  87. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  88. package/dist/heart/daemon/startup-tui.js +264 -0
  89. package/dist/heart/daemon/task-scheduler.js +3 -25
  90. package/dist/heart/daemon/terminal-ui.js +499 -0
  91. package/dist/heart/daemon/thoughts.js +162 -17
  92. package/dist/heart/daemon/up-progress.js +366 -0
  93. package/dist/heart/daemon/vault-items.js +56 -0
  94. package/dist/heart/delegation.js +1 -1
  95. package/dist/heart/habits/habit-migration.js +189 -0
  96. package/dist/heart/habits/habit-parser.js +140 -0
  97. package/dist/heart/habits/habit-runtime-state.js +100 -0
  98. package/dist/heart/habits/habit-scheduler.js +372 -0
  99. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  100. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  101. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  102. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  103. package/dist/heart/identity.js +205 -66
  104. package/dist/heart/kept-notes.js +357 -0
  105. package/dist/heart/kicks.js +1 -1
  106. package/dist/heart/machine-identity.js +161 -0
  107. package/dist/heart/mail-import-discovery.js +353 -0
  108. package/dist/heart/mcp/mcp-server.js +653 -0
  109. package/dist/heart/migrate-config.js +100 -0
  110. package/dist/heart/model-capabilities.js +19 -0
  111. package/dist/heart/outlook/outlook-http-hooks.js +66 -0
  112. package/dist/heart/outlook/outlook-http-response.js +7 -0
  113. package/dist/heart/outlook/outlook-http-routes.js +244 -0
  114. package/dist/heart/outlook/outlook-http-static.js +103 -0
  115. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  116. package/dist/heart/outlook/outlook-http.js +99 -0
  117. package/dist/heart/outlook/outlook-read.js +31 -0
  118. package/dist/heart/outlook/outlook-types.js +27 -0
  119. package/dist/heart/outlook/outlook-view.js +195 -0
  120. package/dist/heart/outlook/readers/agent-machine.js +382 -0
  121. package/dist/heart/outlook/readers/continuity-readers.js +336 -0
  122. package/dist/heart/outlook/readers/mail.js +362 -0
  123. package/dist/heart/outlook/readers/runtime-readers.js +644 -0
  124. package/dist/heart/outlook/readers/sessions.js +232 -0
  125. package/dist/heart/outlook/readers/shared.js +111 -0
  126. package/dist/heart/platform.js +81 -0
  127. package/dist/heart/provider-attempt.js +134 -0
  128. package/dist/heart/provider-binding-resolver.js +255 -0
  129. package/dist/heart/provider-credentials.js +424 -0
  130. package/dist/heart/provider-failover.js +301 -0
  131. package/dist/heart/provider-models.js +81 -0
  132. package/dist/heart/provider-ping.js +262 -0
  133. package/dist/heart/provider-state.js +216 -0
  134. package/dist/heart/provider-visibility.js +188 -0
  135. package/dist/heart/providers/anthropic-token.js +131 -0
  136. package/dist/heart/providers/anthropic.js +139 -52
  137. package/dist/heart/providers/azure.js +97 -13
  138. package/dist/heart/providers/error-classification.js +127 -0
  139. package/dist/heart/providers/github-copilot.js +145 -0
  140. package/dist/heart/providers/minimax-vlm.js +189 -0
  141. package/dist/heart/providers/minimax.js +26 -8
  142. package/dist/heart/providers/openai-codex.js +55 -40
  143. package/dist/heart/runtime-capability-check.js +170 -0
  144. package/dist/heart/runtime-credentials.js +260 -0
  145. package/dist/heart/sense-truth.js +11 -4
  146. package/dist/heart/session-activity.js +43 -22
  147. package/dist/heart/session-events.js +1150 -0
  148. package/dist/heart/session-playback-cli-main.js +5 -0
  149. package/dist/heart/session-playback-cli.js +36 -0
  150. package/dist/heart/session-playback.js +231 -0
  151. package/dist/heart/session-stats-cli-main.js +5 -0
  152. package/dist/heart/session-stats.js +182 -0
  153. package/dist/heart/session-transcript.js +167 -0
  154. package/dist/heart/start-of-turn-packet.js +345 -0
  155. package/dist/heart/streaming.js +44 -27
  156. package/dist/heart/sync.js +332 -0
  157. package/dist/heart/target-resolution.js +127 -0
  158. package/dist/heart/tempo.js +93 -0
  159. package/dist/heart/temporal-view.js +41 -0
  160. package/dist/heart/tool-activity-callbacks.js +36 -0
  161. package/dist/heart/tool-description.js +135 -0
  162. package/dist/heart/tool-friction.js +55 -0
  163. package/dist/heart/tool-loop.js +200 -0
  164. package/dist/heart/turn-context.js +372 -0
  165. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  166. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  167. package/dist/heart/versioning/ouro-path-installer.js +425 -0
  168. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  169. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  170. package/dist/heart/{daemon → versioning}/update-checker.js +5 -1
  171. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  172. package/dist/mailroom/attention.js +167 -0
  173. package/dist/mailroom/autonomy.js +209 -0
  174. package/dist/mailroom/blob-store.js +606 -0
  175. package/dist/mailroom/body-cache.js +61 -0
  176. package/dist/mailroom/core.js +672 -0
  177. package/dist/mailroom/entry.js +160 -0
  178. package/dist/mailroom/file-store.js +426 -0
  179. package/dist/mailroom/mbox-import.js +382 -0
  180. package/dist/mailroom/outbound.js +380 -0
  181. package/dist/mailroom/policy.js +263 -0
  182. package/dist/mailroom/reader.js +219 -0
  183. package/dist/mailroom/search-cache.js +182 -0
  184. package/dist/mailroom/search-relevance.js +319 -0
  185. package/dist/mailroom/smtp-ingress.js +176 -0
  186. package/dist/mailroom/source-state.js +176 -0
  187. package/dist/mailroom/thread.js +109 -0
  188. package/dist/mailroom/travel-extract.js +89 -0
  189. package/dist/mind/bundle-manifest.js +7 -1
  190. package/dist/mind/context.js +165 -101
  191. package/dist/mind/diary-integrity.js +60 -0
  192. package/dist/mind/{memory.js → diary.js} +74 -93
  193. package/dist/mind/embedding-provider.js +60 -0
  194. package/dist/mind/file-state.js +179 -0
  195. package/dist/mind/friends/channel.js +30 -0
  196. package/dist/mind/friends/group-context.js +144 -0
  197. package/dist/mind/friends/resolver.js +54 -2
  198. package/dist/mind/friends/store-file.js +39 -3
  199. package/dist/mind/friends/trust-explanation.js +74 -0
  200. package/dist/mind/friends/types.js +2 -2
  201. package/dist/mind/journal-index.js +161 -0
  202. package/dist/mind/note-search.js +268 -0
  203. package/dist/mind/obligation-steering.js +221 -0
  204. package/dist/mind/pending.js +4 -0
  205. package/dist/mind/prompt-refresh.js +3 -2
  206. package/dist/mind/prompt.js +940 -111
  207. package/dist/mind/provenance-trust.js +26 -0
  208. package/dist/mind/scrutiny.js +173 -0
  209. package/dist/nerves/cli-logging.js +7 -1
  210. package/dist/nerves/coverage/audit-rules.js +15 -6
  211. package/dist/nerves/coverage/audit.js +28 -2
  212. package/dist/nerves/coverage/cli.js +1 -1
  213. package/dist/nerves/coverage/contract.js +5 -5
  214. package/dist/nerves/coverage/file-completeness.js +114 -5
  215. package/dist/nerves/coverage/run-artifacts.js +1 -1
  216. package/dist/nerves/event-buffer.js +111 -0
  217. package/dist/nerves/index.js +224 -4
  218. package/dist/nerves/observation.js +20 -0
  219. package/dist/nerves/redact.js +79 -0
  220. package/dist/nerves/review/cli-main.js +5 -0
  221. package/dist/nerves/review/cli.js +156 -0
  222. package/dist/nerves/review/core.js +152 -0
  223. package/dist/nerves/runtime.js +5 -1
  224. package/dist/outlook-ui/assets/index-BPr5vNuM.css +1 -0
  225. package/dist/outlook-ui/assets/index-Cm51CY9W.js +61 -0
  226. package/dist/outlook-ui/index.html +15 -0
  227. package/dist/repertoire/ado-client.js +15 -56
  228. package/dist/repertoire/ado-semantic.js +11 -10
  229. package/dist/repertoire/api-client.js +97 -0
  230. package/dist/repertoire/bitwarden-store.js +774 -0
  231. package/dist/repertoire/bundle-templates.js +72 -0
  232. package/dist/repertoire/bw-installer.js +180 -0
  233. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  234. package/dist/repertoire/coding/context-pack.js +330 -0
  235. package/dist/repertoire/coding/feedback.js +197 -30
  236. package/dist/repertoire/coding/manager.js +158 -9
  237. package/dist/repertoire/coding/spawner.js +55 -9
  238. package/dist/repertoire/coding/tools.js +170 -7
  239. package/dist/repertoire/commerce-errors.js +109 -0
  240. package/dist/repertoire/commerce-self-test.js +156 -0
  241. package/dist/repertoire/credential-access.js +111 -0
  242. package/dist/repertoire/duffel-client.js +185 -0
  243. package/dist/repertoire/github-client.js +14 -55
  244. package/dist/repertoire/graph-client.js +11 -52
  245. package/dist/repertoire/guardrails.js +396 -0
  246. package/dist/repertoire/mcp-client.js +255 -0
  247. package/dist/repertoire/mcp-manager.js +305 -0
  248. package/dist/repertoire/mcp-tools.js +63 -0
  249. package/dist/repertoire/shell-sessions.js +133 -0
  250. package/dist/repertoire/skills.js +15 -24
  251. package/dist/repertoire/stripe-client.js +131 -0
  252. package/dist/repertoire/tasks/board.js +31 -5
  253. package/dist/repertoire/tasks/fix.js +182 -0
  254. package/dist/repertoire/tasks/index.js +16 -4
  255. package/dist/repertoire/tasks/lifecycle.js +2 -2
  256. package/dist/repertoire/tasks/parser.js +3 -2
  257. package/dist/repertoire/tasks/scanner.js +194 -37
  258. package/dist/repertoire/tasks/transitions.js +16 -78
  259. package/dist/repertoire/tool-results.js +29 -0
  260. package/dist/repertoire/tools-attachments.js +317 -0
  261. package/dist/repertoire/tools-base.js +46 -955
  262. package/dist/repertoire/tools-bluebubbles.js +1 -0
  263. package/dist/repertoire/tools-bridge.js +141 -0
  264. package/dist/repertoire/tools-bundle.js +984 -0
  265. package/dist/repertoire/tools-config.js +185 -0
  266. package/dist/repertoire/tools-continuity.js +248 -0
  267. package/dist/repertoire/tools-credential.js +381 -0
  268. package/dist/repertoire/tools-files.js +342 -0
  269. package/dist/repertoire/tools-flight.js +224 -0
  270. package/dist/repertoire/tools-flow.js +105 -0
  271. package/dist/repertoire/tools-github.js +1 -7
  272. package/dist/repertoire/tools-mail.js +1477 -0
  273. package/dist/repertoire/tools-notes.js +376 -0
  274. package/dist/repertoire/tools-session.js +749 -0
  275. package/dist/repertoire/tools-shell.js +120 -0
  276. package/dist/repertoire/tools-stripe.js +180 -0
  277. package/dist/repertoire/tools-surface.js +243 -0
  278. package/dist/repertoire/tools-teams.js +9 -39
  279. package/dist/repertoire/tools-travel.js +125 -0
  280. package/dist/repertoire/tools-trip.js +422 -0
  281. package/dist/repertoire/tools-user-profile.js +144 -0
  282. package/dist/repertoire/tools-vault.js +40 -0
  283. package/dist/repertoire/tools.js +107 -100
  284. package/dist/repertoire/travel-api-client.js +360 -0
  285. package/dist/repertoire/user-profile.js +131 -0
  286. package/dist/repertoire/vault-setup.js +246 -0
  287. package/dist/repertoire/vault-unlock.js +561 -0
  288. package/dist/scripts/claude-code-hook.js +41 -0
  289. package/dist/scripts/claude-code-stop-hook.js +47 -0
  290. package/dist/senses/attention-queue.js +116 -0
  291. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  292. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  293. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  294. package/dist/senses/bluebubbles/entry.js +73 -0
  295. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  296. package/dist/senses/bluebubbles/index.js +1881 -0
  297. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  298. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  299. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  300. package/dist/senses/bluebubbles/processed-log.js +111 -0
  301. package/dist/senses/bluebubbles/replay.js +129 -0
  302. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +2 -2
  303. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  304. package/dist/senses/cli/bracketed-paste.js +82 -0
  305. package/dist/senses/cli/image-paste.js +287 -0
  306. package/dist/senses/cli/image-ref-navigation.js +75 -0
  307. package/dist/senses/cli/ink-app.js +156 -0
  308. package/dist/senses/cli/inline-diff.js +64 -0
  309. package/dist/senses/cli/input-keys.js +174 -0
  310. package/dist/senses/cli/kill-ring.js +86 -0
  311. package/dist/senses/cli/message-list.js +51 -0
  312. package/dist/senses/cli/ouro-tui.js +605 -0
  313. package/dist/senses/cli/spinner-imperative.js +135 -0
  314. package/dist/senses/cli/spinner.js +101 -0
  315. package/dist/senses/cli/status-line.js +60 -0
  316. package/dist/senses/cli/streaming-markdown.js +526 -0
  317. package/dist/senses/cli/tool-display.js +83 -0
  318. package/dist/senses/cli/tool-render.js +85 -0
  319. package/dist/senses/cli/tui-store.js +240 -0
  320. package/dist/senses/cli/virtual-list.js +35 -0
  321. package/dist/senses/cli-entry.js +60 -8
  322. package/dist/senses/cli-layout.js +187 -0
  323. package/dist/senses/cli.js +511 -209
  324. package/dist/senses/commands.js +66 -3
  325. package/dist/senses/habit-turn-message.js +108 -0
  326. package/dist/senses/inner-dialog-worker.js +175 -21
  327. package/dist/senses/inner-dialog.js +330 -27
  328. package/dist/senses/mail-entry.js +66 -0
  329. package/dist/senses/mail.js +379 -0
  330. package/dist/senses/pipeline.js +573 -164
  331. package/dist/senses/proactive-content-guard.js +51 -0
  332. package/dist/senses/shared-turn.js +248 -0
  333. package/dist/senses/surface-tool.js +68 -0
  334. package/dist/senses/teams-entry.js +60 -8
  335. package/dist/senses/teams.js +405 -170
  336. package/dist/senses/trust-gate.js +100 -5
  337. package/dist/trips/core.js +138 -0
  338. package/dist/trips/store.js +146 -0
  339. package/package.json +37 -7
  340. package/skills/agent-commerce.md +106 -0
  341. package/skills/browser-navigation.md +117 -0
  342. package/skills/commerce-setup-guide.md +116 -0
  343. package/skills/commerce-setup.md +84 -0
  344. package/skills/configure-dev-tools.md +101 -0
  345. package/skills/travel-planning.md +138 -0
  346. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  347. package/dist/heart/daemon/subagent-installer.js +0 -166
  348. package/dist/heart/session-recall.js +0 -116
  349. package/dist/mind/associative-recall.js +0 -209
  350. package/dist/senses/bluebubbles-entry.js +0 -13
  351. package/dist/senses/bluebubbles.js +0 -1142
  352. package/dist/senses/debug-activity.js +0 -148
  353. package/subagents/README.md +0 -86
  354. package/subagents/work-doer.md +0 -237
  355. package/subagents/work-merger.md +0 -618
  356. package/subagents/work-planner.md +0 -390
  357. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  358. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  359. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  360. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  361. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  362. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  363. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  364. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  365. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  366. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  367. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  368. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  369. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  370. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  371. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  372. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -51,15 +51,70 @@ class DaemonProcessManager {
51
51
  now;
52
52
  setTimeoutFn;
53
53
  clearTimeoutFn;
54
+ cooldownRecoveryMs;
55
+ maxCooldownRetries;
56
+ existsSyncFn;
57
+ configCheckFn;
58
+ statusWriterFn;
59
+ onSnapshotChangeFn;
60
+ /**
61
+ * Notify the snapshot-change observer (if registered). Swallows any
62
+ * errors from the observer so process lifecycle code never fails
63
+ * because the observer threw.
64
+ */
65
+ notifySnapshotChange(snapshot) {
66
+ if (!this.onSnapshotChangeFn)
67
+ return;
68
+ try {
69
+ this.onSnapshotChangeFn(snapshot);
70
+ }
71
+ catch (error) {
72
+ (0, runtime_1.emitNervesEvent)({
73
+ level: "warn",
74
+ component: "daemon",
75
+ event: "daemon.snapshot_change_observer_error",
76
+ message: "snapshot-change observer threw",
77
+ meta: {
78
+ agent: snapshot.name,
79
+ error: error instanceof Error ? error.message : /* v8 ignore next -- defensive: non-Error catch branch @preserve */ String(error),
80
+ },
81
+ });
82
+ }
83
+ }
84
+ writeStatus(agent, text) {
85
+ try {
86
+ this.statusWriterFn(text);
87
+ }
88
+ catch (error) {
89
+ (0, runtime_1.emitNervesEvent)({
90
+ level: "warn",
91
+ component: "daemon",
92
+ event: "daemon.status_writer_error",
93
+ message: "daemon status writer threw",
94
+ meta: {
95
+ agent,
96
+ error: error instanceof Error ? error.message : String(error),
97
+ },
98
+ });
99
+ }
100
+ }
54
101
  constructor(options) {
55
102
  this.maxRestartsPerHour = options.maxRestartsPerHour ?? 10;
56
103
  this.stabilityThresholdMs = options.stabilityThresholdMs ?? 60_000;
57
104
  this.initialBackoffMs = options.initialBackoffMs ?? 1_000;
58
105
  this.maxBackoffMs = options.maxBackoffMs ?? 60_000;
106
+ this.cooldownRecoveryMs = options.cooldownRecoveryMs ?? 5 * 60 * 1_000;
107
+ this.maxCooldownRetries = options.maxCooldownRetries ?? 3;
59
108
  this.spawnFn = options.spawn ?? ((command, args, spawnOptions) => (0, child_process_1.spawn)(command, args, spawnOptions));
60
109
  this.now = options.now ?? (() => Date.now());
61
110
  this.setTimeoutFn = options.setTimeoutFn ?? ((cb, delay) => setTimeout(cb, delay));
62
111
  this.clearTimeoutFn = options.clearTimeoutFn ?? ((timer) => clearTimeout(timer));
112
+ this.existsSyncFn = options.existsSync ?? null;
113
+ this.configCheckFn = options.configCheck ?? null;
114
+ this.statusWriterFn = options.statusWriter ?? ((text) => {
115
+ process.stderr.write(text);
116
+ });
117
+ this.onSnapshotChangeFn = options.onSnapshotChange ?? null;
63
118
  for (const agent of options.agents) {
64
119
  this.agents.set(agent.name, {
65
120
  config: agent,
@@ -67,6 +122,9 @@ class DaemonProcessManager {
67
122
  restartTimer: null,
68
123
  crashTimestamps: [],
69
124
  stopRequested: false,
125
+ cooldownTimer: null,
126
+ cooldownRetryCount: 0,
127
+ fastCrashCount: 0,
70
128
  snapshot: {
71
129
  name: agent.name,
72
130
  channel: agent.channel,
@@ -76,6 +134,10 @@ class DaemonProcessManager {
76
134
  startedAt: null,
77
135
  lastCrashAt: null,
78
136
  backoffMs: this.initialBackoffMs,
137
+ lastExitCode: null,
138
+ lastSignal: null,
139
+ errorReason: null,
140
+ fixHint: null,
79
141
  },
80
142
  });
81
143
  }
@@ -94,14 +156,75 @@ class DaemonProcessManager {
94
156
  this.clearRestartTimer(state);
95
157
  state.stopRequested = false;
96
158
  state.snapshot.status = "starting";
159
+ if (this.configCheckFn) {
160
+ const result = await this.configCheckFn(agent);
161
+ if (result.skip) {
162
+ state.snapshot.status = "stopped";
163
+ state.snapshot.errorReason = null;
164
+ state.snapshot.fixHint = null;
165
+ (0, runtime_1.emitNervesEvent)({
166
+ component: "daemon",
167
+ event: "daemon.agent_config_skipped",
168
+ message: result.error ?? "agent start skipped by config check",
169
+ meta: { agent, fix: result.fix ?? null },
170
+ });
171
+ this.notifySnapshotChange(state.snapshot);
172
+ return;
173
+ }
174
+ if (!result.ok) {
175
+ state.snapshot.status = "crashed";
176
+ // Surface the error and fix to the snapshot so sibling agents can
177
+ // read it via the pulse. Without this, the diagnosis stayed
178
+ // trapped in the nerves event and stderr — visible to humans
179
+ // running `ouro status` or grepping logs, but invisible to
180
+ // peer agents trying to coordinate around the broken state.
181
+ state.snapshot.errorReason = result.error ?? "agent config validation failed";
182
+ state.snapshot.fixHint = result.fix ?? null;
183
+ (0, runtime_1.emitNervesEvent)({
184
+ level: "error",
185
+ component: "daemon",
186
+ event: "daemon.agent_config_invalid",
187
+ message: result.error ?? "agent config validation failed",
188
+ meta: { agent, fix: result.fix ?? null },
189
+ });
190
+ this.writeStatus(agent, `[daemon] ${agent}: ${result.error}\n` +
191
+ (result.fix ? ` Fix: ${result.fix}\n` : ""));
192
+ this.notifySnapshotChange(state.snapshot);
193
+ return;
194
+ }
195
+ // Config check passed — clear any prior error so the pulse stops
196
+ // reporting the broken state. This is the recovery path: the user
197
+ // fixed their secrets/config, the next startAgent attempt sees a
198
+ // valid config, and the pulse goes quiet.
199
+ state.snapshot.errorReason = null;
200
+ state.snapshot.fixHint = null;
201
+ }
97
202
  const runCwd = (0, identity_1.getRepoRoot)();
98
203
  const entryScript = path.join((0, identity_1.getRepoRoot)(), "dist", state.config.entry);
204
+ if (this.existsSyncFn && !this.existsSyncFn(entryScript)) {
205
+ state.snapshot.status = "crashed";
206
+ (0, runtime_1.emitNervesEvent)({
207
+ level: "error",
208
+ component: "daemon",
209
+ event: "daemon.agent_entry_missing",
210
+ message: "agent entry script does not exist — cannot spawn. Run 'ouro daemon install' from the correct location.",
211
+ meta: { agent, entryScript },
212
+ });
213
+ this.notifySnapshotChange(state.snapshot);
214
+ return;
215
+ }
99
216
  const args = [entryScript, "--agent", state.config.agentArg ?? agent, ...(state.config.args ?? [])];
100
217
  const child = this.spawnFn("node", args, {
101
218
  cwd: runCwd,
102
219
  env: state.config.env ? { ...process.env, ...state.config.env } : process.env,
103
220
  stdio: ["ignore", "ignore", "ignore", "ipc"],
104
221
  });
222
+ /* v8 ignore next 7 -- defensive: spawn should always return a ChildProcess @preserve */
223
+ if (!child) {
224
+ state.snapshot.status = "crashed";
225
+ (0, runtime_1.emitNervesEvent)({ level: "error", component: "daemon", event: "daemon.agent_spawn_failed", message: "spawn returned null", meta: { agent } });
226
+ return;
227
+ }
105
228
  state.process = child;
106
229
  state.snapshot.status = "running";
107
230
  state.snapshot.pid = child.pid ?? null;
@@ -112,6 +235,18 @@ class DaemonProcessManager {
112
235
  message: "daemon started managed agent process",
113
236
  meta: { agent, pid: child.pid ?? null, cwd: runCwd },
114
237
  });
238
+ this.notifySnapshotChange(state.snapshot);
239
+ /* v8 ignore start — child process error handler; requires real spawn to trigger */
240
+ child.on("error", (err) => {
241
+ (0, runtime_1.emitNervesEvent)({
242
+ level: "warn",
243
+ component: "daemon",
244
+ event: "daemon.agent_process_error",
245
+ message: "managed agent process emitted error",
246
+ meta: { agent, error: err.message },
247
+ });
248
+ });
249
+ /* v8 ignore stop */
115
250
  child.once("exit", (code, signal) => {
116
251
  this.onExit(state, code, signal);
117
252
  });
@@ -119,10 +254,12 @@ class DaemonProcessManager {
119
254
  async stopAgent(agent) {
120
255
  const state = this.requireAgent(agent);
121
256
  this.clearRestartTimer(state);
257
+ this.clearCooldownTimer(state);
122
258
  state.stopRequested = true;
123
259
  if (!state.process) {
124
260
  state.snapshot.status = "stopped";
125
261
  state.snapshot.pid = null;
262
+ this.notifySnapshotChange(state.snapshot);
126
263
  return;
127
264
  }
128
265
  const child = state.process;
@@ -141,6 +278,7 @@ class DaemonProcessManager {
141
278
  meta: { agent },
142
279
  });
143
280
  }
281
+ this.notifySnapshotChange(state.snapshot);
144
282
  }
145
283
  async restartAgent(agent) {
146
284
  await this.stopAgent(agent);
@@ -179,6 +317,8 @@ class DaemonProcessManager {
179
317
  return;
180
318
  state.process = null;
181
319
  state.snapshot.pid = null;
320
+ state.snapshot.lastExitCode = code;
321
+ state.snapshot.lastSignal = signal;
182
322
  const crashed = !state.stopRequested && code !== 0;
183
323
  const now = this.now();
184
324
  const startedAt = state.snapshot.startedAt ? Date.parse(state.snapshot.startedAt) : now;
@@ -195,13 +335,45 @@ class DaemonProcessManager {
195
335
  if (runDuration >= this.stabilityThresholdMs) {
196
336
  state.snapshot.backoffMs = this.initialBackoffMs;
197
337
  }
338
+ this.notifySnapshotChange(state.snapshot);
198
339
  return;
199
340
  }
200
341
  state.snapshot.lastCrashAt = new Date(now).toISOString();
342
+ // Fast-crash detection: if the agent dies within 5 seconds of starting, it's likely
343
+ // a configuration issue (missing credentials, bad provider, etc.) not a transient failure.
344
+ // After 3 consecutive fast crashes, stop retrying and mark as config-failed.
345
+ const FAST_CRASH_THRESHOLD_MS = 5000;
346
+ const FAST_CRASH_MAX = 3;
347
+ if (runDuration < FAST_CRASH_THRESHOLD_MS) {
348
+ state.fastCrashCount = state.fastCrashCount + 1;
349
+ if (state.fastCrashCount >= FAST_CRASH_MAX) {
350
+ state.snapshot.status = "crashed";
351
+ // Capture the fast-crash diagnosis on the snapshot so it surfaces
352
+ // via the pulse. The error message is prescriptive: it tells the
353
+ // user (and their sibling agents) exactly what to do.
354
+ state.snapshot.errorReason = `agent crashed ${FAST_CRASH_MAX} times within ${FAST_CRASH_THRESHOLD_MS}ms of startup — likely a configuration issue (missing credentials, bad provider).`;
355
+ state.snapshot.fixHint = `Fix the config and run \`ouro up\` to restart, or check daemon logs for the underlying error.`;
356
+ (0, runtime_1.emitNervesEvent)({
357
+ level: "error",
358
+ component: "daemon",
359
+ event: "daemon.agent_config_failure",
360
+ message: `agent crashed ${FAST_CRASH_MAX} times within ${FAST_CRASH_THRESHOLD_MS}ms of startup — likely a configuration issue (missing credentials, bad provider). Not retrying. Fix the config and run \`ouro up\` to restart.`,
361
+ meta: { agent: state.config.name, fastCrashCount: state.fastCrashCount, avgRunDurationMs: runDuration },
362
+ });
363
+ this.notifySnapshotChange(state.snapshot);
364
+ return; // Don't schedule cooldown recovery — this needs human/agent intervention
365
+ }
366
+ }
367
+ else {
368
+ // Reset fast-crash counter on a stable run
369
+ state.fastCrashCount = 0;
370
+ }
201
371
  state.crashTimestamps = state.crashTimestamps.filter((crashTs) => crashTs >= startOfHour(now));
202
372
  state.crashTimestamps.push(now);
203
373
  if (state.crashTimestamps.length > this.maxRestartsPerHour) {
204
374
  state.snapshot.status = "crashed";
375
+ state.snapshot.errorReason = `agent exceeded restart limit (${this.maxRestartsPerHour}/hr) — entering cooldown`;
376
+ state.snapshot.fixHint = "investigate why the agent keeps crashing; cooldown will retry shortly";
205
377
  (0, runtime_1.emitNervesEvent)({
206
378
  level: "error",
207
379
  component: "daemon",
@@ -209,6 +381,8 @@ class DaemonProcessManager {
209
381
  message: "managed agent exceeded restart limit and is marked crashed",
210
382
  meta: { agent: state.config.name, maxRestartsPerHour: this.maxRestartsPerHour },
211
383
  });
384
+ this.notifySnapshotChange(state.snapshot);
385
+ this.scheduleCooldownRecovery(state);
212
386
  return;
213
387
  }
214
388
  state.snapshot.status = "starting";
@@ -219,6 +393,7 @@ class DaemonProcessManager {
219
393
  state.restartTimer = this.setTimeoutFn(() => {
220
394
  void this.startAgent(state.config.name);
221
395
  }, waitMs);
396
+ this.notifySnapshotChange(state.snapshot);
222
397
  }
223
398
  clearRestartTimer(state) {
224
399
  if (state.restartTimer === null)
@@ -226,6 +401,45 @@ class DaemonProcessManager {
226
401
  this.clearTimeoutFn(state.restartTimer);
227
402
  state.restartTimer = null;
228
403
  }
404
+ scheduleCooldownRecovery(state) {
405
+ if (state.cooldownRetryCount >= this.maxCooldownRetries) {
406
+ (0, runtime_1.emitNervesEvent)({
407
+ level: "error",
408
+ component: "daemon",
409
+ event: "daemon.agent_permanent_failure",
410
+ message: "managed agent exhausted all cooldown retries — permanently stopped",
411
+ meta: { agent: state.config.name, cooldownRetryCount: state.cooldownRetryCount, maxCooldownRetries: this.maxCooldownRetries },
412
+ });
413
+ return;
414
+ }
415
+ this.clearCooldownTimer(state);
416
+ state.cooldownTimer = this.setTimeoutFn(() => {
417
+ state.cooldownRetryCount += 1;
418
+ state.crashTimestamps = [];
419
+ state.snapshot.backoffMs = this.initialBackoffMs;
420
+ state.snapshot.status = "starting";
421
+ state.snapshot.restartCount += 1;
422
+ (0, runtime_1.emitNervesEvent)({
423
+ component: "daemon",
424
+ event: "daemon.agent_cooldown_recovery",
425
+ message: "attempting cooldown recovery for managed agent",
426
+ meta: { agent: state.config.name, cooldownRetryCount: state.cooldownRetryCount },
427
+ });
428
+ void this.startAgent(state.config.name);
429
+ }, this.cooldownRecoveryMs);
430
+ (0, runtime_1.emitNervesEvent)({
431
+ component: "daemon",
432
+ event: "daemon.agent_cooldown_scheduled",
433
+ message: `scheduled cooldown recovery in ${this.cooldownRecoveryMs}ms`,
434
+ meta: { agent: state.config.name, cooldownRecoveryMs: this.cooldownRecoveryMs, cooldownRetryCount: state.cooldownRetryCount },
435
+ });
436
+ }
437
+ clearCooldownTimer(state) {
438
+ if (state.cooldownTimer === null)
439
+ return;
440
+ this.clearTimeoutFn(state.cooldownTimer);
441
+ state.cooldownTimer = null;
442
+ }
229
443
  requireAgent(agent) {
230
444
  const state = this.agents.get(agent);
231
445
  if (!state) {
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ /**
3
+ * Shared provider discovery for repair.
4
+ *
5
+ * Runtime repair only trusts the agent vault. First-run conveniences may still
6
+ * inspect env vars before credentials are stored, but once an agent exists the
7
+ * vault is the source of truth.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.scanEnvVarCredentials = scanEnvVarCredentials;
11
+ exports.discoverInstalledAgentCredentials = discoverInstalledAgentCredentials;
12
+ exports.describeDiscoveredCredentialSource = describeDiscoveredCredentialSource;
13
+ exports.discoverWorkingProvider = discoverWorkingProvider;
14
+ const identity_1 = require("../identity");
15
+ const provider_credentials_1 = require("../provider-credentials");
16
+ const runtime_1 = require("../../nerves/runtime");
17
+ /**
18
+ * Scan environment variables for API keys during first-run bootstrap.
19
+ * This does not participate in runtime provider repair.
20
+ */
21
+ function scanEnvVarCredentials(env) {
22
+ const results = [];
23
+ for (const [provider, desc] of Object.entries(identity_1.PROVIDER_CREDENTIALS)) {
24
+ const cred = {};
25
+ for (const [envVar, credKey] of Object.entries(desc.envVars)) {
26
+ const value = env[envVar];
27
+ if (value) {
28
+ cred[credKey] = value;
29
+ }
30
+ }
31
+ const hasRequired = desc.required.some((key) => !!cred[key]);
32
+ if (hasRequired) {
33
+ results.push({
34
+ provider,
35
+ agentName: "env",
36
+ credentials: cred,
37
+ providerConfig: { ...cred },
38
+ });
39
+ }
40
+ }
41
+ return results;
42
+ }
43
+ function stringifyProviderFields(fields) {
44
+ const result = {};
45
+ for (const [key, value] of Object.entries(fields)) {
46
+ result[key] = String(value);
47
+ }
48
+ return result;
49
+ }
50
+ function discoveredFromVaultRecord(record, agentName = "vault") {
51
+ return {
52
+ provider: record.provider,
53
+ agentName,
54
+ credentials: stringifyProviderFields(record.credentials),
55
+ providerConfig: stringifyProviderFields(record.config),
56
+ };
57
+ }
58
+ async function discoverInstalledAgentCredentials(agentNames) {
59
+ const discovered = [];
60
+ for (const agentName of agentNames) {
61
+ if (agentName === "SerpentGuide")
62
+ continue;
63
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName, { preserveCachedOnFailure: true });
64
+ if (!poolResult.ok)
65
+ continue;
66
+ for (const record of Object.values(poolResult.pool.providers)) {
67
+ if (!record)
68
+ continue;
69
+ discovered.push(discoveredFromVaultRecord(record, agentName));
70
+ }
71
+ }
72
+ return discovered;
73
+ }
74
+ function describeDiscoveredCredentialSource(credential, envVar) {
75
+ if (credential.agentName === "env") {
76
+ return envVar ? `from env: $${envVar}` : "from env";
77
+ }
78
+ return `from ${credential.agentName}'s vault`;
79
+ }
80
+ async function discoverWorkingProvider(deps) {
81
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(deps.agentName);
82
+ if (!poolResult.ok) {
83
+ (0, runtime_1.emitNervesEvent)({
84
+ level: "warn",
85
+ component: "daemon",
86
+ event: "daemon.provider_discovery_none",
87
+ message: "provider discovery could not read agent vault",
88
+ meta: { agentName: deps.agentName, reason: poolResult.reason },
89
+ });
90
+ return null;
91
+ }
92
+ const candidates = Object.entries(poolResult.pool.providers)
93
+ .map(([, record]) => discoveredFromVaultRecord(record));
94
+ if (candidates.length === 0) {
95
+ (0, runtime_1.emitNervesEvent)({
96
+ level: "info",
97
+ component: "daemon",
98
+ event: "daemon.provider_discovery_none",
99
+ message: "no provider credentials found in agent vault",
100
+ meta: { agentName: deps.agentName },
101
+ });
102
+ return null;
103
+ }
104
+ for (const candidate of candidates) {
105
+ const config = { ...candidate.providerConfig, ...candidate.credentials };
106
+ (0, runtime_1.emitNervesEvent)({
107
+ level: "info",
108
+ component: "daemon",
109
+ event: "daemon.provider_discovery_ping",
110
+ message: `pinging provider: ${candidate.provider}`,
111
+ meta: { agentName: deps.agentName, provider: candidate.provider, source: candidate.agentName },
112
+ });
113
+ const result = await deps.pingProvider(candidate.provider, config);
114
+ if (result.ok) {
115
+ (0, runtime_1.emitNervesEvent)({
116
+ level: "info",
117
+ component: "daemon",
118
+ event: "daemon.provider_discovery_ok",
119
+ message: `provider discovery succeeded: ${candidate.provider}`,
120
+ meta: { agentName: deps.agentName, provider: candidate.provider, source: candidate.agentName },
121
+ });
122
+ return {
123
+ provider: candidate.provider,
124
+ credentials: candidate.credentials,
125
+ providerConfig: candidate.providerConfig,
126
+ };
127
+ }
128
+ }
129
+ (0, runtime_1.emitNervesEvent)({
130
+ level: "warn",
131
+ component: "daemon",
132
+ event: "daemon.provider_discovery_all_failed",
133
+ message: "all vault provider candidates failed ping",
134
+ meta: { agentName: deps.agentName, candidateCount: candidates.length },
135
+ });
136
+ return null;
137
+ }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatProviderAttemptProgress = formatProviderAttemptProgress;
4
+ exports.formatProviderRetryProgress = formatProviderRetryProgress;
5
+ exports.createProviderPingProgressReporter = createProviderPingProgressReporter;
6
+ const runtime_1 = require("../../nerves/runtime");
7
+ function formatProviderPingLabel(context) {
8
+ return context.model ? `${context.provider} / ${context.model}` : context.provider;
9
+ }
10
+ function providerRetryReason(record) {
11
+ switch (record.classification) {
12
+ case "auth-failure":
13
+ return "credentials were rejected";
14
+ case "usage-limit":
15
+ return "usage limit hit";
16
+ case "rate-limit":
17
+ return "provider asked us to slow down";
18
+ case "server-error":
19
+ return record.httpStatus === 529 ? "provider is busy right now" : "provider is having trouble right now";
20
+ case "network-error":
21
+ return "network connection dropped";
22
+ case "unknown":
23
+ return "last check failed";
24
+ default:
25
+ return "last check failed";
26
+ }
27
+ }
28
+ function providerRetryTiming(delayMs) {
29
+ if (!delayMs || delayMs <= 0)
30
+ return "now";
31
+ const seconds = delayMs / 1000;
32
+ const rounded = Number.isInteger(seconds) ? `${seconds.toFixed(0)}s` : `${seconds.toFixed(1).replace(/\.0$/, "")}s`;
33
+ return `in ${rounded}`;
34
+ }
35
+ function formatProviderAttemptProgress(context, attempt, maxAttempts) {
36
+ const prefix = context.subject ? `${context.subject}: ` : "";
37
+ if (maxAttempts <= 1)
38
+ return `${prefix}checking ${formatProviderPingLabel(context)}...`;
39
+ return `${prefix}checking ${formatProviderPingLabel(context)} (attempt ${attempt} of ${maxAttempts})...`;
40
+ }
41
+ function formatProviderRetryProgress(context, record, maxAttempts) {
42
+ const nextAttempt = Math.min(record.attempt + 1, maxAttempts);
43
+ const retryDetail = `${providerRetryReason(record)}; retrying ${providerRetryTiming(record.delayMs)} (attempt ${nextAttempt} of ${maxAttempts})`;
44
+ if (context.subject) {
45
+ return `${context.subject}: ${retryDetail} while checking ${formatProviderPingLabel(context)}`;
46
+ }
47
+ return `${formatProviderPingLabel(record)}: ${retryDetail}`;
48
+ }
49
+ function createProviderPingProgressReporter(context, onProgress) {
50
+ return {
51
+ onAttemptStart: async (attempt, maxAttempts) => {
52
+ (0, runtime_1.emitNervesEvent)({
53
+ component: "daemon",
54
+ event: "daemon.provider_ping_progress_reported",
55
+ message: "reported provider ping attempt progress",
56
+ meta: {
57
+ provider: context.provider,
58
+ model: context.model ?? null,
59
+ kind: "attempt",
60
+ attempt,
61
+ maxAttempts,
62
+ },
63
+ });
64
+ onProgress(formatProviderAttemptProgress(context, attempt, maxAttempts));
65
+ },
66
+ onRetry: async (record, maxAttempts) => {
67
+ (0, runtime_1.emitNervesEvent)({
68
+ component: "daemon",
69
+ event: "daemon.provider_ping_progress_reported",
70
+ message: "reported provider ping retry progress",
71
+ meta: {
72
+ provider: record.provider,
73
+ model: record.model,
74
+ kind: "retry",
75
+ attempt: record.attempt,
76
+ maxAttempts,
77
+ classification: record.classification ?? "unknown",
78
+ },
79
+ });
80
+ onProgress(formatProviderRetryProgress(context, record, maxAttempts));
81
+ },
82
+ };
83
+ }