@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,554 @@
1
+ "use strict";
2
+ /**
3
+ * Agentic repair flow for degraded agents detected during `ouro up`.
4
+ *
5
+ * Runs known local repair prompts first, then offers AI-assisted diagnosis
6
+ * when no local repair was attempted and a working LLM provider is available.
7
+ * This is a lightweight integration: one diagnostic LLM call, not a chat loop.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.createAgenticDiagnosisProviderRuntime = createAgenticDiagnosisProviderRuntime;
44
+ exports.runAgenticRepair = runAgenticRepair;
45
+ exports.shouldFireRepairGuide = shouldFireRepairGuide;
46
+ exports.loadRepairGuideContent = loadRepairGuideContent;
47
+ exports.parseRepairProposals = parseRepairProposals;
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const runtime_1 = require("../../nerves/runtime");
51
+ const interactive_repair_1 = require("./interactive-repair");
52
+ const identity_1 = require("../identity");
53
+ const provider_ping_1 = require("../provider-ping");
54
+ const readiness_repair_1 = require("./readiness-repair");
55
+ function buildSystemPrompt(degraded) {
56
+ const agentList = degraded
57
+ .map((d) => `- ${d.agent}: error="${d.errorReason}", hint="${d.fixHint}"`)
58
+ .join("\n");
59
+ return [
60
+ "You are a diagnostic assistant for the Ouroboros agent daemon.",
61
+ "The daemon detected degraded agents during startup.",
62
+ "Analyze the errors below and provide a concise diagnosis with suggested fixes.",
63
+ "",
64
+ "Degraded agents:",
65
+ agentList,
66
+ "",
67
+ "Keep your response brief and actionable. Focus on the most likely root cause",
68
+ "and the simplest fix the user can apply.",
69
+ ].join("\n");
70
+ }
71
+ function buildUserMessage(degraded, logsTail, driftFindings = [], syncFindings = []) {
72
+ const agentDetails = degraded
73
+ .map((d) => `Agent: ${d.agent}\n Error: ${d.errorReason}\n Fix hint: ${d.fixHint}`)
74
+ .join("\n\n");
75
+ const sections = [
76
+ "Here are the degraded agents and recent daemon logs:",
77
+ "",
78
+ agentDetails,
79
+ "",
80
+ "Recent daemon logs:",
81
+ logsTail,
82
+ ];
83
+ // Layer 3: thread Layer 4's structured drift findings into the prompt as
84
+ // a JSON block. The `diagnose-bootstrap-drift` skill (loaded into the
85
+ // system prompt by `buildSystemPromptWithRepairGuide`) instructs the LLM
86
+ // how to read this shape and what `ouro use` repair to propose.
87
+ if (driftFindings.length > 0) {
88
+ sections.push("", "driftFindings (DriftFinding[]):", "```json", JSON.stringify(driftFindings, null, 2), "```");
89
+ }
90
+ // Layer 3: thread Layer 2's structured sync-probe findings into the
91
+ // prompt as a JSON block. `diagnose-broken-remote` (auth/404/network/
92
+ // timeout-hard) and `diagnose-sync-blocked` (dirty/non-fast-forward/
93
+ // merge-conflict/timeout-soft) consume this shape.
94
+ if (syncFindings.length > 0) {
95
+ sections.push("", "bootSyncFindings (BootSyncProbeFinding[]):", "```json", JSON.stringify(syncFindings, null, 2), "```");
96
+ }
97
+ sections.push("", "What is the most likely cause and how should I fix it?");
98
+ return sections.join("\n");
99
+ }
100
+ function makeInteractiveRepairDeps(deps) {
101
+ return {
102
+ promptInput: deps.promptInput,
103
+ writeStdout: deps.writeStdout,
104
+ /* v8 ignore next -- fallback no-op: tests always inject runAuthFlow; default is for production @preserve */
105
+ runAuthFlow: deps.runAuthFlow ?? (async () => undefined),
106
+ runVaultUnlock: deps.runVaultUnlock,
107
+ skipQueueSummary: deps.skipQueueSummary,
108
+ isTTY: deps.isTTY,
109
+ stdoutColumns: deps.stdoutColumns,
110
+ };
111
+ }
112
+ async function runDeterministicRepair(degraded, deps) {
113
+ return deps.runInteractiveRepair(degraded, makeInteractiveRepairDeps(deps));
114
+ }
115
+ function discoveredProviderModel(provider) {
116
+ const model = provider.providerConfig.model?.trim();
117
+ return model ? model : undefined;
118
+ }
119
+ function createAgenticDiagnosisProviderRuntime(provider) {
120
+ const config = {
121
+ ...provider.providerConfig,
122
+ ...provider.credentials,
123
+ };
124
+ return (0, provider_ping_1.createProviderRuntimeForConfig)(provider.provider, config, {
125
+ model: discoveredProviderModel(provider),
126
+ });
127
+ }
128
+ /**
129
+ * Layer 3: build the system prompt for the diagnostic call. Prepends
130
+ * RepairGuide bundle content (`psyche/SOUL.md`, `psyche/IDENTITY.md`, all
131
+ * skills) when the bundle is present and readable; falls back to today's
132
+ * pre-RepairGuide prompt when the loader returns null.
133
+ */
134
+ function buildSystemPromptWithRepairGuide(degraded, repairGuide) {
135
+ const basePrompt = buildSystemPrompt(degraded);
136
+ if (repairGuide === null)
137
+ return basePrompt;
138
+ const sections = [];
139
+ if (repairGuide.psyche.soul) {
140
+ sections.push("# RepairGuide SOUL\n\n" + repairGuide.psyche.soul);
141
+ }
142
+ if (repairGuide.psyche.identity) {
143
+ sections.push("# RepairGuide IDENTITY\n\n" + repairGuide.psyche.identity);
144
+ }
145
+ for (const [name, body] of Object.entries(repairGuide.skills)) {
146
+ sections.push(`# RepairGuide skill: ${name}\n\n${body}`);
147
+ }
148
+ if (sections.length === 0)
149
+ return basePrompt;
150
+ return [...sections, "---", basePrompt].join("\n\n");
151
+ }
152
+ async function tryAgenticDiagnosis(degraded, provider, deps) {
153
+ const logsTail = deps.readDaemonLogsTail();
154
+ const runtime = deps.createProviderRuntime(provider);
155
+ // Layer 3: prepend RepairGuide bundle content when present. Loader
156
+ // returns null on missing bundle / I/O error — caller silently falls back
157
+ // to today's pre-RepairGuide prompt.
158
+ const repoRoot = deps.repoRootOverride ?? (0, identity_1.getRepoRoot)();
159
+ const repairGuide = loadRepairGuideContent(repoRoot);
160
+ const systemPrompt = buildSystemPromptWithRepairGuide(degraded, repairGuide);
161
+ const userMessage = buildUserMessage(degraded, logsTail, deps.driftFindings, deps.syncFindings);
162
+ const messages = [
163
+ { role: "system", content: systemPrompt },
164
+ { role: "user", content: userMessage },
165
+ ];
166
+ /* v8 ignore start -- no-op callbacks: satisfy interface contract, never invoked by diagnostic call @preserve */
167
+ const noopCallbacks = {
168
+ onModelStart: () => { },
169
+ onModelStreamStart: () => { },
170
+ onTextChunk: () => { },
171
+ onReasoningChunk: () => { },
172
+ onToolStart: () => { },
173
+ onToolEnd: () => { },
174
+ onError: () => { },
175
+ };
176
+ /* v8 ignore stop */
177
+ const result = await runtime.streamTurn({
178
+ messages,
179
+ activeTools: [],
180
+ callbacks: noopCallbacks,
181
+ });
182
+ if (result.content) {
183
+ // Layer 3: when RepairGuide content was prepended, parse the LLM output
184
+ // through the typed-action catalog. If actions are extracted, surface
185
+ // them as structured proposals; otherwise fall back to today's plain
186
+ // text-blob diagnosis. `parseRepairProposals` handles the unparseable
187
+ // case by returning `fallbackBlob` set to the raw output.
188
+ if (repairGuide !== null) {
189
+ const parsed = parseRepairProposals(result.content);
190
+ if (parsed.actions.length > 0) {
191
+ deps.writeStdout("");
192
+ deps.writeStdout("--- RepairGuide proposals ---");
193
+ for (const action of parsed.actions) {
194
+ deps.writeStdout(` • ${action.kind}: ${action.label}`);
195
+ }
196
+ for (const warning of parsed.warnings) {
197
+ deps.writeStdout(` (warning) ${warning}`);
198
+ }
199
+ deps.writeStdout("--- End RepairGuide proposals ---");
200
+ deps.writeStdout("");
201
+ }
202
+ else if (parsed.fallbackBlob !== undefined) {
203
+ deps.writeStdout("");
204
+ deps.writeStdout("--- AI Diagnosis ---");
205
+ deps.writeStdout(parsed.fallbackBlob);
206
+ deps.writeStdout("--- End Diagnosis ---");
207
+ deps.writeStdout("");
208
+ }
209
+ }
210
+ else {
211
+ deps.writeStdout("");
212
+ deps.writeStdout("--- AI Diagnosis ---");
213
+ deps.writeStdout(result.content);
214
+ deps.writeStdout("--- End Diagnosis ---");
215
+ deps.writeStdout("");
216
+ }
217
+ }
218
+ return true;
219
+ }
220
+ async function runAgenticRepair(degraded, deps) {
221
+ (0, runtime_1.emitNervesEvent)({
222
+ level: "info",
223
+ component: "daemon",
224
+ event: "daemon.agentic_repair_start",
225
+ message: "agentic repair flow started",
226
+ meta: { degradedCount: degraded.length },
227
+ });
228
+ if (degraded.length === 0) {
229
+ return { repairsAttempted: false, usedAgentic: false };
230
+ }
231
+ const hasLocalRepair = degraded.some(interactive_repair_1.hasRunnableInteractiveRepair);
232
+ const hasKnownTypedRepair = degraded.some((entry) => (0, readiness_repair_1.isKnownReadinessIssue)(entry.issue));
233
+ const forceDiagnosis = deps.forceDiagnosis === true;
234
+ if (hasLocalRepair) {
235
+ const interactiveResult = await runDeterministicRepair(degraded, deps);
236
+ if (interactiveResult.repairsAttempted) {
237
+ return { repairsAttempted: true, usedAgentic: false };
238
+ }
239
+ if (hasKnownTypedRepair && !forceDiagnosis) {
240
+ return { repairsAttempted: false, usedAgentic: false };
241
+ }
242
+ }
243
+ else if (hasKnownTypedRepair && !forceDiagnosis) {
244
+ return { repairsAttempted: false, usedAgentic: false };
245
+ }
246
+ // Try to discover a working provider for agentic diagnosis
247
+ let discoveredProvider = null;
248
+ try {
249
+ discoveredProvider = await deps.discoverWorkingProvider(degraded[0].agent);
250
+ }
251
+ catch (error) {
252
+ const msg = error instanceof Error ? error.message : String(error);
253
+ (0, runtime_1.emitNervesEvent)({
254
+ level: "warn",
255
+ component: "daemon",
256
+ event: "daemon.agentic_repair_discovery_error",
257
+ message: `provider discovery failed during agentic repair: ${msg}`,
258
+ meta: { error: msg },
259
+ });
260
+ }
261
+ if (!discoveredProvider) {
262
+ // No working provider — fall back to deterministic repair
263
+ (0, runtime_1.emitNervesEvent)({
264
+ level: "info",
265
+ component: "daemon",
266
+ event: "daemon.agentic_repair_no_provider",
267
+ message: "no working provider found, falling back to deterministic repair",
268
+ meta: {},
269
+ });
270
+ if (hasLocalRepair) {
271
+ return { repairsAttempted: false, usedAgentic: false };
272
+ }
273
+ const interactiveResult = await runDeterministicRepair(degraded, deps);
274
+ return { repairsAttempted: interactiveResult.repairsAttempted, usedAgentic: false };
275
+ }
276
+ // Offer agentic diagnosis
277
+ const answer = await deps.promptInput("would you like AI-assisted diagnosis? [y/n] ");
278
+ if (!(0, interactive_repair_1.isAffirmativeAnswer)(answer)) {
279
+ // User declined — fall back to deterministic repair
280
+ (0, runtime_1.emitNervesEvent)({
281
+ level: "info",
282
+ component: "daemon",
283
+ event: "daemon.agentic_repair_declined",
284
+ message: "user declined agentic diagnosis",
285
+ meta: {},
286
+ });
287
+ if (hasLocalRepair) {
288
+ return { repairsAttempted: false, usedAgentic: false };
289
+ }
290
+ const interactiveResult = await runDeterministicRepair(degraded, deps);
291
+ return { repairsAttempted: interactiveResult.repairsAttempted, usedAgentic: false };
292
+ }
293
+ // User accepted — run agentic diagnosis then fall through to deterministic repair
294
+ let usedAgentic = false;
295
+ try {
296
+ usedAgentic = await tryAgenticDiagnosis(degraded, discoveredProvider, deps);
297
+ (0, runtime_1.emitNervesEvent)({
298
+ level: "info",
299
+ component: "daemon",
300
+ event: "daemon.agentic_repair_diagnosis_complete",
301
+ message: "agentic diagnosis completed, proceeding to deterministic repair",
302
+ meta: { provider: discoveredProvider.provider },
303
+ });
304
+ }
305
+ catch (error) {
306
+ const msg = error instanceof Error ? error.message : String(error);
307
+ deps.writeStdout(`AI diagnosis failed: ${msg}`);
308
+ (0, runtime_1.emitNervesEvent)({
309
+ level: "warn",
310
+ component: "daemon",
311
+ event: "daemon.agentic_repair_diagnosis_error",
312
+ message: `agentic diagnosis failed: ${msg}`,
313
+ meta: { error: msg, provider: discoveredProvider.provider },
314
+ });
315
+ }
316
+ // Always fall through to deterministic repair for actionable fixes
317
+ const interactiveResult = hasLocalRepair
318
+ ? { repairsAttempted: false }
319
+ : await runDeterministicRepair(degraded, deps);
320
+ (0, runtime_1.emitNervesEvent)({
321
+ level: "info",
322
+ component: "daemon",
323
+ event: "daemon.agentic_repair_end",
324
+ message: "agentic repair flow completed",
325
+ meta: { usedAgentic, repairsAttempted: interactiveResult.repairsAttempted },
326
+ });
327
+ return { repairsAttempted: interactiveResult.repairsAttempted, usedAgentic };
328
+ }
329
+ // ──────────────────────────────────────────────────────────────────────
330
+ // Layer 3: RepairGuide activation contract
331
+ // ──────────────────────────────────────────────────────────────────────
332
+ /**
333
+ * Threshold for compound typed-degraded findings to activate RepairGuide.
334
+ * Set to 3 (not 2) so that common pairs — vault-locked + provider-auth-needed,
335
+ * for example — do NOT trigger the new path on every boot. Encoded once here;
336
+ * never duplicate at call sites.
337
+ */
338
+ const REPAIR_GUIDE_TYPED_THRESHOLD = 3;
339
+ /**
340
+ * Single decision function for whether to fire the RepairGuide-driven
341
+ * diagnostic flow.
342
+ *
343
+ * Contract (LOCKED, planning O4):
344
+ * - `noRepair: true` → false unconditionally (escape hatch).
345
+ * - `untypedDegraded.length > 0` → true (preserves today's gate at
346
+ * `cli-exec.ts:6706`).
347
+ * - `typedDegraded.length >= REPAIR_GUIDE_TYPED_THRESHOLD` → true (compound
348
+ * stack of typed issues; the new behavior this PR introduces).
349
+ * - Otherwise → false.
350
+ */
351
+ function shouldFireRepairGuide(input) {
352
+ if (input.noRepair)
353
+ return false;
354
+ if (input.untypedDegraded.length > 0)
355
+ return true;
356
+ if (input.typedDegraded.length >= REPAIR_GUIDE_TYPED_THRESHOLD)
357
+ return true;
358
+ return false;
359
+ }
360
+ /**
361
+ * Read `RepairGuide.ouro/{psyche,skills}/*.md` from the given repo root and
362
+ * return a structured shape suitable for prepending to a diagnostic LLM call.
363
+ *
364
+ * Behavior:
365
+ * - Returns `null` if `RepairGuide.ouro/` does not exist at all (graceful: caller
366
+ * should fall back to today's pre-RepairGuide pipeline).
367
+ * - Returns `null` on any I/O error (`readdirSync`/`readFileSync` throws).
368
+ * - Returns a populated `RepairGuideContent` when the bundle exists, even if
369
+ * psyche or skills are partially populated.
370
+ * - Skips files that are not `.md`, are not regular files, or have empty
371
+ * contents.
372
+ * - `skills` map is iterated in alphabetical order so callers can rely on
373
+ * deterministic prompt assembly.
374
+ *
375
+ * The loader is intentionally inline in `agentic-repair.ts` per the planning
376
+ * O5 lock — splitting into its own module is allowed only if the validator
377
+ * grows large.
378
+ */
379
+ function loadRepairGuideContent(repoRoot) {
380
+ const bundleRoot = path.join(repoRoot, "RepairGuide.ouro");
381
+ if (!fs.existsSync(bundleRoot))
382
+ return null;
383
+ try {
384
+ const psyche = {};
385
+ const skills = {};
386
+ const psycheDir = path.join(bundleRoot, "psyche");
387
+ if (fs.existsSync(psycheDir)) {
388
+ const psycheEntries = fs.readdirSync(psycheDir, { withFileTypes: true });
389
+ for (const entry of psycheEntries) {
390
+ if (!entry.isFile() || !entry.name.endsWith(".md"))
391
+ continue;
392
+ const content = fs.readFileSync(path.join(psycheDir, entry.name), "utf-8");
393
+ if (entry.name === "SOUL.md")
394
+ psyche.soul = content;
395
+ else if (entry.name === "IDENTITY.md")
396
+ psyche.identity = content;
397
+ }
398
+ }
399
+ const skillsDir = path.join(bundleRoot, "skills");
400
+ if (fs.existsSync(skillsDir)) {
401
+ const skillEntries = fs.readdirSync(skillsDir, { withFileTypes: true });
402
+ const sorted = skillEntries
403
+ .filter((e) => e.isFile() && e.name.endsWith(".md"))
404
+ .sort((a, b) => a.name.localeCompare(b.name));
405
+ for (const entry of sorted) {
406
+ const content = fs.readFileSync(path.join(skillsDir, entry.name), "utf-8");
407
+ if (content.length === 0)
408
+ continue;
409
+ skills[entry.name] = content;
410
+ }
411
+ }
412
+ return { psyche, skills };
413
+ }
414
+ catch {
415
+ // Best-effort: any I/O error in the bundle leads to null and the caller
416
+ // falls back to today's pre-RepairGuide diagnostic prompt.
417
+ return null;
418
+ }
419
+ }
420
+ // ──────────────────────────────────────────────────────────────────────
421
+ // Layer 3: RepairGuide LLM output parser → typed `RepairAction[]`
422
+ // ──────────────────────────────────────────────────────────────────────
423
+ /**
424
+ * The set of `RepairActionKind` literals the typed catalog recognizes.
425
+ * Encoded once here; the parser uses this for membership checks. Any other
426
+ * kind in the LLM output is dropped with a warning.
427
+ */
428
+ const KNOWN_REPAIR_ACTION_KINDS = new Set([
429
+ "vault-create",
430
+ "vault-unlock",
431
+ "vault-replace",
432
+ "vault-recover",
433
+ "provider-auth",
434
+ "provider-retry",
435
+ "provider-use",
436
+ ]);
437
+ function extractFirstJsonBlock(text) {
438
+ // Look for a triple-backtick fence labeled `json` and grab its body.
439
+ const fenceMatch = text.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
440
+ if (fenceMatch)
441
+ return fenceMatch[1];
442
+ // Fallback: the LLM may have emitted a bare JSON object (no fence).
443
+ const objectMatch = text.match(/\{[\s\S]*\}/);
444
+ if (objectMatch)
445
+ return objectMatch[0];
446
+ return null;
447
+ }
448
+ function isPlainObject(value) {
449
+ return typeof value === "object" && value !== null && !Array.isArray(value);
450
+ }
451
+ /**
452
+ * Parse a single LLM-emitted action object into a typed `RepairAction`. Returns
453
+ * `null` when the entry is shaped wrong — the caller logs a warning and drops
454
+ * it. The parser backfills `label`, `command`, and `actor` so the result plugs
455
+ * into the existing interactive-repair surface without further massaging.
456
+ */
457
+ function buildRepairAction(entry) {
458
+ const kind = entry.kind;
459
+ if (typeof kind !== "string")
460
+ return null;
461
+ if (!KNOWN_REPAIR_ACTION_KINDS.has(kind))
462
+ return null;
463
+ const reason = typeof entry.reason === "string" ? entry.reason : "(no reason given)";
464
+ const agent = typeof entry.agent === "string" ? entry.agent : "(unknown agent)";
465
+ const label = `RepairGuide: ${kind} for ${agent}`;
466
+ const command = `# ${kind} (${agent}): ${reason}`;
467
+ switch (kind) {
468
+ case "provider-auth": {
469
+ const provider = typeof entry.provider === "string" ? entry.provider : "anthropic";
470
+ return {
471
+ kind: "provider-auth",
472
+ label,
473
+ command,
474
+ actor: "human-required",
475
+ provider: provider,
476
+ };
477
+ }
478
+ case "provider-use": {
479
+ // `provider-use` may carry an optional `lane` — pass it through when
480
+ // present and validly typed (`outward` or `inner`).
481
+ const lane = entry.lane === "outward" || entry.lane === "inner" ? entry.lane : undefined;
482
+ const action = {
483
+ kind: "provider-use",
484
+ label,
485
+ command,
486
+ actor: "human-choice",
487
+ ...(lane ? { lane } : {}),
488
+ };
489
+ return action;
490
+ }
491
+ case "vault-create":
492
+ case "vault-unlock":
493
+ case "vault-replace":
494
+ case "vault-recover":
495
+ case "provider-retry": {
496
+ return {
497
+ kind: kind,
498
+ label,
499
+ command,
500
+ actor: "human-required",
501
+ };
502
+ }
503
+ /* v8 ignore next 4 -- exhaustiveness guard: unreachable since membership
504
+ * was checked above; left in place to satisfy `never` on future
505
+ * RepairActionKind extensions. @preserve */
506
+ default: {
507
+ return null;
508
+ }
509
+ }
510
+ }
511
+ /**
512
+ * Parse RepairGuide LLM output. The persona content (`SOUL.md`) instructs the
513
+ * model to emit exactly one ```json fenced block containing
514
+ * `{ actions: RepairAction[], notes?: string[] }`. The parser extracts that
515
+ * block, walks `actions[]`, drops entries with unknown kinds (with warnings),
516
+ * and falls back to the raw output when no JSON can be extracted at all
517
+ * (preserving today's text-blob behavior).
518
+ */
519
+ function parseRepairProposals(llmOutput) {
520
+ const block = extractFirstJsonBlock(llmOutput);
521
+ if (block === null) {
522
+ return { actions: [], warnings: [], fallbackBlob: llmOutput };
523
+ }
524
+ let parsed;
525
+ try {
526
+ parsed = JSON.parse(block);
527
+ }
528
+ catch {
529
+ return { actions: [], warnings: [], fallbackBlob: llmOutput };
530
+ }
531
+ if (!isPlainObject(parsed)) {
532
+ return { actions: [], warnings: [] };
533
+ }
534
+ const rawActions = parsed.actions;
535
+ if (!Array.isArray(rawActions)) {
536
+ return { actions: [], warnings: [] };
537
+ }
538
+ const actions = [];
539
+ const warnings = [];
540
+ for (const entry of rawActions) {
541
+ if (!isPlainObject(entry)) {
542
+ warnings.push(`dropped non-object entry from actions[]: ${JSON.stringify(entry)}`);
543
+ continue;
544
+ }
545
+ const built = buildRepairAction(entry);
546
+ if (built === null) {
547
+ const kindLabel = typeof entry.kind === "string" ? entry.kind : "(no kind)";
548
+ warnings.push(`dropped action with unknown or missing kind: ${kindLabel}`);
549
+ continue;
550
+ }
551
+ actions.push(built);
552
+ }
553
+ return { actions, warnings };
554
+ }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stringifyBlueBubblesHealthError = stringifyBlueBubblesHealthError;
4
+ exports.redactBlueBubblesHealthDetailForNerves = redactBlueBubblesHealthDetailForNerves;
5
+ exports.formatBlueBubblesHealthcheckFailure = formatBlueBubblesHealthcheckFailure;
6
+ exports.probeBlueBubblesHealth = probeBlueBubblesHealth;
7
+ const runtime_1 = require("../../nerves/runtime");
8
+ const error_classification_1 = require("../providers/error-classification");
9
+ function buildBlueBubblesApiUrl(baseUrl, endpoint, password) {
10
+ const root = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
11
+ const url = new URL(endpoint.replace(/^\//, ""), root);
12
+ url.searchParams.set("password", password);
13
+ return url.toString();
14
+ }
15
+ function stringifyBlueBubblesHealthError(error) {
16
+ if (error instanceof Error) {
17
+ const message = error.message.trim();
18
+ if (message)
19
+ return message;
20
+ return error.name || "unknown";
21
+ }
22
+ const value = String(error).trim();
23
+ return value || "unknown";
24
+ }
25
+ function redactBlueBubblesHealthDetailForNerves(detail) {
26
+ return detail
27
+ .replace(/\bbluebubbles\.password\b/gi, "bluebubbles credential")
28
+ .replace(/\bpassword\b/gi, "credential");
29
+ }
30
+ function blueBubblesHealthStatus(error) {
31
+ return error instanceof Error && typeof error.status === "number"
32
+ ? error.status
33
+ : null;
34
+ }
35
+ function blueBubblesHealthClassification(error) {
36
+ return error instanceof Error ? (0, error_classification_1.classifyHttpError)(error) : "unknown";
37
+ }
38
+ function formatBlueBubblesHealthcheckFailure(serverUrlInput, error) {
39
+ const serverUrl = serverUrlInput.trim() || "configured BlueBubbles server";
40
+ const rawReason = stringifyBlueBubblesHealthError(error);
41
+ const status = blueBubblesHealthStatus(error);
42
+ if (!(error instanceof Error)) {
43
+ return `BlueBubbles health check failed at ${serverUrl}. Check \`bluebubbles.serverUrl\`, confirm the BlueBubbles app/API is running, and inspect daemon logs. Raw error: ${rawReason}`;
44
+ }
45
+ switch (blueBubblesHealthClassification(error)) {
46
+ case "network-error":
47
+ return `Cannot reach BlueBubbles at ${serverUrl}. Check \`bluebubbles.serverUrl\`, confirm the BlueBubbles app/API is running, and verify this machine can reach it. Raw error: ${rawReason}`;
48
+ case "auth-failure":
49
+ return `BlueBubbles auth failed at ${serverUrl} (HTTP ${status}). Check this machine's BlueBubbles attachment with \`ouro connect bluebubbles --agent <agent>\` and confirm the server accepts the password. Raw error: ${rawReason}`;
50
+ case "server-error":
51
+ return `BlueBubbles upstream returned HTTP ${status} at ${serverUrl}. Check the BlueBubbles app/server logs and confirm the upstream API is healthy. Raw error: ${rawReason}`;
52
+ default:
53
+ return `BlueBubbles health check failed at ${serverUrl}${status === null ? "" : ` (HTTP ${status})`}. Check \`bluebubbles.serverUrl\`, the BlueBubbles server configuration, and daemon logs. Raw error: ${rawReason}`;
54
+ }
55
+ }
56
+ async function probeBlueBubblesHealth(input) {
57
+ try {
58
+ const url = buildBlueBubblesApiUrl(input.serverUrl, "/api/v1/message/count", input.password);
59
+ const response = await input.fetchImpl(url, {
60
+ method: "GET",
61
+ signal: AbortSignal.timeout(input.requestTimeoutMs),
62
+ });
63
+ if (!response.ok) {
64
+ const errorText = await response.text().catch(() => "");
65
+ const error = new Error(errorText || "unknown");
66
+ error.status = response.status;
67
+ throw error;
68
+ }
69
+ (0, runtime_1.emitNervesEvent)({
70
+ component: "daemon",
71
+ event: "daemon.bluebubbles_health_probe_checked",
72
+ message: "checked bluebubbles upstream health",
73
+ meta: {
74
+ serverUrl: input.serverUrl,
75
+ ok: true,
76
+ status: response.status,
77
+ },
78
+ });
79
+ return {
80
+ ok: true,
81
+ detail: "upstream reachable",
82
+ reason: null,
83
+ status: response.status,
84
+ classification: null,
85
+ };
86
+ }
87
+ catch (error) {
88
+ const detail = formatBlueBubblesHealthcheckFailure(input.serverUrl, error);
89
+ const reason = stringifyBlueBubblesHealthError(error);
90
+ const status = blueBubblesHealthStatus(error);
91
+ const classification = blueBubblesHealthClassification(error);
92
+ (0, runtime_1.emitNervesEvent)({
93
+ level: "warn",
94
+ component: "daemon",
95
+ event: "daemon.bluebubbles_health_probe_checked",
96
+ message: "checked bluebubbles upstream health",
97
+ meta: {
98
+ serverUrl: input.serverUrl,
99
+ ok: false,
100
+ status,
101
+ reason,
102
+ classification,
103
+ detail: redactBlueBubblesHealthDetailForNerves(detail),
104
+ },
105
+ });
106
+ return {
107
+ ok: false,
108
+ detail,
109
+ reason,
110
+ status,
111
+ classification,
112
+ };
113
+ }
114
+ }
115
+ /* v8 ignore start -- module load observability event */
116
+ (0, runtime_1.emitNervesEvent)({
117
+ component: "daemon",
118
+ event: "daemon.bluebubbles_health_diagnostics_loaded",
119
+ message: "bluebubbles health diagnostics loaded",
120
+ meta: {},
121
+ });
122
+ /* v8 ignore stop */