@ouro.bot/cli 0.1.0-alpha.35 → 0.1.0-alpha.350

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 (324) hide show
  1. package/README.md +188 -187
  2. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +3 -2
  3. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +1 -1
  4. package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +1 -1
  5. package/changelog.json +2088 -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 +832 -0
  16. package/dist/heart/agent-entry.js +37 -2
  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 +463 -0
  28. package/dist/heart/bridges/manager.js +358 -0
  29. package/dist/heart/bridges/state-machine.js +135 -0
  30. package/dist/heart/bridges/store.js +123 -0
  31. package/dist/heart/bundle-state.js +168 -0
  32. package/dist/heart/commitments.js +111 -0
  33. package/dist/heart/config-registry.js +304 -0
  34. package/dist/heart/config.js +53 -21
  35. package/dist/heart/core.js +744 -252
  36. package/dist/heart/cross-chat-delivery.js +131 -0
  37. package/dist/heart/daemon/agent-config-check.js +561 -0
  38. package/dist/heart/daemon/agent-discovery.js +79 -3
  39. package/dist/heart/daemon/agent-service.js +360 -0
  40. package/dist/heart/daemon/agentic-repair.js +170 -0
  41. package/dist/heart/daemon/bluebubbles-health-diagnostics.js +122 -0
  42. package/dist/heart/daemon/cadence.js +70 -0
  43. package/dist/heart/daemon/cli-defaults.js +591 -0
  44. package/dist/heart/daemon/cli-exec.js +2633 -0
  45. package/dist/heart/daemon/cli-help.js +306 -0
  46. package/dist/heart/daemon/cli-parse.js +913 -0
  47. package/dist/heart/daemon/cli-render-doctor.js +57 -0
  48. package/dist/heart/daemon/cli-render.js +512 -0
  49. package/dist/heart/daemon/cli-types.js +8 -0
  50. package/dist/heart/daemon/daemon-cli.js +30 -1171
  51. package/dist/heart/daemon/daemon-entry.js +358 -3
  52. package/dist/heart/daemon/daemon-health.js +141 -0
  53. package/dist/heart/daemon/daemon-runtime-sync.js +157 -12
  54. package/dist/heart/daemon/daemon-tombstone.js +236 -0
  55. package/dist/heart/daemon/daemon.js +751 -58
  56. package/dist/heart/daemon/doctor-types.js +8 -0
  57. package/dist/heart/daemon/doctor.js +465 -0
  58. package/dist/heart/daemon/health-monitor.js +79 -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/inner-status.js +89 -0
  63. package/dist/heart/daemon/interactive-repair.js +91 -0
  64. package/dist/heart/daemon/launchd.js +46 -9
  65. package/dist/heart/daemon/log-tailer.js +82 -12
  66. package/dist/heart/daemon/logs-prune.js +105 -0
  67. package/dist/heart/daemon/message-router.js +17 -8
  68. package/dist/heart/daemon/os-cron-deps.js +134 -0
  69. package/dist/heart/daemon/ouro-bot-entry.js +1 -1
  70. package/dist/heart/daemon/process-manager.js +201 -0
  71. package/dist/heart/daemon/provider-discovery.js +105 -0
  72. package/dist/heart/daemon/pulse.js +463 -0
  73. package/dist/heart/daemon/run-hooks.js +2 -0
  74. package/dist/heart/daemon/runtime-logging.js +67 -16
  75. package/dist/heart/daemon/runtime-metadata.js +101 -0
  76. package/dist/heart/daemon/runtime-mode.js +67 -0
  77. package/dist/heart/daemon/safe-mode.js +161 -0
  78. package/dist/heart/daemon/sense-manager.js +72 -3
  79. package/dist/heart/daemon/session-id-resolver.js +131 -0
  80. package/dist/heart/daemon/skill-management-installer.js +94 -0
  81. package/dist/heart/daemon/socket-client.js +307 -0
  82. package/dist/heart/daemon/stale-bundle-prune.js +96 -0
  83. package/dist/heart/daemon/startup-tui.js +237 -0
  84. package/dist/heart/daemon/task-scheduler.js +3 -25
  85. package/dist/heart/daemon/thoughts.js +510 -0
  86. package/dist/heart/daemon/up-progress.js +135 -0
  87. package/dist/heart/delegation.js +62 -0
  88. package/dist/heart/habits/habit-migration.js +181 -0
  89. package/dist/heart/habits/habit-parser.js +140 -0
  90. package/dist/heart/habits/habit-scheduler.js +371 -0
  91. package/dist/heart/{daemon → hatch}/hatch-flow.js +52 -120
  92. package/dist/heart/{daemon → hatch}/hatch-specialist.js +3 -3
  93. package/dist/heart/{daemon → hatch}/specialist-prompt.js +10 -7
  94. package/dist/heart/{daemon → hatch}/specialist-tools.js +56 -10
  95. package/dist/heart/identity.js +154 -59
  96. package/dist/heart/kept-notes.js +357 -0
  97. package/dist/heart/kicks.js +2 -20
  98. package/dist/heart/machine-identity.js +161 -0
  99. package/dist/heart/mcp/mcp-server.js +653 -0
  100. package/dist/heart/migrate-config.js +127 -0
  101. package/dist/heart/model-capabilities.js +59 -0
  102. package/dist/heart/outlook/outlook-http-hooks.js +64 -0
  103. package/dist/heart/outlook/outlook-http-response.js +7 -0
  104. package/dist/heart/outlook/outlook-http-routes.js +232 -0
  105. package/dist/heart/outlook/outlook-http-static.js +99 -0
  106. package/dist/heart/outlook/outlook-http-transport.js +116 -0
  107. package/dist/heart/outlook/outlook-http.js +99 -0
  108. package/dist/heart/outlook/outlook-read.js +28 -0
  109. package/dist/heart/outlook/outlook-types.js +27 -0
  110. package/dist/heart/outlook/outlook-view.js +194 -0
  111. package/dist/heart/outlook/readers/agent-machine.js +355 -0
  112. package/dist/heart/outlook/readers/continuity-readers.js +332 -0
  113. package/dist/heart/outlook/readers/runtime-readers.js +660 -0
  114. package/dist/heart/outlook/readers/sessions.js +231 -0
  115. package/dist/heart/outlook/readers/shared.js +111 -0
  116. package/dist/heart/progress-story.js +42 -0
  117. package/dist/heart/provider-attempt.js +133 -0
  118. package/dist/heart/provider-binding-resolver.js +240 -0
  119. package/dist/heart/provider-credential-pool.js +395 -0
  120. package/dist/heart/provider-failover.js +135 -0
  121. package/dist/heart/provider-models.js +81 -0
  122. package/dist/heart/provider-ping.js +258 -0
  123. package/dist/heart/provider-state.js +208 -0
  124. package/dist/heart/providers/anthropic-token.js +163 -0
  125. package/dist/heart/providers/anthropic.js +171 -50
  126. package/dist/heart/providers/azure.js +97 -11
  127. package/dist/heart/providers/error-classification.js +63 -0
  128. package/dist/heart/providers/github-copilot.js +135 -0
  129. package/dist/heart/providers/minimax-vlm.js +189 -0
  130. package/dist/heart/providers/minimax.js +23 -6
  131. package/dist/heart/providers/openai-codex.js +33 -23
  132. package/dist/heart/session-activity.js +190 -0
  133. package/dist/heart/session-events.js +727 -0
  134. package/dist/heart/session-transcript.js +162 -0
  135. package/dist/heart/start-of-turn-packet.js +341 -0
  136. package/dist/heart/streaming.js +36 -27
  137. package/dist/heart/sync.js +332 -0
  138. package/dist/heart/target-resolution.js +127 -0
  139. package/dist/heart/tempo.js +93 -0
  140. package/dist/heart/temporal-view.js +41 -0
  141. package/dist/heart/tool-activity-callbacks.js +36 -0
  142. package/dist/heart/tool-description.js +135 -0
  143. package/dist/heart/tool-friction.js +55 -0
  144. package/dist/heart/tool-loop.js +200 -0
  145. package/dist/heart/turn-context.js +358 -0
  146. package/dist/heart/turn-coordinator.js +28 -0
  147. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  148. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  149. package/dist/heart/versioning/ouro-path-installer.js +296 -0
  150. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  151. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  152. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  153. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  154. package/dist/mind/bundle-manifest.js +7 -1
  155. package/dist/mind/context.js +140 -94
  156. package/dist/mind/diary-integrity.js +60 -0
  157. package/dist/mind/{memory.js → diary.js} +84 -96
  158. package/dist/mind/embedding-provider.js +60 -0
  159. package/dist/mind/file-state.js +179 -0
  160. package/dist/mind/first-impressions.js +14 -1
  161. package/dist/mind/friends/channel.js +56 -0
  162. package/dist/mind/friends/group-context.js +144 -0
  163. package/dist/mind/friends/resolver.js +38 -1
  164. package/dist/mind/friends/store-file.js +58 -3
  165. package/dist/mind/friends/trust-explanation.js +74 -0
  166. package/dist/mind/friends/types.js +9 -1
  167. package/dist/mind/journal-index.js +161 -0
  168. package/dist/mind/note-search.js +268 -0
  169. package/dist/mind/obligation-steering.js +221 -0
  170. package/dist/mind/pending.js +74 -7
  171. package/dist/mind/prompt.js +1000 -112
  172. package/dist/mind/provenance-trust.js +26 -0
  173. package/dist/mind/scrutiny.js +173 -0
  174. package/dist/mind/token-estimate.js +8 -12
  175. package/dist/nerves/cli-logging.js +7 -1
  176. package/dist/nerves/coverage/audit-rules.js +15 -6
  177. package/dist/nerves/coverage/audit.js +28 -2
  178. package/dist/nerves/coverage/cli.js +1 -1
  179. package/dist/nerves/coverage/file-completeness.js +83 -5
  180. package/dist/nerves/coverage/run-artifacts.js +1 -1
  181. package/dist/nerves/event-buffer.js +111 -0
  182. package/dist/nerves/index.js +224 -4
  183. package/dist/nerves/observation.js +20 -0
  184. package/dist/nerves/redact.js +79 -0
  185. package/dist/nerves/runtime.js +5 -1
  186. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  187. package/dist/outlook-ui/assets/index-xTdv64BV.js +61 -0
  188. package/dist/outlook-ui/index.html +15 -0
  189. package/dist/repertoire/ado-client.js +15 -56
  190. package/dist/repertoire/ado-semantic.js +11 -10
  191. package/dist/repertoire/api-client.js +97 -0
  192. package/dist/repertoire/bitwarden-store.js +319 -0
  193. package/dist/repertoire/bundle-templates.js +72 -0
  194. package/dist/repertoire/bw-installer.js +79 -0
  195. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  196. package/dist/repertoire/coding/context-pack.js +330 -0
  197. package/dist/repertoire/coding/feedback.js +197 -30
  198. package/dist/repertoire/coding/manager.js +158 -9
  199. package/dist/repertoire/coding/spawner.js +55 -9
  200. package/dist/repertoire/coding/tools.js +170 -7
  201. package/dist/repertoire/commerce-errors.js +109 -0
  202. package/dist/repertoire/commerce-self-test.js +156 -0
  203. package/dist/repertoire/credential-access.js +527 -0
  204. package/dist/repertoire/duffel-client.js +185 -0
  205. package/dist/repertoire/github-client.js +14 -55
  206. package/dist/repertoire/graph-client.js +11 -52
  207. package/dist/repertoire/guardrails.js +375 -0
  208. package/dist/repertoire/mcp-client.js +255 -0
  209. package/dist/repertoire/mcp-manager.js +305 -0
  210. package/dist/repertoire/mcp-tools.js +63 -0
  211. package/dist/repertoire/shell-sessions.js +133 -0
  212. package/dist/repertoire/skills.js +15 -24
  213. package/dist/repertoire/stripe-client.js +131 -0
  214. package/dist/repertoire/tasks/board.js +43 -5
  215. package/dist/repertoire/tasks/fix.js +182 -0
  216. package/dist/repertoire/tasks/index.js +28 -10
  217. package/dist/repertoire/tasks/lifecycle.js +2 -2
  218. package/dist/repertoire/tasks/parser.js +3 -2
  219. package/dist/repertoire/tasks/scanner.js +194 -37
  220. package/dist/repertoire/tasks/transitions.js +16 -79
  221. package/dist/repertoire/tool-results.js +29 -0
  222. package/dist/repertoire/tools-attachments.js +316 -0
  223. package/dist/repertoire/tools-base.js +45 -771
  224. package/dist/repertoire/tools-bluebubbles.js +1 -0
  225. package/dist/repertoire/tools-bridge.js +141 -0
  226. package/dist/repertoire/tools-bundle.js +984 -0
  227. package/dist/repertoire/tools-config.js +185 -0
  228. package/dist/repertoire/tools-continuity.js +248 -0
  229. package/dist/repertoire/tools-credential.js +182 -0
  230. package/dist/repertoire/tools-files.js +342 -0
  231. package/dist/repertoire/tools-flight.js +224 -0
  232. package/dist/repertoire/tools-flow.js +105 -0
  233. package/dist/repertoire/tools-github.js +1 -7
  234. package/dist/repertoire/tools-notes.js +376 -0
  235. package/dist/repertoire/tools-session.js +739 -0
  236. package/dist/repertoire/tools-shell.js +120 -0
  237. package/dist/repertoire/tools-stripe.js +180 -0
  238. package/dist/repertoire/tools-surface.js +243 -0
  239. package/dist/repertoire/tools-teams.js +12 -62
  240. package/dist/repertoire/tools-travel.js +125 -0
  241. package/dist/repertoire/tools-user-profile.js +144 -0
  242. package/dist/repertoire/tools-vault.js +110 -0
  243. package/dist/repertoire/tools.js +144 -138
  244. package/dist/repertoire/travel-api-client.js +360 -0
  245. package/dist/repertoire/user-profile.js +118 -0
  246. package/dist/repertoire/vault-setup.js +241 -0
  247. package/dist/scripts/claude-code-hook.js +41 -0
  248. package/dist/scripts/claude-code-stop-hook.js +47 -0
  249. package/dist/senses/attention-queue.js +116 -0
  250. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  251. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  252. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +225 -9
  253. package/dist/senses/bluebubbles/entry.js +13 -0
  254. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  255. package/dist/senses/bluebubbles/index.js +1590 -0
  256. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  257. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
  258. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  259. package/dist/senses/bluebubbles/replay.js +129 -0
  260. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  261. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  262. package/dist/senses/cli/bracketed-paste.js +82 -0
  263. package/dist/senses/cli/image-paste.js +287 -0
  264. package/dist/senses/cli/image-ref-navigation.js +75 -0
  265. package/dist/senses/cli/ink-app.js +156 -0
  266. package/dist/senses/cli/inline-diff.js +64 -0
  267. package/dist/senses/cli/input-keys.js +174 -0
  268. package/dist/senses/cli/kill-ring.js +86 -0
  269. package/dist/senses/cli/message-list.js +51 -0
  270. package/dist/senses/cli/ouro-tui.js +605 -0
  271. package/dist/senses/cli/spinner-imperative.js +135 -0
  272. package/dist/senses/cli/spinner.js +101 -0
  273. package/dist/senses/cli/status-line.js +60 -0
  274. package/dist/senses/cli/streaming-markdown.js +526 -0
  275. package/dist/senses/cli/tool-display.js +83 -0
  276. package/dist/senses/cli/tool-render.js +85 -0
  277. package/dist/senses/cli/tui-store.js +240 -0
  278. package/dist/senses/cli/virtual-list.js +35 -0
  279. package/dist/senses/cli-entry.js +1 -1
  280. package/dist/senses/cli-layout.js +187 -0
  281. package/dist/senses/cli.js +603 -246
  282. package/dist/senses/commands.js +65 -1
  283. package/dist/senses/continuity.js +94 -0
  284. package/dist/senses/habit-turn-message.js +108 -0
  285. package/dist/senses/inner-dialog-worker.js +112 -19
  286. package/dist/senses/inner-dialog.js +633 -86
  287. package/dist/senses/pipeline.js +567 -0
  288. package/dist/senses/shared-turn.js +199 -0
  289. package/dist/senses/surface-tool.js +68 -0
  290. package/dist/senses/teams.js +665 -160
  291. package/dist/senses/trust-gate.js +112 -2
  292. package/package.json +29 -7
  293. package/skills/agent-commerce.md +106 -0
  294. package/skills/browser-navigation.md +110 -0
  295. package/skills/commerce-setup-guide.md +116 -0
  296. package/skills/commerce-setup.md +84 -0
  297. package/skills/configure-dev-tools.md +81 -0
  298. package/skills/travel-planning.md +138 -0
  299. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  300. package/dist/heart/daemon/subagent-installer.js +0 -134
  301. package/dist/mind/associative-recall.js +0 -197
  302. package/dist/senses/bluebubbles-entry.js +0 -11
  303. package/dist/senses/bluebubbles.js +0 -548
  304. package/dist/senses/debug-activity.js +0 -127
  305. package/subagents/README.md +0 -73
  306. package/subagents/work-doer.md +0 -235
  307. package/subagents/work-merger.md +0 -618
  308. package/subagents/work-planner.md +0 -382
  309. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  310. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  311. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  312. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  313. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  314. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  315. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  316. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  317. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  318. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  319. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  320. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  321. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  322. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  323. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  324. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deliverCrossChatMessage = deliverCrossChatMessage;
4
+ const types_1 = require("../mind/friends/types");
5
+ const runtime_1 = require("../nerves/runtime");
6
+ function buildPendingEnvelope(request, agentName, now) {
7
+ return {
8
+ from: agentName,
9
+ friendId: request.friendId,
10
+ channel: request.channel,
11
+ key: request.key,
12
+ content: request.content,
13
+ timestamp: now,
14
+ };
15
+ }
16
+ function queueForLater(request, deps, detail) {
17
+ deps.queuePending(buildPendingEnvelope(request, deps.agentName, (deps.now ?? Date.now)()));
18
+ return {
19
+ status: "queued_for_later",
20
+ detail,
21
+ };
22
+ }
23
+ function isExplicitlyAuthorized(request) {
24
+ return request.intent === "explicit_cross_chat"
25
+ && Boolean(request.authorizingSession)
26
+ && (0, types_1.isTrustedLevel)(request.authorizingSession?.trustLevel);
27
+ }
28
+ async function deliverCrossChatMessage(request, deps) {
29
+ (0, runtime_1.emitNervesEvent)({
30
+ component: "engine",
31
+ event: "engine.cross_chat_delivery_start",
32
+ message: "resolving cross-chat delivery",
33
+ meta: {
34
+ friendId: request.friendId,
35
+ channel: request.channel,
36
+ key: request.key,
37
+ intent: request.intent,
38
+ authorizingTrustLevel: request.authorizingSession?.trustLevel ?? null,
39
+ },
40
+ });
41
+ if (!isExplicitlyAuthorized(request) && request.intent !== "generic_outreach") {
42
+ const result = {
43
+ status: "blocked",
44
+ detail: "cross-chat delivery requires a trusted asking session or generic outreach intent",
45
+ };
46
+ (0, runtime_1.emitNervesEvent)({
47
+ level: "warn",
48
+ component: "engine",
49
+ event: "engine.cross_chat_delivery_end",
50
+ message: "blocked cross-chat delivery",
51
+ meta: {
52
+ friendId: request.friendId,
53
+ channel: request.channel,
54
+ key: request.key,
55
+ status: result.status,
56
+ },
57
+ });
58
+ return result;
59
+ }
60
+ const deliverer = deps.deliverers?.[request.channel];
61
+ if (!deliverer) {
62
+ const result = queueForLater(request, deps, "live delivery unavailable right now; queued for the next active turn");
63
+ (0, runtime_1.emitNervesEvent)({
64
+ component: "engine",
65
+ event: "engine.cross_chat_delivery_end",
66
+ message: "queued explicit cross-chat delivery because no live deliverer was available",
67
+ meta: {
68
+ friendId: request.friendId,
69
+ channel: request.channel,
70
+ key: request.key,
71
+ status: result.status,
72
+ },
73
+ });
74
+ return result;
75
+ }
76
+ try {
77
+ const direct = await deliverer(request);
78
+ if (direct.status === "delivered_now" || direct.status === "blocked" || direct.status === "failed") {
79
+ const result = {
80
+ status: direct.status,
81
+ detail: direct.detail,
82
+ };
83
+ (0, runtime_1.emitNervesEvent)({
84
+ level: result.status === "failed" ? "error" : result.status === "blocked" ? "warn" : "info",
85
+ component: "engine",
86
+ event: "engine.cross_chat_delivery_end",
87
+ message: "completed direct cross-chat delivery resolution",
88
+ meta: {
89
+ friendId: request.friendId,
90
+ channel: request.channel,
91
+ key: request.key,
92
+ status: result.status,
93
+ },
94
+ });
95
+ return result;
96
+ }
97
+ const result = queueForLater(request, deps, direct.detail.trim() || "live delivery unavailable right now; queued for the next active turn");
98
+ (0, runtime_1.emitNervesEvent)({
99
+ component: "engine",
100
+ event: "engine.cross_chat_delivery_end",
101
+ message: "queued explicit cross-chat delivery after adapter reported unavailability",
102
+ meta: {
103
+ friendId: request.friendId,
104
+ channel: request.channel,
105
+ key: request.key,
106
+ status: result.status,
107
+ },
108
+ });
109
+ return result;
110
+ }
111
+ catch (error) {
112
+ const result = {
113
+ status: "failed",
114
+ detail: error instanceof Error ? error.message : String(error),
115
+ };
116
+ (0, runtime_1.emitNervesEvent)({
117
+ level: "error",
118
+ component: "engine",
119
+ event: "engine.cross_chat_delivery_end",
120
+ message: "cross-chat delivery threw unexpectedly",
121
+ meta: {
122
+ friendId: request.friendId,
123
+ channel: request.channel,
124
+ key: request.key,
125
+ status: result.status,
126
+ reason: result.detail,
127
+ },
128
+ });
129
+ return result;
130
+ }
131
+ }
@@ -0,0 +1,561 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.checkAgentConfig = checkAgentConfig;
37
+ exports.checkAgentConfigWithProviderHealth = checkAgentConfigWithProviderHealth;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const identity_1 = require("../identity");
41
+ const runtime_1 = require("../../nerves/runtime");
42
+ const provider_models_1 = require("../provider-models");
43
+ const machine_identity_1 = require("../machine-identity");
44
+ const provider_state_1 = require("../provider-state");
45
+ const provider_credential_pool_1 = require("../provider-credential-pool");
46
+ function isAgentProvider(value) {
47
+ return Object.prototype.hasOwnProperty.call(identity_1.PROVIDER_CREDENTIALS, value);
48
+ }
49
+ function agentRootFor(agentName, bundlesRoot) {
50
+ return path.join(bundlesRoot, `${agentName}.ouro`);
51
+ }
52
+ function configPathFor(agentName, bundlesRoot) {
53
+ return path.join(agentRootFor(agentName, bundlesRoot), "agent.json");
54
+ }
55
+ function formatFacingList(facings) {
56
+ if (facings.length === 1)
57
+ return facings[0];
58
+ return `${facings.slice(0, -1).join(", ")} and ${facings[facings.length - 1]}`;
59
+ }
60
+ function selectedProviderMap(selectedProviders) {
61
+ const byProvider = new Map();
62
+ for (const selected of selectedProviders) {
63
+ const facings = byProvider.get(selected.provider) ?? [];
64
+ facings.push(selected.facing);
65
+ byProvider.set(selected.provider, facings);
66
+ }
67
+ return byProvider;
68
+ }
69
+ function resolveFacingProvider(parsed, facing, agentName, agentJsonPath) {
70
+ const raw = parsed[facing];
71
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
72
+ return {
73
+ ok: false,
74
+ result: {
75
+ ok: false,
76
+ error: `agent.json for '${agentName}' is missing ${facing}.provider`,
77
+ fix: `Add ${facing}: { provider, model } to ${agentJsonPath}. Valid providers: ${Object.keys(identity_1.PROVIDER_CREDENTIALS).join(", ")}`,
78
+ },
79
+ };
80
+ }
81
+ const provider = raw.provider;
82
+ if (typeof provider !== "string" || provider.length === 0) {
83
+ return {
84
+ ok: false,
85
+ result: {
86
+ ok: false,
87
+ error: `agent.json for '${agentName}' is missing ${facing}.provider`,
88
+ fix: `Set ${facing}.provider in ${agentJsonPath}. Valid providers: ${Object.keys(identity_1.PROVIDER_CREDENTIALS).join(", ")}`,
89
+ },
90
+ };
91
+ }
92
+ if (!isAgentProvider(provider)) {
93
+ return {
94
+ ok: false,
95
+ result: {
96
+ ok: false,
97
+ error: `Unknown provider '${provider}' in ${facing}.provider for '${agentName}'`,
98
+ fix: `Set ${facing}.provider to one of: ${Object.keys(identity_1.PROVIDER_CREDENTIALS).join(", ")}`,
99
+ },
100
+ };
101
+ }
102
+ return { ok: true, selected: { facing, provider } };
103
+ }
104
+ function resolveSelectedProviders(parsed, agentName, agentJsonPath) {
105
+ const hasHumanFacing = parsed.humanFacing !== undefined;
106
+ const hasAgentFacing = parsed.agentFacing !== undefined;
107
+ if (!hasHumanFacing && !hasAgentFacing && typeof parsed.provider === "string") {
108
+ if (!isAgentProvider(parsed.provider)) {
109
+ return {
110
+ ok: false,
111
+ result: {
112
+ ok: false,
113
+ error: `Unknown provider '${parsed.provider}' in agent.json for '${agentName}'`,
114
+ fix: `Set provider to one of: ${Object.keys(identity_1.PROVIDER_CREDENTIALS).join(", ")}`,
115
+ },
116
+ };
117
+ }
118
+ return { ok: true, selectedProviders: [{ facing: "provider", provider: parsed.provider }] };
119
+ }
120
+ const human = resolveFacingProvider(parsed, "humanFacing", agentName, agentJsonPath);
121
+ if (!human.ok)
122
+ return human;
123
+ const agent = resolveFacingProvider(parsed, "agentFacing", agentName, agentJsonPath);
124
+ if (!agent.ok)
125
+ return agent;
126
+ return { ok: true, selectedProviders: [human.selected, agent.selected] };
127
+ }
128
+ function readConfigCheckContext(agentName, bundlesRoot, secretsRoot) {
129
+ const agentJsonPath = path.join(bundlesRoot, `${agentName}.ouro`, "agent.json");
130
+ let raw;
131
+ try {
132
+ raw = fs.readFileSync(agentJsonPath, "utf-8");
133
+ }
134
+ catch {
135
+ return {
136
+ ok: false,
137
+ result: {
138
+ ok: false,
139
+ error: `agent.json not found at ${agentJsonPath}`,
140
+ fix: `Run 'ouro hatch ${agentName}' to create the agent bundle, or verify that ${bundlesRoot}/${agentName}.ouro/ exists.`,
141
+ },
142
+ };
143
+ }
144
+ let parsed;
145
+ try {
146
+ parsed = JSON.parse(raw);
147
+ }
148
+ catch {
149
+ return {
150
+ ok: false,
151
+ result: {
152
+ ok: false,
153
+ error: `agent.json at ${agentJsonPath} contains invalid JSON`,
154
+ fix: `Open ${agentJsonPath} and fix the JSON syntax.`,
155
+ },
156
+ };
157
+ }
158
+ // Disabled agents are valid — they just won't run
159
+ if (parsed.enabled === false) {
160
+ return {
161
+ ok: true,
162
+ context: {
163
+ agentJsonPath,
164
+ secretsJsonPath: path.join(secretsRoot, agentName, "secrets.json"),
165
+ providers: {},
166
+ selectedProviders: [],
167
+ },
168
+ };
169
+ }
170
+ const selected = resolveSelectedProviders(parsed, agentName, agentJsonPath);
171
+ if (!selected.ok)
172
+ return selected;
173
+ const secretsJsonPath = path.join(secretsRoot, agentName, "secrets.json");
174
+ let secrets;
175
+ try {
176
+ const secretsRaw = fs.readFileSync(secretsJsonPath, "utf-8");
177
+ secrets = JSON.parse(secretsRaw);
178
+ }
179
+ catch {
180
+ const firstProvider = selected.selectedProviders[0].provider;
181
+ return {
182
+ ok: false,
183
+ result: {
184
+ ok: false,
185
+ error: `secrets.json not found or unreadable at ${secretsJsonPath}`,
186
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${firstProvider}' to configure credentials, or create ${secretsJsonPath} with providers.${firstProvider} credentials.`,
187
+ },
188
+ };
189
+ }
190
+ const providers = secrets.providers;
191
+ if (!providers || typeof providers !== "object" || Array.isArray(providers)) {
192
+ const firstProvider = selected.selectedProviders[0].provider;
193
+ return {
194
+ ok: false,
195
+ result: {
196
+ ok: false,
197
+ error: `secrets.json for '${agentName}' is missing providers object`,
198
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${firstProvider}' to configure credentials.`,
199
+ },
200
+ };
201
+ }
202
+ return {
203
+ ok: true,
204
+ context: {
205
+ agentJsonPath,
206
+ secretsJsonPath,
207
+ providers,
208
+ selectedProviders: selected.selectedProviders,
209
+ },
210
+ };
211
+ }
212
+ function readAgentConfigForProviderState(agentName, bundlesRoot) {
213
+ const agentJsonPath = configPathFor(agentName, bundlesRoot);
214
+ let raw;
215
+ try {
216
+ raw = fs.readFileSync(agentJsonPath, "utf-8");
217
+ }
218
+ catch {
219
+ return {
220
+ ok: false,
221
+ result: {
222
+ ok: false,
223
+ error: `agent.json not found at ${agentJsonPath}`,
224
+ fix: `Run 'ouro hatch ${agentName}' to create the agent bundle, or verify that ${bundlesRoot}/${agentName}.ouro/ exists.`,
225
+ },
226
+ };
227
+ }
228
+ let parsed;
229
+ try {
230
+ parsed = JSON.parse(raw);
231
+ }
232
+ catch {
233
+ return {
234
+ ok: false,
235
+ result: {
236
+ ok: false,
237
+ error: `agent.json at ${agentJsonPath} contains invalid JSON`,
238
+ fix: `Open ${agentJsonPath} and fix the JSON syntax.`,
239
+ },
240
+ };
241
+ }
242
+ if (parsed.enabled === false) {
243
+ return { ok: true, disabled: true, agentJsonPath, parsed };
244
+ }
245
+ return { ok: true, disabled: false, agentJsonPath, parsed };
246
+ }
247
+ function readFacingForBootstrap(parsed, facing, agentName, agentJsonPath) {
248
+ const providerResult = resolveFacingProvider(parsed, facing, agentName, agentJsonPath);
249
+ if (!providerResult.ok) {
250
+ return {
251
+ ok: false,
252
+ result: {
253
+ ok: false,
254
+ error: providerResult.result.error,
255
+ fix: `Run 'ouro use --agent ${agentName} --lane ${facing === "humanFacing" ? "outward" : "inner"} --provider <provider> --model <model>' to configure this machine's provider binding.`,
256
+ },
257
+ };
258
+ }
259
+ const raw = parsed[facing];
260
+ const model = typeof raw.model === "string" && raw.model.trim().length > 0
261
+ ? raw.model.trim()
262
+ : (0, provider_models_1.getDefaultModelForProvider)(providerResult.selected.provider);
263
+ return { ok: true, provider: providerResult.selected.provider, model };
264
+ }
265
+ function bootstrapMissingProviderState(input) {
266
+ const outward = readFacingForBootstrap(input.parsed, "humanFacing", input.agentName, input.agentJsonPath);
267
+ if (!outward.ok)
268
+ return { ok: false, error: outward.result.error, fix: outward.result.fix };
269
+ const inner = readFacingForBootstrap(input.parsed, "agentFacing", input.agentName, input.agentJsonPath);
270
+ if (!inner.ok)
271
+ return { ok: false, error: inner.result.error, fix: inner.result.fix };
272
+ const now = new Date();
273
+ const homeDir = (0, provider_credential_pool_1.providerCredentialHomeDirFromSecretsRoot)(input.secretsRoot);
274
+ const machine = (0, machine_identity_1.loadOrCreateMachineIdentity)({ homeDir, now: () => now });
275
+ const state = (0, provider_state_1.bootstrapProviderStateFromAgentConfig)({
276
+ machineId: machine.machineId,
277
+ now,
278
+ agentConfig: {
279
+ humanFacing: { provider: outward.provider, model: outward.model },
280
+ agentFacing: { provider: inner.provider, model: inner.model },
281
+ },
282
+ });
283
+ const agentRoot = agentRootFor(input.agentName, input.bundlesRoot);
284
+ (0, provider_state_1.writeProviderState)(agentRoot, state);
285
+ (0, runtime_1.emitNervesEvent)({
286
+ component: "daemon",
287
+ event: "daemon.provider_state_bootstrapped",
288
+ message: "bootstrapped local provider state from agent config",
289
+ meta: { agent: input.agentName, agentRoot },
290
+ });
291
+ return { ok: true, agentRoot, state };
292
+ }
293
+ function readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, secretsRoot) {
294
+ const configResult = readAgentConfigForProviderState(agentName, bundlesRoot);
295
+ if (!configResult.ok)
296
+ return { ok: false, result: configResult.result };
297
+ if (configResult.disabled)
298
+ return { ok: true, disabled: true };
299
+ const agentRoot = agentRootFor(agentName, bundlesRoot);
300
+ const stateResult = (0, provider_state_1.readProviderState)(agentRoot);
301
+ if (stateResult.ok) {
302
+ return { ok: true, disabled: false, agentRoot, state: stateResult.state };
303
+ }
304
+ if (stateResult.reason === "invalid") {
305
+ return {
306
+ ok: false,
307
+ result: {
308
+ ok: false,
309
+ error: `provider state for ${agentName} is invalid at ${stateResult.statePath}: ${stateResult.error}`,
310
+ fix: `Run 'ouro use --agent ${agentName} --lane outward --provider <provider> --model <model> --force' to rewrite this machine's provider binding.`,
311
+ },
312
+ };
313
+ }
314
+ const bootstrap = bootstrapMissingProviderState({
315
+ agentName,
316
+ bundlesRoot,
317
+ secretsRoot,
318
+ parsed: configResult.parsed,
319
+ agentJsonPath: configResult.agentJsonPath,
320
+ });
321
+ if (!bootstrap.ok)
322
+ return { ok: false, result: bootstrap };
323
+ return { ok: true, disabled: false, agentRoot: bootstrap.agentRoot, state: bootstrap.state };
324
+ }
325
+ function validateSelectedProviderSecrets(agentName, context) {
326
+ for (const [provider, facings] of selectedProviderMap(context.selectedProviders)) {
327
+ const desc = identity_1.PROVIDER_CREDENTIALS[provider];
328
+ const providerSecrets = context.providers[provider];
329
+ const selectedBy = formatFacingList(facings);
330
+ if (!providerSecrets) {
331
+ return {
332
+ ok: false,
333
+ error: `secrets.json for '${agentName}' is missing providers.${provider} section selected by ${selectedBy}`,
334
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to configure ${provider} credentials.`,
335
+ };
336
+ }
337
+ // Azure special case: managed identity only needs endpoint + deployment.
338
+ if (provider === "azure") {
339
+ const hasEndpoint = typeof providerSecrets.endpoint === "string" && providerSecrets.endpoint.length > 0;
340
+ const hasDeployment = typeof providerSecrets.deployment === "string" && providerSecrets.deployment.length > 0;
341
+ const hasManagedId = typeof providerSecrets.managedIdentityClientId === "string" && providerSecrets.managedIdentityClientId.length > 0;
342
+ if (hasEndpoint && hasDeployment && hasManagedId) {
343
+ continue;
344
+ }
345
+ }
346
+ const missing = desc.required.filter((field) => {
347
+ const val = providerSecrets[field];
348
+ return typeof val !== "string" || val.length === 0;
349
+ });
350
+ if (missing.length > 0) {
351
+ return {
352
+ ok: false,
353
+ error: `secrets.json for '${agentName}' is missing required ${provider} credentials selected by ${selectedBy}: ${missing.join(", ")}`,
354
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to set up ${provider} credentials, or add the missing fields to providers.${provider} in ${context.secretsJsonPath}.`,
355
+ };
356
+ }
357
+ }
358
+ return { ok: true };
359
+ }
360
+ function emitConfigValid(agentName, context, liveProviderCheck) {
361
+ (0, runtime_1.emitNervesEvent)({
362
+ component: "daemon",
363
+ event: "daemon.agent_config_valid",
364
+ message: "agent config validation passed",
365
+ meta: {
366
+ agent: agentName,
367
+ providers: [...selectedProviderMap(context.selectedProviders).keys()],
368
+ liveProviderCheck,
369
+ },
370
+ });
371
+ }
372
+ function providerCredentialConfig(record) {
373
+ return {
374
+ ...record.credentials,
375
+ ...record.config,
376
+ };
377
+ }
378
+ function pingAttemptCount(result) {
379
+ if (Array.isArray(result.attempts))
380
+ return result.attempts.length;
381
+ return undefined;
382
+ }
383
+ function writeLaneReadiness(input) {
384
+ const binding = input.state.lanes[input.lane];
385
+ const checkedAt = new Date().toISOString();
386
+ input.state.updatedAt = checkedAt;
387
+ input.state.readiness[input.lane] = {
388
+ status: input.status,
389
+ provider: binding.provider,
390
+ model: binding.model,
391
+ checkedAt,
392
+ credentialRevision: input.credentialRevision,
393
+ ...(input.error ? { error: input.error } : {}),
394
+ ...(input.attempts !== undefined ? { attempts: input.attempts } : {}),
395
+ };
396
+ (0, provider_state_1.writeProviderState)(input.agentRoot, input.state);
397
+ }
398
+ function legacyProviderCredentialCandidates(agentName, secretsRoot) {
399
+ const secretsPath = path.join(secretsRoot, agentName, "secrets.json");
400
+ let parsed;
401
+ try {
402
+ parsed = JSON.parse(fs.readFileSync(secretsPath, "utf-8"));
403
+ }
404
+ catch {
405
+ return [];
406
+ }
407
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
408
+ return [];
409
+ const providers = parsed.providers;
410
+ if (!providers || typeof providers !== "object" || Array.isArray(providers))
411
+ return [];
412
+ const candidates = [];
413
+ for (const [providerKey, rawConfig] of Object.entries(providers)) {
414
+ if (!isAgentProvider(providerKey) || !rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
415
+ continue;
416
+ }
417
+ const split = (0, provider_credential_pool_1.splitProviderCredentialFields)(providerKey, rawConfig);
418
+ if (Object.keys(split.credentials).length === 0 && Object.keys(split.config).length === 0)
419
+ continue;
420
+ candidates.push({ provider: providerKey, credentials: split.credentials, config: split.config });
421
+ }
422
+ return candidates;
423
+ }
424
+ function readPoolWithLegacyMigration(agentName, homeDir, secretsRoot) {
425
+ const initial = (0, provider_credential_pool_1.readProviderCredentialPool)(homeDir);
426
+ if (initial.ok || initial.reason === "invalid")
427
+ return initial;
428
+ const candidates = legacyProviderCredentialCandidates(agentName, secretsRoot);
429
+ for (const candidate of candidates) {
430
+ (0, provider_credential_pool_1.upsertProviderCredential)({
431
+ homeDir,
432
+ provider: candidate.provider,
433
+ credentials: candidate.credentials,
434
+ config: candidate.config,
435
+ provenance: {
436
+ source: "legacy-agent-secrets",
437
+ contributedByAgent: agentName,
438
+ },
439
+ });
440
+ }
441
+ return candidates.length > 0 ? (0, provider_credential_pool_1.readProviderCredentialPool)(homeDir) : initial;
442
+ }
443
+ function missingCredentialResult(agentName, lane, provider, model, poolPath) {
444
+ return {
445
+ ok: false,
446
+ error: `${lane} provider ${provider} model ${model} has no credentials in the machine provider pool at ${poolPath}`,
447
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to authenticate this machine, or run 'ouro use --agent ${agentName} --lane ${lane} --provider <provider> --model <model>' to choose a working provider/model.`,
448
+ };
449
+ }
450
+ function invalidPoolResult(agentName, lane, provider, model, pool) {
451
+ return {
452
+ ok: false,
453
+ error: `${lane} provider ${provider} model ${model} cannot read machine provider credentials at ${pool.poolPath}: ${pool.error}`,
454
+ fix: `Fix ${pool.poolPath}, then run 'ouro auth --agent ${agentName} --provider ${provider}' or 'ouro use --agent ${agentName} --lane ${lane} --provider <provider> --model <model> --force'.`,
455
+ };
456
+ }
457
+ function failedPingResult(agentName, lane, provider, model, result) {
458
+ return {
459
+ ok: false,
460
+ error: `${lane} provider ${provider} model ${model} failed live check: ${result.message}`,
461
+ fix: `Run 'ouro auth --agent ${agentName} --provider ${provider}' to refresh credentials, or run 'ouro use --agent ${agentName} --lane ${lane} --provider <provider> --model <model>' to switch this lane.`,
462
+ };
463
+ }
464
+ function credentialRecordForLane(pool, provider) {
465
+ return pool.providers[provider];
466
+ }
467
+ /**
468
+ * Pre-spawn validation: ensures agent.json exists and required secrets are present.
469
+ * Returns `{ ok: true }` when the agent is ready to run, or a descriptive error
470
+ * with an actionable fix message when something is missing.
471
+ */
472
+ function checkAgentConfig(agentName, bundlesRoot, secretsRoot) {
473
+ const contextResult = readConfigCheckContext(agentName, bundlesRoot, secretsRoot);
474
+ if (!contextResult.ok)
475
+ return contextResult.result;
476
+ const context = contextResult.context;
477
+ const structural = validateSelectedProviderSecrets(agentName, context);
478
+ if (!structural.ok)
479
+ return structural;
480
+ emitConfigValid(agentName, context, false);
481
+ return { ok: true };
482
+ }
483
+ async function checkAgentConfigWithProviderHealth(agentName, bundlesRoot, secretsRoot, deps = {}) {
484
+ const stateResult = readOrBootstrapProviderStateForCheck(agentName, bundlesRoot, secretsRoot);
485
+ if (!stateResult.ok)
486
+ return stateResult.result;
487
+ if (stateResult.disabled)
488
+ return { ok: true };
489
+ const ping = deps.pingProvider ?? (await Promise.resolve().then(() => __importStar(require("../provider-ping")))).pingProvider;
490
+ const homeDir = (0, provider_credential_pool_1.providerCredentialHomeDirFromSecretsRoot)(secretsRoot);
491
+ const poolResult = readPoolWithLegacyMigration(agentName, homeDir, secretsRoot);
492
+ const pingGroups = new Map();
493
+ const lanes = ["outward", "inner"];
494
+ for (const lane of lanes) {
495
+ const binding = stateResult.state.lanes[lane];
496
+ if (!poolResult.ok) {
497
+ if (poolResult.reason === "missing") {
498
+ return missingCredentialResult(agentName, lane, binding.provider, binding.model, poolResult.poolPath);
499
+ }
500
+ return invalidPoolResult(agentName, lane, binding.provider, binding.model, {
501
+ ...poolResult,
502
+ reason: "invalid",
503
+ });
504
+ }
505
+ const record = credentialRecordForLane(poolResult.pool, binding.provider);
506
+ if (!record) {
507
+ return missingCredentialResult(agentName, lane, binding.provider, binding.model, poolResult.poolPath);
508
+ }
509
+ const key = `${binding.provider}\0${binding.model}\0${record.revision}`;
510
+ const group = pingGroups.get(key);
511
+ if (group) {
512
+ group.lanes.push(lane);
513
+ }
514
+ else {
515
+ pingGroups.set(key, {
516
+ provider: binding.provider,
517
+ model: binding.model,
518
+ record,
519
+ lanes: [lane],
520
+ });
521
+ }
522
+ }
523
+ for (const group of pingGroups.values()) {
524
+ const result = await ping(group.provider, providerCredentialConfig(group.record), { model: group.model });
525
+ if (!result.ok) {
526
+ for (const lane of group.lanes) {
527
+ writeLaneReadiness({
528
+ agentRoot: stateResult.agentRoot,
529
+ state: stateResult.state,
530
+ lane,
531
+ status: "failed",
532
+ credentialRevision: group.record.revision,
533
+ error: result.message,
534
+ attempts: pingAttemptCount(result),
535
+ });
536
+ }
537
+ return failedPingResult(agentName, group.lanes[0], group.provider, group.model, result);
538
+ }
539
+ for (const lane of group.lanes) {
540
+ writeLaneReadiness({
541
+ agentRoot: stateResult.agentRoot,
542
+ state: stateResult.state,
543
+ lane,
544
+ status: "ready",
545
+ credentialRevision: group.record.revision,
546
+ attempts: pingAttemptCount(result),
547
+ });
548
+ }
549
+ }
550
+ (0, runtime_1.emitNervesEvent)({
551
+ component: "daemon",
552
+ event: "daemon.agent_config_valid",
553
+ message: "agent config validation passed",
554
+ meta: {
555
+ agent: agentName,
556
+ providers: [...new Set([...pingGroups.values()].map((group) => group.provider))],
557
+ liveProviderCheck: true,
558
+ },
559
+ });
560
+ return { ok: true };
561
+ }