@ouro.bot/cli 0.1.0-alpha.55 → 0.1.0-alpha.550

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 (386) hide show
  1. package/README.md +133 -19
  2. package/RepairGuide.ouro/agent.json +5 -0
  3. package/RepairGuide.ouro/psyche/IDENTITY.md +19 -0
  4. package/RepairGuide.ouro/psyche/SOUL.md +55 -0
  5. package/RepairGuide.ouro/skills/diagnose-bootstrap-drift.md +54 -0
  6. package/RepairGuide.ouro/skills/diagnose-broken-remote.md +63 -0
  7. package/RepairGuide.ouro/skills/diagnose-stacked-typed-issues.md +35 -0
  8. package/RepairGuide.ouro/skills/diagnose-sync-blocked.md +54 -0
  9. package/RepairGuide.ouro/skills/diagnose-vault-expired.md +60 -0
  10. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +4 -2
  11. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +2 -2
  12. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  13. package/changelog.json +3555 -0
  14. package/dist/arc/attention-types.js +8 -0
  15. package/dist/arc/cares.js +140 -0
  16. package/dist/arc/episodes.js +117 -0
  17. package/dist/arc/intentions.js +133 -0
  18. package/dist/arc/json-store.js +117 -0
  19. package/dist/arc/obligations.js +237 -0
  20. package/dist/arc/packets.js +193 -0
  21. package/dist/arc/presence.js +185 -0
  22. package/dist/arc/task-lifecycle.js +65 -0
  23. package/dist/heart/active-work.js +837 -26
  24. package/dist/heart/agent-entry.js +58 -3
  25. package/dist/heart/attachments/image-normalize.js +194 -0
  26. package/dist/heart/attachments/materialize.js +97 -0
  27. package/dist/heart/attachments/originals.js +88 -0
  28. package/dist/heart/attachments/render.js +29 -0
  29. package/dist/heart/attachments/sources/adapter.js +2 -0
  30. package/dist/heart/attachments/sources/bluebubbles.js +156 -0
  31. package/dist/heart/attachments/sources/cli-local-file.js +78 -0
  32. package/dist/heart/attachments/sources/index.js +16 -0
  33. package/dist/heart/attachments/store.js +103 -0
  34. package/dist/heart/attachments/types.js +93 -0
  35. package/dist/heart/auth/auth-flow.js +479 -0
  36. package/dist/heart/background-operations.js +281 -0
  37. package/dist/heart/bundle-state.js +168 -0
  38. package/dist/heart/commitments.js +111 -0
  39. package/dist/heart/config-registry.js +304 -0
  40. package/dist/heart/config.js +114 -118
  41. package/dist/heart/core.js +925 -246
  42. package/dist/heart/cross-chat-delivery.js +3 -18
  43. package/dist/heart/daemon/agent-config-check.js +512 -0
  44. package/dist/heart/daemon/agent-discovery.js +102 -3
  45. package/dist/heart/daemon/agent-service.js +522 -0
  46. package/dist/heart/daemon/agentic-repair.js +554 -0
  47. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  48. package/dist/heart/daemon/boot-sync-probe.js +197 -0
  49. package/dist/heart/daemon/cadence.js +70 -0
  50. package/dist/heart/daemon/cli-defaults.js +665 -0
  51. package/dist/heart/daemon/cli-exec.js +7565 -0
  52. package/dist/heart/daemon/cli-help.js +498 -0
  53. package/dist/heart/daemon/cli-parse.js +1590 -0
  54. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  55. package/dist/heart/daemon/cli-render.js +775 -0
  56. package/dist/heart/daemon/cli-types.js +8 -0
  57. package/dist/heart/daemon/connect-bay.js +323 -0
  58. package/dist/heart/daemon/daemon-cli.js +29 -1672
  59. package/dist/heart/daemon/daemon-entry.js +417 -2
  60. package/dist/heart/daemon/daemon-health.js +183 -0
  61. package/dist/heart/daemon/daemon-rollup.js +58 -0
  62. package/dist/heart/daemon/daemon-runtime-sync.js +87 -13
  63. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  64. package/dist/heart/daemon/daemon.js +758 -71
  65. package/dist/heart/daemon/dns-workflow.js +394 -0
  66. package/dist/heart/daemon/doctor-types.js +8 -0
  67. package/dist/heart/daemon/doctor.js +844 -0
  68. package/dist/heart/daemon/drift-detection.js +146 -0
  69. package/dist/heart/daemon/health-monitor.js +122 -1
  70. package/dist/heart/daemon/hooks/agent-config-v2.js +33 -0
  71. package/dist/heart/daemon/hooks/bundle-meta.js +115 -1
  72. package/dist/heart/daemon/http-health-probe.js +80 -0
  73. package/dist/heart/daemon/human-command-screens.js +234 -0
  74. package/dist/heart/daemon/human-readiness.js +114 -0
  75. package/dist/heart/daemon/inner-status.js +102 -0
  76. package/dist/heart/daemon/interactive-repair.js +394 -0
  77. package/dist/heart/daemon/launchd.js +37 -8
  78. package/dist/heart/daemon/log-tailer.js +82 -12
  79. package/dist/heart/daemon/logs-prune.js +110 -0
  80. package/dist/heart/daemon/mcp-canary.js +297 -0
  81. package/dist/heart/daemon/message-router.js +2 -2
  82. package/dist/heart/daemon/os-cron-deps.js +135 -0
  83. package/dist/heart/daemon/os-cron.js +14 -12
  84. package/dist/heart/daemon/ouro-bot-entry.js +4 -2
  85. package/dist/heart/daemon/ouro-entry.js +3 -1
  86. package/dist/heart/daemon/process-manager.js +375 -33
  87. package/dist/heart/daemon/provider-discovery.js +137 -0
  88. package/dist/heart/daemon/provider-ping-progress.js +83 -0
  89. package/dist/heart/daemon/pulse.js +475 -0
  90. package/dist/heart/daemon/readiness-repair.js +365 -0
  91. package/dist/heart/daemon/run-hooks.js +2 -0
  92. package/dist/heart/daemon/runtime-logging.js +67 -16
  93. package/dist/heart/daemon/runtime-metadata.js +3 -31
  94. package/dist/heart/daemon/safe-mode.js +161 -0
  95. package/dist/heart/daemon/sense-manager.js +353 -38
  96. package/dist/heart/daemon/session-id-resolver.js +131 -0
  97. package/dist/heart/daemon/skill-management-installer.js +94 -0
  98. package/dist/heart/daemon/socket-client.js +158 -11
  99. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  100. package/dist/heart/daemon/startup-tui.js +330 -0
  101. package/dist/heart/daemon/task-scheduler.js +3 -25
  102. package/dist/heart/daemon/terminal-ui.js +499 -0
  103. package/dist/heart/daemon/thoughts.js +162 -17
  104. package/dist/heart/daemon/up-progress.js +366 -0
  105. package/dist/heart/daemon/vault-items.js +56 -0
  106. package/dist/heart/delegation.js +1 -1
  107. package/dist/heart/habits/habit-migration.js +189 -0
  108. package/dist/heart/habits/habit-parser.js +140 -0
  109. package/dist/heart/habits/habit-runtime-state.js +100 -0
  110. package/dist/heart/habits/habit-scheduler.js +372 -0
  111. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -117
  112. package/dist/heart/{daemon → hatch}/hatch-specialist.js +6 -8
  113. package/dist/heart/{daemon → hatch}/specialist-prompt.js +12 -9
  114. package/dist/heart/{daemon → hatch}/specialist-tools.js +35 -12
  115. package/dist/heart/identity.js +200 -51
  116. package/dist/heart/kept-notes.js +357 -0
  117. package/dist/heart/kicks.js +1 -1
  118. package/dist/heart/machine-identity.js +161 -0
  119. package/dist/heart/mail-import-discovery.js +353 -0
  120. package/dist/heart/mailbox/mailbox-http-hooks.js +66 -0
  121. package/dist/heart/mailbox/mailbox-http-response.js +7 -0
  122. package/dist/heart/mailbox/mailbox-http-routes.js +246 -0
  123. package/dist/heart/mailbox/mailbox-http-static.js +103 -0
  124. package/dist/heart/mailbox/mailbox-http-transport.js +116 -0
  125. package/dist/heart/mailbox/mailbox-http.js +99 -0
  126. package/dist/heart/mailbox/mailbox-read.js +31 -0
  127. package/dist/heart/mailbox/mailbox-types.js +27 -0
  128. package/dist/heart/mailbox/mailbox-view.js +195 -0
  129. package/dist/heart/mailbox/readers/agent-machine.js +382 -0
  130. package/dist/heart/mailbox/readers/continuity-readers.js +338 -0
  131. package/dist/heart/mailbox/readers/mail.js +362 -0
  132. package/dist/heart/mailbox/readers/runtime-readers.js +651 -0
  133. package/dist/heart/mailbox/readers/sessions.js +232 -0
  134. package/dist/heart/mailbox/readers/shared.js +111 -0
  135. package/dist/heart/mcp/mcp-server.js +683 -0
  136. package/dist/heart/migrate-config.js +100 -0
  137. package/dist/heart/model-capabilities.js +19 -0
  138. package/dist/heart/platform.js +81 -0
  139. package/dist/heart/provider-attempt.js +134 -0
  140. package/dist/heart/provider-binding-resolver.js +255 -0
  141. package/dist/heart/provider-credentials.js +425 -0
  142. package/dist/heart/provider-failover.js +301 -0
  143. package/dist/heart/provider-models.js +81 -0
  144. package/dist/heart/provider-ping.js +262 -0
  145. package/dist/heart/provider-state.js +216 -0
  146. package/dist/heart/provider-visibility.js +188 -0
  147. package/dist/heart/providers/anthropic-token.js +131 -0
  148. package/dist/heart/providers/anthropic.js +139 -52
  149. package/dist/heart/providers/azure.js +97 -13
  150. package/dist/heart/providers/error-classification.js +127 -0
  151. package/dist/heart/providers/github-copilot.js +145 -0
  152. package/dist/heart/providers/minimax-vlm.js +189 -0
  153. package/dist/heart/providers/minimax.js +26 -8
  154. package/dist/heart/providers/openai-codex.js +55 -40
  155. package/dist/heart/runtime-capability-check.js +170 -0
  156. package/dist/heart/runtime-credentials.js +367 -0
  157. package/dist/heart/runtime-cwd.js +87 -0
  158. package/dist/heart/sense-truth.js +11 -4
  159. package/dist/heart/session-activity.js +43 -22
  160. package/dist/heart/session-events.js +1149 -0
  161. package/dist/heart/session-playback-cli-main.js +5 -0
  162. package/dist/heart/session-playback-cli.js +36 -0
  163. package/dist/heart/session-playback.js +231 -0
  164. package/dist/heart/session-stats-cli-main.js +5 -0
  165. package/dist/heart/session-stats.js +182 -0
  166. package/dist/heart/session-transcript.js +243 -0
  167. package/dist/heart/start-of-turn-packet.js +345 -0
  168. package/dist/heart/streaming.js +44 -27
  169. package/dist/heart/sync-classification.js +176 -0
  170. package/dist/heart/sync.js +449 -0
  171. package/dist/heart/target-resolution.js +9 -5
  172. package/dist/heart/tempo.js +93 -0
  173. package/dist/heart/temporal-view.js +41 -0
  174. package/dist/heart/timeouts.js +101 -0
  175. package/dist/heart/tool-activity-callbacks.js +59 -0
  176. package/dist/heart/tool-description.js +139 -0
  177. package/dist/heart/tool-friction.js +55 -0
  178. package/dist/heart/tool-loop.js +200 -0
  179. package/dist/heart/turn-context.js +381 -0
  180. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +6 -5
  181. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  182. package/dist/heart/versioning/ouro-path-installer.js +426 -0
  183. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  184. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  185. package/dist/heart/{daemon → versioning}/update-checker.js +6 -1
  186. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  187. package/dist/mailbox-ui/assets/index-BPr5vNuM.css +1 -0
  188. package/dist/mailbox-ui/assets/index-Cm51CY9W.js +61 -0
  189. package/dist/mailbox-ui/index.html +15 -0
  190. package/dist/mailroom/attention.js +167 -0
  191. package/dist/mailroom/autonomy.js +209 -0
  192. package/dist/mailroom/blob-store.js +674 -0
  193. package/dist/mailroom/body-cache.js +61 -0
  194. package/dist/mailroom/core.js +720 -0
  195. package/dist/mailroom/entry.js +160 -0
  196. package/dist/mailroom/file-store.js +430 -0
  197. package/dist/mailroom/mbox-import.js +383 -0
  198. package/dist/mailroom/outbound.js +380 -0
  199. package/dist/mailroom/policy.js +263 -0
  200. package/dist/mailroom/reader.js +233 -0
  201. package/dist/mailroom/search-cache.js +256 -0
  202. package/dist/mailroom/search-relevance.js +319 -0
  203. package/dist/mailroom/smtp-ingress.js +176 -0
  204. package/dist/mailroom/source-state.js +176 -0
  205. package/dist/mailroom/thread.js +109 -0
  206. package/dist/mailroom/travel-extract.js +89 -0
  207. package/dist/mind/bundle-manifest.js +7 -1
  208. package/dist/mind/context.js +165 -101
  209. package/dist/mind/diary-integrity.js +60 -0
  210. package/dist/mind/{memory.js → diary.js} +62 -75
  211. package/dist/mind/embedding-provider.js +60 -0
  212. package/dist/mind/file-state.js +179 -0
  213. package/dist/mind/friends/channel.js +30 -0
  214. package/dist/mind/friends/resolver.js +54 -2
  215. package/dist/mind/friends/store-file.js +39 -3
  216. package/dist/mind/friends/types.js +2 -2
  217. package/dist/mind/journal-index.js +161 -0
  218. package/dist/mind/note-search.js +268 -0
  219. package/dist/mind/obligation-steering.js +221 -0
  220. package/dist/mind/pending.js +4 -0
  221. package/dist/mind/prompt-refresh.js +3 -2
  222. package/dist/mind/prompt.js +995 -123
  223. package/dist/mind/provenance-trust.js +26 -0
  224. package/dist/mind/scrutiny.js +173 -0
  225. package/dist/nerves/cli-logging.js +7 -1
  226. package/dist/nerves/coverage/audit-rules.js +15 -6
  227. package/dist/nerves/coverage/audit.js +28 -2
  228. package/dist/nerves/coverage/cli.js +1 -1
  229. package/dist/nerves/coverage/contract.js +5 -5
  230. package/dist/nerves/coverage/file-completeness.js +139 -5
  231. package/dist/nerves/coverage/run-artifacts.js +1 -1
  232. package/dist/nerves/event-buffer.js +111 -0
  233. package/dist/nerves/index.js +224 -4
  234. package/dist/nerves/observation.js +20 -0
  235. package/dist/nerves/redact.js +79 -0
  236. package/dist/nerves/review/cli-main.js +5 -0
  237. package/dist/nerves/review/cli.js +156 -0
  238. package/dist/nerves/review/core.js +152 -0
  239. package/dist/nerves/runtime.js +5 -1
  240. package/dist/repertoire/ado-client.js +15 -56
  241. package/dist/repertoire/ado-semantic.js +11 -10
  242. package/dist/repertoire/api-client.js +97 -0
  243. package/dist/repertoire/bitwarden-store.js +816 -0
  244. package/dist/repertoire/bundle-templates.js +72 -0
  245. package/dist/repertoire/bw-installer.js +180 -0
  246. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  247. package/dist/repertoire/coding/context-pack.js +330 -0
  248. package/dist/repertoire/coding/feedback.js +197 -30
  249. package/dist/repertoire/coding/manager.js +158 -9
  250. package/dist/repertoire/coding/spawner.js +55 -9
  251. package/dist/repertoire/coding/tools.js +170 -7
  252. package/dist/repertoire/commerce-errors.js +109 -0
  253. package/dist/repertoire/commerce-self-test.js +156 -0
  254. package/dist/repertoire/credential-access.js +111 -0
  255. package/dist/repertoire/duffel-client.js +185 -0
  256. package/dist/repertoire/github-client.js +14 -55
  257. package/dist/repertoire/graph-client.js +11 -52
  258. package/dist/repertoire/guardrails.js +396 -0
  259. package/dist/repertoire/mcp-client.js +295 -0
  260. package/dist/repertoire/mcp-manager.js +362 -0
  261. package/dist/repertoire/mcp-tools.js +63 -0
  262. package/dist/repertoire/shell-sessions.js +133 -0
  263. package/dist/repertoire/skills.js +15 -24
  264. package/dist/repertoire/stripe-client.js +131 -0
  265. package/dist/repertoire/tasks/board.js +31 -5
  266. package/dist/repertoire/tasks/fix.js +182 -0
  267. package/dist/repertoire/tasks/index.js +16 -4
  268. package/dist/repertoire/tasks/lifecycle.js +2 -2
  269. package/dist/repertoire/tasks/parser.js +3 -2
  270. package/dist/repertoire/tasks/scanner.js +194 -37
  271. package/dist/repertoire/tasks/transitions.js +16 -78
  272. package/dist/repertoire/tool-results.js +29 -0
  273. package/dist/repertoire/tools-attachments.js +317 -0
  274. package/dist/repertoire/tools-base.js +47 -1075
  275. package/dist/repertoire/tools-bluebubbles.js +1 -0
  276. package/dist/repertoire/tools-bridge.js +142 -0
  277. package/dist/repertoire/tools-bundle.js +984 -0
  278. package/dist/repertoire/tools-config.js +185 -0
  279. package/dist/repertoire/tools-continuity.js +248 -0
  280. package/dist/repertoire/tools-credential.js +381 -0
  281. package/dist/repertoire/tools-files.js +342 -0
  282. package/dist/repertoire/tools-flight.js +224 -0
  283. package/dist/repertoire/tools-flow.js +119 -0
  284. package/dist/repertoire/tools-github.js +1 -7
  285. package/dist/repertoire/tools-mail.js +1857 -0
  286. package/dist/repertoire/tools-notes.js +421 -0
  287. package/dist/repertoire/tools-session.js +750 -0
  288. package/dist/repertoire/tools-shell.js +120 -0
  289. package/dist/repertoire/tools-stripe.js +180 -0
  290. package/dist/repertoire/tools-surface.js +243 -0
  291. package/dist/repertoire/tools-teams.js +9 -39
  292. package/dist/repertoire/tools-travel.js +125 -0
  293. package/dist/repertoire/tools-trip.js +604 -0
  294. package/dist/repertoire/tools-user-profile.js +144 -0
  295. package/dist/repertoire/tools-vault.js +40 -0
  296. package/dist/repertoire/tools.js +108 -100
  297. package/dist/repertoire/travel-api-client.js +360 -0
  298. package/dist/repertoire/user-profile.js +131 -0
  299. package/dist/repertoire/vault-setup.js +246 -0
  300. package/dist/repertoire/vault-unlock.js +561 -0
  301. package/dist/scripts/claude-code-hook.js +41 -0
  302. package/dist/scripts/claude-code-stop-hook.js +47 -0
  303. package/dist/senses/attention-queue.js +116 -0
  304. package/dist/senses/bluebubbles/active-turns.js +216 -0
  305. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  306. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  307. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +219 -18
  308. package/dist/senses/bluebubbles/entry.js +77 -0
  309. package/dist/senses/{bluebubbles-inbound-log.js → bluebubbles/inbound-log.js} +20 -3
  310. package/dist/senses/bluebubbles/index.js +2305 -0
  311. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  312. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +33 -12
  313. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +3 -3
  314. package/dist/senses/bluebubbles/processed-log.js +133 -0
  315. package/dist/senses/bluebubbles/replay.js +137 -0
  316. package/dist/senses/{bluebubbles-runtime-state.js → bluebubbles/runtime-state.js} +30 -2
  317. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  318. package/dist/senses/cli/bracketed-paste.js +82 -0
  319. package/dist/senses/cli/image-paste.js +287 -0
  320. package/dist/senses/cli/image-ref-navigation.js +75 -0
  321. package/dist/senses/cli/ink-app.js +156 -0
  322. package/dist/senses/cli/inline-diff.js +64 -0
  323. package/dist/senses/cli/input-keys.js +174 -0
  324. package/dist/senses/cli/kill-ring.js +86 -0
  325. package/dist/senses/cli/message-list.js +51 -0
  326. package/dist/senses/cli/ouro-tui.js +607 -0
  327. package/dist/senses/cli/spinner-imperative.js +135 -0
  328. package/dist/senses/cli/spinner.js +101 -0
  329. package/dist/senses/cli/status-line.js +60 -0
  330. package/dist/senses/cli/streaming-markdown.js +526 -0
  331. package/dist/senses/cli/tool-display.js +85 -0
  332. package/dist/senses/cli/tool-render.js +85 -0
  333. package/dist/senses/cli/tui-store.js +240 -0
  334. package/dist/senses/cli/virtual-list.js +35 -0
  335. package/dist/senses/cli-entry.js +60 -8
  336. package/dist/senses/cli-layout.js +187 -0
  337. package/dist/senses/cli.js +520 -209
  338. package/dist/senses/commands.js +66 -3
  339. package/dist/senses/habit-turn-message.js +108 -0
  340. package/dist/senses/inner-dialog-worker.js +175 -21
  341. package/dist/senses/inner-dialog.js +330 -27
  342. package/dist/senses/mail-entry.js +66 -0
  343. package/dist/senses/mail.js +379 -0
  344. package/dist/senses/pipeline.js +569 -182
  345. package/dist/senses/proactive-content-guard.js +51 -0
  346. package/dist/senses/shared-turn.js +248 -0
  347. package/dist/senses/surface-tool.js +68 -0
  348. package/dist/senses/teams-entry.js +60 -8
  349. package/dist/senses/teams.js +387 -98
  350. package/dist/senses/trust-gate.js +100 -5
  351. package/dist/trips/core.js +138 -0
  352. package/dist/trips/store.js +146 -0
  353. package/package.json +38 -7
  354. package/skills/agent-commerce.md +106 -0
  355. package/skills/browser-navigation.md +117 -0
  356. package/skills/commerce-setup-guide.md +116 -0
  357. package/skills/commerce-setup.md +84 -0
  358. package/skills/configure-dev-tools.md +101 -0
  359. package/skills/travel-planning.md +138 -0
  360. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  361. package/dist/heart/daemon/subagent-installer.js +0 -166
  362. package/dist/heart/session-recall.js +0 -116
  363. package/dist/mind/associative-recall.js +0 -209
  364. package/dist/senses/bluebubbles-entry.js +0 -13
  365. package/dist/senses/bluebubbles.js +0 -1177
  366. package/dist/senses/debug-activity.js +0 -148
  367. package/subagents/README.md +0 -86
  368. package/subagents/work-doer.md +0 -237
  369. package/subagents/work-merger.md +0 -618
  370. package/subagents/work-planner.md +0 -390
  371. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  372. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  373. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  374. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  375. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  376. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  377. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  378. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  379. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  380. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  381. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  382. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  383. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  384. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  385. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  386. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatCredentialProvenanceLabel = formatCredentialProvenanceLabel;
4
+ exports.formatReadyProviderLabel = formatReadyProviderLabel;
5
+ exports.buildFailoverContext = buildFailoverContext;
6
+ exports.handleFailoverReply = handleFailoverReply;
7
+ exports.runMachineProviderFailoverInventory = runMachineProviderFailoverInventory;
8
+ exports.validateFailoverSwitchCandidate = validateFailoverSwitchCandidate;
9
+ const identity_1 = require("./identity");
10
+ const provider_ping_1 = require("./provider-ping");
11
+ const provider_models_1 = require("./provider-models");
12
+ const provider_credentials_1 = require("./provider-credentials");
13
+ const runtime_1 = require("../nerves/runtime");
14
+ const CLASSIFICATION_LABELS = {
15
+ "auth-failure": "authentication failed",
16
+ "usage-limit": "hit its usage limit",
17
+ "rate-limit": "is being rate limited",
18
+ "server-error": "is experiencing an outage",
19
+ "network-error": "is unreachable (network error)",
20
+ "unknown": "encountered an error",
21
+ };
22
+ function formatProviderWithModel(provider, model) {
23
+ if (!model)
24
+ return provider;
25
+ if ((0, provider_models_1.getProviderModelMismatchMessage)(provider, model)) {
26
+ return `${provider} [configured model: ${model}]`;
27
+ }
28
+ return `${provider} (${model})`;
29
+ }
30
+ function formatErrorDetail(errorMessage, errorSummary) {
31
+ const detail = errorMessage.replace(/\s+/g, " ").trim();
32
+ if (!detail || detail === errorSummary)
33
+ return "";
34
+ return detail.length > 300 ? `${detail.slice(0, 297)}...` : detail;
35
+ }
36
+ function formatCredentialProvenanceLabel(candidate) {
37
+ if (candidate.source) {
38
+ return `credentials in vault via ${candidate.source}`;
39
+ }
40
+ return undefined;
41
+ }
42
+ function formatReadyProviderLabel(candidate) {
43
+ const provenance = formatCredentialProvenanceLabel(candidate);
44
+ const provenanceSuffix = provenance ? `; ${provenance}` : "";
45
+ return `${candidate.provider} (${candidate.model}${provenanceSuffix})`;
46
+ }
47
+ function formatFailingProviderLine(provider, classification, agentName) {
48
+ const authCommand = `ouro auth --agent ${agentName} --provider ${provider}`;
49
+ switch (classification) {
50
+ case "auth-failure":
51
+ return ` - ${provider}: credentials need to be refreshed. Run \`${authCommand}\`.`;
52
+ case "network-error":
53
+ return ` - ${provider}: could not be reached. Check network/provider availability; if credentials may be stale, run \`${authCommand}\`.`;
54
+ case "server-error":
55
+ return ` - ${provider}: provider outage or server error. Retry later; if it keeps failing, run \`${authCommand}\`.`;
56
+ case "rate-limit":
57
+ return ` - ${provider}: rate limited. Wait and retry, or switch to a ready provider below.`;
58
+ case "usage-limit":
59
+ return ` - ${provider}: usage limit hit. Wait for quota reset, raise quota, or switch to a ready provider below.`;
60
+ case "unknown":
61
+ return ` - ${provider}: could not be reached. Run \`${authCommand}\` if credentials may be stale.`;
62
+ }
63
+ }
64
+ function isProviderFailoverInventory(inventory) {
65
+ const candidate = inventory;
66
+ return Array.isArray(candidate.ready) && Array.isArray(candidate.unavailable) && Array.isArray(candidate.unconfigured);
67
+ }
68
+ function normalizeLegacyInventory(inventory, providerModels) {
69
+ const ready = [];
70
+ const unavailable = [];
71
+ const unconfigured = [];
72
+ for (const [provider, result] of Object.entries(inventory)) {
73
+ if (result.ok) {
74
+ ready.push({
75
+ provider,
76
+ model: (0, provider_models_1.resolveModelForProviderDisplay)(provider, providerModels[provider]),
77
+ result,
78
+ });
79
+ }
80
+ else if (result.classification === "auth-failure" && result.message === "no credentials configured") {
81
+ unconfigured.push(provider);
82
+ }
83
+ else {
84
+ // Configured but ping failed (expired token, provider also down, etc.)
85
+ unavailable.push({
86
+ provider,
87
+ model: (0, provider_models_1.resolveModelForProviderDisplay)(provider, providerModels[provider]),
88
+ result,
89
+ });
90
+ }
91
+ }
92
+ return { ready, unavailable, unconfigured };
93
+ }
94
+ function normalizeFailoverInventory(inventory, providerModels) {
95
+ if (!isProviderFailoverInventory(inventory)) {
96
+ return normalizeLegacyInventory(inventory, providerModels);
97
+ }
98
+ return {
99
+ ready: inventory.ready.map((candidate) => ({
100
+ ...candidate,
101
+ model: (0, provider_models_1.resolveModelForProviderDisplay)(candidate.provider, candidate.model),
102
+ })),
103
+ unavailable: inventory.unavailable.map((candidate) => ({
104
+ ...candidate,
105
+ model: candidate.model ? (0, provider_models_1.resolveModelForProviderDisplay)(candidate.provider, candidate.model) : undefined,
106
+ })),
107
+ unconfigured: [...inventory.unconfigured],
108
+ };
109
+ }
110
+ function buildFailoverContext(errorMessage, classification, currentProvider, currentModel, agentName, inventory, providerModels, options = {}) {
111
+ const currentLane = options.currentLane ?? "outward";
112
+ const label = CLASSIFICATION_LABELS[classification];
113
+ const providerWithModel = formatProviderWithModel(currentProvider, currentModel);
114
+ const errorSummary = `${providerWithModel} ${label}`;
115
+ const errorDetail = formatErrorDetail(errorMessage, errorSummary);
116
+ const modelMismatch = (0, provider_models_1.getProviderModelMismatchMessage)(currentProvider, currentModel);
117
+ const normalizedInventory = normalizeFailoverInventory(inventory, providerModels);
118
+ const readyProviders = normalizedInventory.ready;
119
+ const workingProviders = readyProviders.map((candidate) => candidate.provider);
120
+ const unconfiguredProviders = normalizedInventory.unconfigured;
121
+ const failingProviders = normalizedInventory.unavailable;
122
+ const lines = [`${errorSummary}.`];
123
+ if (errorDetail) {
124
+ lines.push(`provider detail: ${errorDetail}`);
125
+ }
126
+ if (classification === "auth-failure") {
127
+ lines.push("");
128
+ lines.push("To keep using the current provider:");
129
+ lines.push(` 1. Run \`ouro auth --agent ${agentName} --provider ${currentProvider}\``);
130
+ }
131
+ if (modelMismatch) {
132
+ const defaultModel = (0, provider_models_1.getDefaultModelForProvider)(currentProvider);
133
+ lines.push("");
134
+ lines.push("Config warning:");
135
+ lines.push(` - ${modelMismatch}`);
136
+ lines.push(" - Repair the configured model with:");
137
+ lines.push(` \`ouro use --agent ${agentName} --lane ${currentLane} --provider ${currentProvider} --model ${defaultModel}\``);
138
+ }
139
+ if (readyProviders.length > 0) {
140
+ lines.push("");
141
+ lines.push("Ready providers:");
142
+ for (const candidate of readyProviders) {
143
+ lines.push(` - ${formatReadyProviderLabel(candidate)}: reply "switch to ${candidate.provider}"`);
144
+ }
145
+ }
146
+ if (failingProviders.length > 0) {
147
+ lines.push("");
148
+ lines.push("Configured but unavailable:");
149
+ for (const candidate of failingProviders) {
150
+ lines.push(formatFailingProviderLine(candidate.provider, candidate.result.classification, agentName));
151
+ }
152
+ }
153
+ if (unconfiguredProviders.length > 0) {
154
+ lines.push("");
155
+ lines.push("Not configured:");
156
+ for (const provider of unconfiguredProviders) {
157
+ lines.push(` - ${provider}: run \`ouro auth --agent ${agentName} --provider ${provider}\``);
158
+ }
159
+ }
160
+ if (workingProviders.length === 0 && unconfiguredProviders.length === 0 && failingProviders.length === 0) {
161
+ lines.push("");
162
+ lines.push(`No other providers are available. Run \`ouro auth --agent ${agentName}\` in terminal to configure one.`);
163
+ }
164
+ (0, runtime_1.emitNervesEvent)({
165
+ component: "engine",
166
+ event: "engine.failover_context_built",
167
+ message: "built provider failover context",
168
+ meta: { currentProvider, currentLane, classification, workingProviders, unconfiguredProviders },
169
+ });
170
+ return {
171
+ errorSummary,
172
+ classification,
173
+ currentProvider,
174
+ currentModel,
175
+ currentLane,
176
+ agentName,
177
+ workingProviders,
178
+ readyProviders,
179
+ unconfiguredProviders,
180
+ userMessage: lines.join("\n"),
181
+ };
182
+ }
183
+ function handleFailoverReply(reply, context) {
184
+ const lower = reply.toLowerCase().trim();
185
+ const readyProviders = context.readyProviders ?? context.workingProviders.map((provider) => ({
186
+ provider,
187
+ model: (0, provider_models_1.resolveModelForProviderDisplay)(provider),
188
+ }));
189
+ const currentLane = context.currentLane ?? "outward";
190
+ for (const candidate of readyProviders) {
191
+ if (lower.includes(`switch to ${candidate.provider}`) || lower === candidate.provider) {
192
+ return {
193
+ action: "switch",
194
+ provider: candidate.provider,
195
+ model: candidate.model,
196
+ lane: currentLane,
197
+ ...(candidate.credentialRevision ? { credentialRevision: candidate.credentialRevision } : {}),
198
+ ...(candidate.source ? { source: candidate.source } : {}),
199
+ };
200
+ }
201
+ }
202
+ return { action: "dismiss" };
203
+ }
204
+ function candidateFromCredentialRecord(record) {
205
+ return {
206
+ provider: record.provider,
207
+ credentialRevision: record.revision,
208
+ source: record.provenance.source,
209
+ };
210
+ }
211
+ async function runMachineProviderFailoverInventory(agentName, currentProvider, options = {}) {
212
+ const ping = options.ping ?? provider_ping_1.pingProvider;
213
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName);
214
+ const providers = Object.keys(identity_1.PROVIDER_CREDENTIALS).filter((provider) => provider !== currentProvider);
215
+ const inventory = { ready: [], unavailable: [], unconfigured: [] };
216
+ if (!poolResult.ok) {
217
+ inventory.unconfigured.push(...providers);
218
+ (0, runtime_1.emitNervesEvent)({
219
+ component: "engine",
220
+ event: "engine.machine_failover_inventory_built",
221
+ message: "built machine provider failover inventory",
222
+ meta: { agentName, currentProvider, credentialPoolStatus: poolResult.reason, readyCount: 0, unavailableCount: 0, unconfiguredCount: inventory.unconfigured.length },
223
+ });
224
+ return inventory;
225
+ }
226
+ const results = await Promise.all(providers.map(async (provider) => {
227
+ const record = poolResult.pool.providers[provider];
228
+ if (!record)
229
+ return { provider, record: undefined, result: undefined };
230
+ const model = (0, provider_models_1.getDefaultModelForProvider)(provider);
231
+ const config = { ...record.credentials, ...record.config };
232
+ const result = await ping(provider, config, { model });
233
+ return { provider, record, model, result };
234
+ }));
235
+ for (const entry of results) {
236
+ if (!entry.record) {
237
+ inventory.unconfigured.push(entry.provider);
238
+ }
239
+ else if (entry.result.ok) {
240
+ inventory.ready.push({
241
+ ...candidateFromCredentialRecord(entry.record),
242
+ model: entry.model,
243
+ result: entry.result,
244
+ });
245
+ }
246
+ else {
247
+ inventory.unavailable.push({
248
+ ...candidateFromCredentialRecord(entry.record),
249
+ model: entry.model,
250
+ result: entry.result,
251
+ });
252
+ }
253
+ }
254
+ (0, runtime_1.emitNervesEvent)({
255
+ component: "engine",
256
+ event: "engine.machine_failover_inventory_built",
257
+ message: "built machine provider failover inventory",
258
+ meta: {
259
+ agentName,
260
+ currentProvider,
261
+ credentialPoolStatus: "present",
262
+ readyCount: inventory.ready.length,
263
+ unavailableCount: inventory.unavailable.length,
264
+ unconfiguredCount: inventory.unconfigured.length,
265
+ },
266
+ });
267
+ return inventory;
268
+ }
269
+ /**
270
+ * Re-verify a failover candidate is actually reachable right before we mutate
271
+ * provider state. The inventory ping that produced the candidate may be stale
272
+ * (creds revoked between inventory and reply); without this preflight, an
273
+ * agent-driven "switch to <provider>" can move the lane onto an unreachable
274
+ * provider and brick the next turn.
275
+ */
276
+ async function validateFailoverSwitchCandidate(agentName, candidate, options = {}) {
277
+ const ping = options.ping ?? provider_ping_1.pingProvider;
278
+ const refreshPool = options.refreshPool ?? provider_credentials_1.refreshProviderCredentialPool;
279
+ const poolResult = await refreshPool(agentName);
280
+ if (!poolResult.ok) {
281
+ return {
282
+ ok: false,
283
+ classification: "auth-failure",
284
+ message: `provider credential pool unavailable (${poolResult.reason}): ${poolResult.error}`,
285
+ };
286
+ }
287
+ const record = poolResult.pool.providers[candidate.provider];
288
+ if (!record) {
289
+ return {
290
+ ok: false,
291
+ classification: "auth-failure",
292
+ message: `no credentials configured for ${candidate.provider}`,
293
+ };
294
+ }
295
+ const config = { ...record.credentials, ...record.config };
296
+ const result = await ping(candidate.provider, config, { model: candidate.model });
297
+ if (!result.ok) {
298
+ return { ok: false, classification: result.classification, message: result.message };
299
+ }
300
+ return { ok: true };
301
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_PROVIDER_MODELS = void 0;
4
+ exports.getProviderDisplayName = getProviderDisplayName;
5
+ exports.getDefaultModelForProvider = getDefaultModelForProvider;
6
+ exports.isModelClearlyIncompatibleWithProvider = isModelClearlyIncompatibleWithProvider;
7
+ exports.resolveModelForProviderSelection = resolveModelForProviderSelection;
8
+ exports.resolveModelForProviderDisplay = resolveModelForProviderDisplay;
9
+ exports.getProviderModelMismatchMessage = getProviderModelMismatchMessage;
10
+ const runtime_1 = require("../nerves/runtime");
11
+ exports.DEFAULT_PROVIDER_MODELS = {
12
+ anthropic: "claude-opus-4-6",
13
+ azure: "gpt-4o-mini",
14
+ minimax: "MiniMax-M2.7",
15
+ "openai-codex": "gpt-5.4",
16
+ "github-copilot": "claude-sonnet-4.6",
17
+ };
18
+ const PROVIDER_NAMES = {
19
+ anthropic: "Anthropic",
20
+ azure: "Azure OpenAI",
21
+ minimax: "MiniMax",
22
+ "openai-codex": "OpenAI Codex",
23
+ "github-copilot": "GitHub Copilot",
24
+ };
25
+ function normalized(model) {
26
+ return model.trim().toLowerCase();
27
+ }
28
+ function getProviderDisplayName(provider) {
29
+ return PROVIDER_NAMES[provider];
30
+ }
31
+ function getDefaultModelForProvider(provider) {
32
+ return exports.DEFAULT_PROVIDER_MODELS[provider];
33
+ }
34
+ function isModelClearlyIncompatibleWithProvider(provider, model) {
35
+ const value = normalized(model);
36
+ if (!value)
37
+ return true;
38
+ switch (provider) {
39
+ case "anthropic":
40
+ return !value.startsWith("claude-");
41
+ case "minimax":
42
+ return !value.startsWith("minimax");
43
+ case "openai-codex":
44
+ return value.startsWith("claude-") || value.startsWith("minimax");
45
+ case "azure":
46
+ return value.startsWith("claude-") || value.startsWith("minimax");
47
+ case "github-copilot":
48
+ return false;
49
+ }
50
+ }
51
+ function resolveModelForProviderSelection(provider, currentModel) {
52
+ const trimmed = currentModel.trim();
53
+ if (trimmed && !isModelClearlyIncompatibleWithProvider(provider, trimmed)) {
54
+ return { model: trimmed, preserved: true };
55
+ }
56
+ const model = getDefaultModelForProvider(provider);
57
+ (0, runtime_1.emitNervesEvent)({
58
+ component: "config/identity",
59
+ event: "config_identity.provider_model_defaulted",
60
+ message: "defaulted provider model during provider selection",
61
+ meta: { provider, previousModel: currentModel, model },
62
+ });
63
+ return { model, preserved: false };
64
+ }
65
+ function resolveModelForProviderDisplay(provider, modelHint) {
66
+ const hint = modelHint?.trim() ?? "";
67
+ if (hint && !isModelClearlyIncompatibleWithProvider(provider, hint))
68
+ return hint;
69
+ return getDefaultModelForProvider(provider);
70
+ }
71
+ function getProviderModelMismatchMessage(provider, model) {
72
+ const trimmed = model.trim();
73
+ if (!isModelClearlyIncompatibleWithProvider(provider, trimmed))
74
+ return null;
75
+ const providerName = getProviderDisplayName(provider);
76
+ const defaultModel = getDefaultModelForProvider(provider);
77
+ if (!trimmed) {
78
+ return `${providerName} has no model set. Suggested model: ${defaultModel}.`;
79
+ }
80
+ return `${providerName} is currently paired with ${trimmed}, which does not look like a model for ${providerName}. Suggested model: ${defaultModel}.`;
81
+ }
@@ -0,0 +1,262 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitizeErrorMessage = sanitizeErrorMessage;
4
+ exports.pingGithubCopilotModel = pingGithubCopilotModel;
5
+ exports.createProviderRuntimeForConfig = createProviderRuntimeForConfig;
6
+ exports.pingProvider = pingProvider;
7
+ exports.runHealthInventory = runHealthInventory;
8
+ const identity_1 = require("./identity");
9
+ const anthropic_1 = require("./providers/anthropic");
10
+ const azure_1 = require("./providers/azure");
11
+ const minimax_1 = require("./providers/minimax");
12
+ const openai_codex_1 = require("./providers/openai-codex");
13
+ const github_copilot_1 = require("./providers/github-copilot");
14
+ const provider_models_1 = require("./provider-models");
15
+ const runtime_1 = require("../nerves/runtime");
16
+ const provider_attempt_1 = require("./provider-attempt");
17
+ const provider_credentials_1 = require("./provider-credentials");
18
+ const PING_TIMEOUT_MS = 10_000;
19
+ const PING_PROMPT = "ping";
20
+ const CHAT_PING_MAX_TOKENS = 1;
21
+ const RESPONSE_PING_MAX_OUTPUT_TOKENS = 16;
22
+ const DEFAULT_AZURE_API_VERSION = "2025-04-01-preview";
23
+ function createPingMessages() {
24
+ return [{ role: "user", content: PING_PROMPT }];
25
+ }
26
+ function createChatPingRequest(model) {
27
+ return { model, max_tokens: CHAT_PING_MAX_TOKENS, messages: createPingMessages() };
28
+ }
29
+ function createResponsePingRequest(model) {
30
+ return { model, input: PING_PROMPT, max_output_tokens: RESPONSE_PING_MAX_OUTPUT_TOKENS };
31
+ }
32
+ /**
33
+ * Strip raw JSON/HTML API response bodies from error messages.
34
+ * SDK errors often include the full response: "400 {"type":"error",...}" or "403 <html>...".
35
+ * Extract just the HTTP status and a short human-readable summary.
36
+ */
37
+ function sanitizeErrorMessage(message) {
38
+ const statusMatch = message.match(/^(\d{3})\s/);
39
+ if (!statusMatch)
40
+ return message;
41
+ const status = statusMatch[1];
42
+ const body = message.slice(status.length).trim();
43
+ // HTML response (Cloudflare challenge, error pages, etc.)
44
+ if (body.startsWith("<") || body.includes("<!DOCTYPE") || body.includes("<html")) {
45
+ return `HTTP ${status}`;
46
+ }
47
+ // JSON response
48
+ if (body.startsWith("{")) {
49
+ try {
50
+ const json = JSON.parse(body);
51
+ const inner = json?.error?.message;
52
+ if (typeof inner === "string" && inner && inner !== "Error") {
53
+ return `${status} ${inner}`;
54
+ }
55
+ }
56
+ catch { /* not valid JSON */ }
57
+ return `HTTP ${status}`;
58
+ }
59
+ // Already clean (e.g., "401 Provided authentication token is expired.")
60
+ return message;
61
+ }
62
+ async function readGithubCopilotModelPingError(response) {
63
+ let detail = `HTTP ${response.status}`;
64
+ try {
65
+ const json = await response.json();
66
+ /* v8 ignore start -- error format parsing: all branches tested via config-models.test.ts @preserve */
67
+ if (typeof json.error === "string")
68
+ detail = json.error;
69
+ else if (typeof json.error === "object" && json.error !== null) {
70
+ const errObj = json.error;
71
+ if (typeof errObj.message === "string")
72
+ detail = errObj.message;
73
+ }
74
+ else if (typeof json.message === "string")
75
+ detail = json.message;
76
+ /* v8 ignore stop */
77
+ }
78
+ catch {
79
+ // response body not JSON — keep HTTP status
80
+ }
81
+ return detail;
82
+ }
83
+ function createStatusError(message, status) {
84
+ return Object.assign(new Error(message), { status });
85
+ }
86
+ function normalizePingTimeoutMs(timeoutMs) {
87
+ if (timeoutMs === undefined)
88
+ return PING_TIMEOUT_MS;
89
+ if (!Number.isFinite(timeoutMs))
90
+ return PING_TIMEOUT_MS;
91
+ return Math.max(1, Math.floor(timeoutMs));
92
+ }
93
+ function createPingTimeoutError(timeoutMs) {
94
+ return Object.assign(new Error(`provider ping timed out after ${timeoutMs}ms`), {
95
+ code: "ETIMEDOUT",
96
+ });
97
+ }
98
+ async function runPingWithHardTimeout(runtime, timeoutMs) {
99
+ const controller = new AbortController();
100
+ let timeout;
101
+ const timeoutPromise = new Promise((_, reject) => {
102
+ timeout = setTimeout(() => {
103
+ controller.abort();
104
+ reject(createPingTimeoutError(timeoutMs));
105
+ }, timeoutMs);
106
+ });
107
+ try {
108
+ await Promise.race([
109
+ Promise.resolve().then(() => runtime.ping(controller.signal)),
110
+ timeoutPromise,
111
+ ]);
112
+ }
113
+ finally {
114
+ clearTimeout(timeout);
115
+ }
116
+ }
117
+ async function pingGithubCopilotModel(baseUrl, token, model, fetchImpl = fetch) {
118
+ const base = baseUrl.replace(/\/+$/, "");
119
+ const isClaude = model.startsWith("claude");
120
+ const url = isClaude ? `${base}/chat/completions` : `${base}/responses`;
121
+ const body = isClaude
122
+ ? JSON.stringify(createChatPingRequest(model))
123
+ : JSON.stringify(createResponsePingRequest(model));
124
+ const attempt = await (0, provider_attempt_1.runProviderAttempt)({
125
+ operation: "model-ping",
126
+ provider: "github-copilot",
127
+ model,
128
+ classifyError: github_copilot_1.classifyGithubCopilotError,
129
+ policy: {
130
+ maxAttempts: 3,
131
+ baseDelayMs: 0,
132
+ backoffMultiplier: 2,
133
+ },
134
+ run: async () => {
135
+ const response = await fetchImpl(url, {
136
+ method: "POST",
137
+ headers: {
138
+ Authorization: `Bearer ${token}`,
139
+ "Content-Type": "application/json",
140
+ },
141
+ body,
142
+ });
143
+ if (!response.ok) {
144
+ throw createStatusError(await readGithubCopilotModelPingError(response), response.status);
145
+ }
146
+ },
147
+ });
148
+ return attempt.ok ? { ok: true } : { ok: false, error: attempt.error.message };
149
+ }
150
+ function hasEmptyCredentials(provider, config) {
151
+ const record = config;
152
+ if (provider === "azure") {
153
+ const hasManagedIdentity = typeof record.endpoint === "string" && record.endpoint.length > 0 &&
154
+ typeof record.deployment === "string" && record.deployment.length > 0 &&
155
+ typeof record.managedIdentityClientId === "string" && record.managedIdentityClientId.length > 0;
156
+ if (hasManagedIdentity)
157
+ return false;
158
+ }
159
+ return identity_1.PROVIDER_CREDENTIALS[provider].required.some((key) => !record[key]);
160
+ }
161
+ function createProviderRuntimeForConfig(provider, config, options = {}) {
162
+ // Use the same provider defaults as auth switch and hatch so verification
163
+ // cannot drift to stale provider/model pairings, and pass the checked
164
+ // credentials directly so daemon-side pings do not depend on --agent globals.
165
+ const resolvedModel = options.model ?? (0, provider_models_1.getDefaultModelForProvider)(provider);
166
+ switch (provider) {
167
+ case "anthropic":
168
+ return (0, anthropic_1.createAnthropicProviderRuntime)(resolvedModel, config);
169
+ case "azure":
170
+ return (0, azure_1.createAzureProviderRuntime)(resolvedModel, {
171
+ ...config,
172
+ apiVersion: config.apiVersion ?? DEFAULT_AZURE_API_VERSION,
173
+ });
174
+ case "minimax":
175
+ return (0, minimax_1.createMinimaxProviderRuntime)(resolvedModel, config);
176
+ case "openai-codex":
177
+ return (0, openai_codex_1.createOpenAICodexProviderRuntime)(resolvedModel, config);
178
+ case "github-copilot":
179
+ return (0, github_copilot_1.createGithubCopilotProviderRuntime)(resolvedModel, config);
180
+ /* v8 ignore next 2 -- exhaustive: all providers handled above @preserve */
181
+ default:
182
+ throw new Error(`unsupported provider for ping: ${provider}`);
183
+ }
184
+ }
185
+ async function pingProvider(provider, config, options = {}) {
186
+ if (hasEmptyCredentials(provider, config)) {
187
+ return { ok: false, classification: "auth-failure", message: "no credentials configured" };
188
+ }
189
+ let runtime;
190
+ try {
191
+ runtime = createProviderRuntimeForConfig(provider, config, { model: options.model });
192
+ /* v8 ignore start -- factory creation failure: tested via individual provider init tests @preserve */
193
+ }
194
+ catch (error) {
195
+ return {
196
+ ok: false,
197
+ classification: "auth-failure",
198
+ message: error instanceof Error ? error.message : String(error),
199
+ };
200
+ }
201
+ /* v8 ignore stop */
202
+ const attempt = await (0, provider_attempt_1.runProviderAttempt)({
203
+ operation: "ping",
204
+ provider,
205
+ model: runtime.model,
206
+ classifyError: (error) => runtime.classifyError(error),
207
+ policy: {
208
+ maxAttempts: 3,
209
+ baseDelayMs: 0,
210
+ backoffMultiplier: 2,
211
+ ...options.attemptPolicy,
212
+ },
213
+ sleep: options.sleep,
214
+ onAttemptStart: options.onAttemptStart,
215
+ onRetry: options.onRetry,
216
+ run: async () => {
217
+ await runPingWithHardTimeout(runtime, normalizePingTimeoutMs(options.timeoutMs));
218
+ },
219
+ });
220
+ if (attempt.ok) {
221
+ return { ok: true, attempts: attempt.attempts };
222
+ }
223
+ (0, runtime_1.emitNervesEvent)({
224
+ component: "engine",
225
+ event: "engine.provider_ping_fail",
226
+ message: `provider ping failed: ${provider}`,
227
+ meta: { provider, classification: attempt.classification, error: attempt.error.message },
228
+ });
229
+ return {
230
+ ok: false,
231
+ classification: attempt.classification,
232
+ message: sanitizeErrorMessage(attempt.error.message),
233
+ attempts: attempt.attempts,
234
+ };
235
+ }
236
+ const PINGABLE_PROVIDERS = ["anthropic", "openai-codex", "azure", "minimax", "github-copilot"];
237
+ async function runHealthInventory(agentName, currentProvider, deps = {}) {
238
+ /* v8 ignore next -- default: tests inject ping dep @preserve */
239
+ const ping = deps.ping ?? pingProvider;
240
+ const poolResult = await (0, provider_credentials_1.refreshProviderCredentialPool)(agentName);
241
+ const providers = PINGABLE_PROVIDERS.filter((p) => p !== currentProvider);
242
+ if (!poolResult.ok) {
243
+ return Object.fromEntries(providers.map((provider) => [
244
+ provider,
245
+ { ok: false, classification: "auth-failure", message: poolResult.error },
246
+ ]));
247
+ }
248
+ const results = await Promise.all(providers.map(async (provider) => {
249
+ const record = poolResult.pool.providers[provider];
250
+ if (!record) {
251
+ return [provider, { ok: false, classification: "auth-failure", message: "no credentials configured" }];
252
+ }
253
+ const config = { ...record.config, ...record.credentials };
254
+ const result = await ping(provider, config);
255
+ return [provider, result];
256
+ }));
257
+ const inventory = {};
258
+ for (const [provider, result] of results) {
259
+ inventory[provider] = result;
260
+ }
261
+ return inventory;
262
+ }