@ouro.bot/cli 0.1.0-alpha.36 → 0.1.0-alpha.360

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 (326) hide show
  1. package/README.md +194 -184
  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 +2149 -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 +743 -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 +185 -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 +2649 -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 +560 -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 +757 -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 +140 -0
  72. package/dist/heart/daemon/pulse.js +475 -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 +195 -0
  111. package/dist/heart/outlook/readers/agent-machine.js +359 -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 +232 -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 +274 -0
  121. package/dist/heart/provider-models.js +81 -0
  122. package/dist/heart/provider-ping.js +227 -0
  123. package/dist/heart/provider-state.js +208 -0
  124. package/dist/heart/provider-visibility.js +183 -0
  125. package/dist/heart/providers/anthropic-token.js +163 -0
  126. package/dist/heart/providers/anthropic.js +177 -50
  127. package/dist/heart/providers/azure.js +102 -11
  128. package/dist/heart/providers/error-classification.js +63 -0
  129. package/dist/heart/providers/github-copilot.js +145 -0
  130. package/dist/heart/providers/minimax-vlm.js +189 -0
  131. package/dist/heart/providers/minimax.js +28 -6
  132. package/dist/heart/providers/openai-codex.js +38 -23
  133. package/dist/heart/session-activity.js +190 -0
  134. package/dist/heart/session-events.js +855 -0
  135. package/dist/heart/session-transcript.js +167 -0
  136. package/dist/heart/start-of-turn-packet.js +345 -0
  137. package/dist/heart/streaming.js +36 -27
  138. package/dist/heart/sync.js +332 -0
  139. package/dist/heart/target-resolution.js +127 -0
  140. package/dist/heart/tempo.js +93 -0
  141. package/dist/heart/temporal-view.js +41 -0
  142. package/dist/heart/tool-activity-callbacks.js +36 -0
  143. package/dist/heart/tool-description.js +135 -0
  144. package/dist/heart/tool-friction.js +55 -0
  145. package/dist/heart/tool-loop.js +200 -0
  146. package/dist/heart/turn-context.js +362 -0
  147. package/dist/heart/turn-coordinator.js +28 -0
  148. package/dist/heart/{daemon → versioning}/ouro-bot-global-installer.js +1 -1
  149. package/dist/heart/{daemon → versioning}/ouro-bot-wrapper.js +1 -1
  150. package/dist/heart/versioning/ouro-path-installer.js +296 -0
  151. package/dist/heart/versioning/ouro-version-manager.js +295 -0
  152. package/dist/heart/{daemon → versioning}/staged-restart.js +40 -8
  153. package/dist/heart/{daemon → versioning}/update-checker.js +12 -2
  154. package/dist/heart/{daemon → versioning}/update-hooks.js +63 -59
  155. package/dist/mind/bundle-manifest.js +7 -1
  156. package/dist/mind/context.js +141 -94
  157. package/dist/mind/diary-integrity.js +60 -0
  158. package/dist/mind/{memory.js → diary.js} +84 -96
  159. package/dist/mind/embedding-provider.js +60 -0
  160. package/dist/mind/file-state.js +179 -0
  161. package/dist/mind/first-impressions.js +14 -1
  162. package/dist/mind/friends/channel.js +56 -0
  163. package/dist/mind/friends/group-context.js +144 -0
  164. package/dist/mind/friends/resolver.js +38 -1
  165. package/dist/mind/friends/store-file.js +58 -3
  166. package/dist/mind/friends/trust-explanation.js +74 -0
  167. package/dist/mind/friends/types.js +9 -1
  168. package/dist/mind/journal-index.js +161 -0
  169. package/dist/mind/note-search.js +268 -0
  170. package/dist/mind/obligation-steering.js +221 -0
  171. package/dist/mind/pending.js +74 -7
  172. package/dist/mind/prompt.js +1013 -112
  173. package/dist/mind/provenance-trust.js +26 -0
  174. package/dist/mind/scrutiny.js +173 -0
  175. package/dist/mind/token-estimate.js +8 -12
  176. package/dist/nerves/cli-logging.js +7 -1
  177. package/dist/nerves/coverage/audit-rules.js +15 -6
  178. package/dist/nerves/coverage/audit.js +28 -2
  179. package/dist/nerves/coverage/cli.js +1 -1
  180. package/dist/nerves/coverage/file-completeness.js +83 -5
  181. package/dist/nerves/coverage/run-artifacts.js +1 -1
  182. package/dist/nerves/event-buffer.js +111 -0
  183. package/dist/nerves/index.js +224 -4
  184. package/dist/nerves/observation.js +20 -0
  185. package/dist/nerves/redact.js +79 -0
  186. package/dist/nerves/runtime.js +5 -1
  187. package/dist/outlook-ui/assets/index-LwChZTgL.css +1 -0
  188. package/dist/outlook-ui/assets/index-xTdv64BV.js +61 -0
  189. package/dist/outlook-ui/index.html +15 -0
  190. package/dist/repertoire/ado-client.js +15 -56
  191. package/dist/repertoire/ado-semantic.js +11 -10
  192. package/dist/repertoire/api-client.js +97 -0
  193. package/dist/repertoire/bitwarden-store.js +319 -0
  194. package/dist/repertoire/bundle-templates.js +72 -0
  195. package/dist/repertoire/bw-installer.js +79 -0
  196. package/dist/repertoire/coding/codex-jsonl.js +64 -0
  197. package/dist/repertoire/coding/context-pack.js +330 -0
  198. package/dist/repertoire/coding/feedback.js +197 -30
  199. package/dist/repertoire/coding/manager.js +158 -9
  200. package/dist/repertoire/coding/spawner.js +55 -9
  201. package/dist/repertoire/coding/tools.js +170 -7
  202. package/dist/repertoire/commerce-errors.js +109 -0
  203. package/dist/repertoire/commerce-self-test.js +156 -0
  204. package/dist/repertoire/credential-access.js +527 -0
  205. package/dist/repertoire/duffel-client.js +185 -0
  206. package/dist/repertoire/github-client.js +14 -55
  207. package/dist/repertoire/graph-client.js +11 -52
  208. package/dist/repertoire/guardrails.js +375 -0
  209. package/dist/repertoire/mcp-client.js +255 -0
  210. package/dist/repertoire/mcp-manager.js +305 -0
  211. package/dist/repertoire/mcp-tools.js +63 -0
  212. package/dist/repertoire/shell-sessions.js +133 -0
  213. package/dist/repertoire/skills.js +15 -24
  214. package/dist/repertoire/stripe-client.js +131 -0
  215. package/dist/repertoire/tasks/board.js +43 -5
  216. package/dist/repertoire/tasks/fix.js +182 -0
  217. package/dist/repertoire/tasks/index.js +28 -10
  218. package/dist/repertoire/tasks/lifecycle.js +2 -2
  219. package/dist/repertoire/tasks/parser.js +3 -2
  220. package/dist/repertoire/tasks/scanner.js +194 -37
  221. package/dist/repertoire/tasks/transitions.js +16 -79
  222. package/dist/repertoire/tool-results.js +29 -0
  223. package/dist/repertoire/tools-attachments.js +316 -0
  224. package/dist/repertoire/tools-base.js +45 -771
  225. package/dist/repertoire/tools-bluebubbles.js +1 -0
  226. package/dist/repertoire/tools-bridge.js +141 -0
  227. package/dist/repertoire/tools-bundle.js +984 -0
  228. package/dist/repertoire/tools-config.js +185 -0
  229. package/dist/repertoire/tools-continuity.js +248 -0
  230. package/dist/repertoire/tools-credential.js +182 -0
  231. package/dist/repertoire/tools-files.js +342 -0
  232. package/dist/repertoire/tools-flight.js +224 -0
  233. package/dist/repertoire/tools-flow.js +105 -0
  234. package/dist/repertoire/tools-github.js +1 -7
  235. package/dist/repertoire/tools-notes.js +376 -0
  236. package/dist/repertoire/tools-session.js +739 -0
  237. package/dist/repertoire/tools-shell.js +120 -0
  238. package/dist/repertoire/tools-stripe.js +180 -0
  239. package/dist/repertoire/tools-surface.js +243 -0
  240. package/dist/repertoire/tools-teams.js +12 -62
  241. package/dist/repertoire/tools-travel.js +125 -0
  242. package/dist/repertoire/tools-user-profile.js +144 -0
  243. package/dist/repertoire/tools-vault.js +110 -0
  244. package/dist/repertoire/tools.js +144 -138
  245. package/dist/repertoire/travel-api-client.js +360 -0
  246. package/dist/repertoire/user-profile.js +118 -0
  247. package/dist/repertoire/vault-setup.js +241 -0
  248. package/dist/scripts/claude-code-hook.js +41 -0
  249. package/dist/scripts/claude-code-stop-hook.js +47 -0
  250. package/dist/senses/attention-queue.js +116 -0
  251. package/dist/senses/bluebubbles/attachment-cache.js +53 -0
  252. package/dist/senses/bluebubbles/attachment-download.js +137 -0
  253. package/dist/senses/{bluebubbles-client.js → bluebubbles/client.js} +225 -9
  254. package/dist/senses/bluebubbles/entry.js +13 -0
  255. package/dist/senses/bluebubbles/inbound-log.js +113 -0
  256. package/dist/senses/bluebubbles/index.js +1616 -0
  257. package/dist/senses/{bluebubbles-media.js → bluebubbles/media.js} +121 -70
  258. package/dist/senses/{bluebubbles-model.js → bluebubbles/model.js} +43 -12
  259. package/dist/senses/{bluebubbles-mutation-log.js → bluebubbles/mutation-log.js} +46 -6
  260. package/dist/senses/bluebubbles/replay.js +129 -0
  261. package/dist/senses/bluebubbles/runtime-state.js +109 -0
  262. package/dist/senses/{bluebubbles-session-cleanup.js → bluebubbles/session-cleanup.js} +1 -1
  263. package/dist/senses/cli/bracketed-paste.js +82 -0
  264. package/dist/senses/cli/image-paste.js +287 -0
  265. package/dist/senses/cli/image-ref-navigation.js +75 -0
  266. package/dist/senses/cli/ink-app.js +156 -0
  267. package/dist/senses/cli/inline-diff.js +64 -0
  268. package/dist/senses/cli/input-keys.js +174 -0
  269. package/dist/senses/cli/kill-ring.js +86 -0
  270. package/dist/senses/cli/message-list.js +51 -0
  271. package/dist/senses/cli/ouro-tui.js +605 -0
  272. package/dist/senses/cli/spinner-imperative.js +135 -0
  273. package/dist/senses/cli/spinner.js +101 -0
  274. package/dist/senses/cli/status-line.js +60 -0
  275. package/dist/senses/cli/streaming-markdown.js +526 -0
  276. package/dist/senses/cli/tool-display.js +83 -0
  277. package/dist/senses/cli/tool-render.js +85 -0
  278. package/dist/senses/cli/tui-store.js +240 -0
  279. package/dist/senses/cli/virtual-list.js +35 -0
  280. package/dist/senses/cli-entry.js +1 -1
  281. package/dist/senses/cli-layout.js +187 -0
  282. package/dist/senses/cli.js +587 -249
  283. package/dist/senses/commands.js +66 -3
  284. package/dist/senses/continuity.js +94 -0
  285. package/dist/senses/habit-turn-message.js +108 -0
  286. package/dist/senses/inner-dialog-worker.js +112 -19
  287. package/dist/senses/inner-dialog.js +633 -86
  288. package/dist/senses/pipeline.js +603 -0
  289. package/dist/senses/proactive-content-guard.js +51 -0
  290. package/dist/senses/shared-turn.js +199 -0
  291. package/dist/senses/surface-tool.js +68 -0
  292. package/dist/senses/teams.js +690 -160
  293. package/dist/senses/trust-gate.js +112 -2
  294. package/package.json +29 -7
  295. package/skills/agent-commerce.md +106 -0
  296. package/skills/browser-navigation.md +110 -0
  297. package/skills/commerce-setup-guide.md +116 -0
  298. package/skills/commerce-setup.md +84 -0
  299. package/skills/configure-dev-tools.md +81 -0
  300. package/skills/travel-planning.md +138 -0
  301. package/dist/heart/daemon/ouro-path-installer.js +0 -178
  302. package/dist/heart/daemon/subagent-installer.js +0 -134
  303. package/dist/mind/associative-recall.js +0 -197
  304. package/dist/senses/bluebubbles-entry.js +0 -11
  305. package/dist/senses/bluebubbles.js +0 -558
  306. package/dist/senses/debug-activity.js +0 -127
  307. package/subagents/README.md +0 -73
  308. package/subagents/work-doer.md +0 -235
  309. package/subagents/work-merger.md +0 -618
  310. package/subagents/work-planner.md +0 -382
  311. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  312. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  313. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  314. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  315. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  316. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  317. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  318. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  319. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  320. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  321. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  322. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
  323. /package/dist/heart/{daemon → hatch}/hatch-animation.js +0 -0
  324. /package/dist/heart/{daemon → hatch}/specialist-orchestrator.js +0 -0
  325. /package/dist/heart/{daemon → versioning}/ouro-uti.js +0 -0
  326. /package/dist/heart/{daemon → versioning}/wrapper-publish-guard.js +0 -0
@@ -1,14 +1,51 @@
1
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
+ })();
2
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
37
  };
5
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.toAnthropicMessages = toAnthropicMessages;
40
+ exports.classifyAnthropicError = classifyAnthropicError;
6
41
  exports.createAnthropicProviderRuntime = createAnthropicProviderRuntime;
7
42
  const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
8
43
  const config_1 = require("../config");
9
44
  const identity_1 = require("../identity");
10
45
  const runtime_1 = require("../../nerves/runtime");
11
46
  const streaming_1 = require("../streaming");
47
+ const model_capabilities_1 = require("../model-capabilities");
48
+ const error_classification_1 = require("./error-classification");
12
49
  const ANTHROPIC_SETUP_TOKEN_PREFIX = "sk-ant-oat01-";
13
50
  const ANTHROPIC_SETUP_TOKEN_MIN_LENGTH = 80;
14
51
  const ANTHROPIC_OAUTH_BETA_HEADER = "claude-code-20250219,oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14,interleaved-thinking-2025-05-14";
@@ -22,10 +59,10 @@ function getAnthropicSetupTokenInstructions() {
22
59
  const agentName = getAnthropicAgentNameForGuidance();
23
60
  return [
24
61
  "Fix:",
25
- ` 1. Run \`npm run auth:claude-setup-token -- --agent ${agentName}\``,
26
- " (or run `claude setup-token` and paste the token manually)",
62
+ ` 1. Run \`ouro auth --agent ${agentName}\``,
27
63
  ` 2. Open ${getAnthropicSecretsPathForGuidance()}`,
28
64
  " 3. Confirm providers.anthropic.setupToken is set",
65
+ " 4. After reauth, retry the failed ouro command or reconnect this session.",
29
66
  ].join("\n");
30
67
  }
31
68
  function getAnthropicReauthGuidance(reason) {
@@ -35,8 +72,7 @@ function getAnthropicReauthGuidance(reason) {
35
72
  getAnthropicSetupTokenInstructions(),
36
73
  ].join("\n");
37
74
  }
38
- function resolveAnthropicSetupTokenCredential() {
39
- const anthropicConfig = (0, config_1.getAnthropicConfig)();
75
+ function resolveAnthropicSetupTokenCredential(anthropicConfig = (0, config_1.getAnthropicConfig)()) {
40
76
  const token = anthropicConfig.setupToken?.trim();
41
77
  if (!token) {
42
78
  throw new Error(getAnthropicReauthGuidance("Anthropic provider is selected but no setup-token credential was found."));
@@ -93,6 +129,18 @@ function toAnthropicMessages(messages) {
93
129
  if (msg.role === "assistant") {
94
130
  const assistant = msg;
95
131
  const blocks = [];
132
+ // Restore thinking blocks before text/tool_use blocks
133
+ const thinkingBlocks = assistant._thinking_blocks;
134
+ if (thinkingBlocks) {
135
+ for (const tb of thinkingBlocks) {
136
+ if (tb.type === "thinking") {
137
+ blocks.push({ type: "thinking", thinking: tb.thinking, signature: tb.signature });
138
+ }
139
+ else {
140
+ blocks.push({ type: "redacted_thinking", data: tb.data });
141
+ }
142
+ }
143
+ }
96
144
  const text = toAnthropicTextContent(assistant.content);
97
145
  if (text) {
98
146
  blocks.push({ type: "text", text });
@@ -173,53 +221,64 @@ function mergeAnthropicToolArguments(current, partial) {
173
221
  }
174
222
  return current + partial;
175
223
  }
224
+ function classifyAnthropicError(error) {
225
+ return (0, error_classification_1.classifyHttpError)(error, {
226
+ isAuthFailure: isAnthropicAuthFailure,
227
+ isServerError: (e) => e.status === 529,
228
+ });
229
+ }
176
230
  function isAnthropicAuthFailure(error) {
177
- if (!(error instanceof Error))
178
- return false;
179
- const status = error.status;
180
- if (status === 401 || status === 403)
181
- return true;
182
231
  const lower = error.message.toLowerCase();
183
232
  return (lower.includes("oauth authentication") ||
184
233
  lower.includes("authentication failed") ||
185
234
  lower.includes("unauthorized") ||
186
235
  lower.includes("invalid api key"));
187
236
  }
188
- function withAnthropicAuthGuidance(error) {
189
- const base = error instanceof Error ? error.message : String(error);
190
- if (isAnthropicAuthFailure(error)) {
191
- return new Error(getAnthropicReauthGuidance(`Anthropic authentication failed (${base}).`));
192
- }
193
- return error instanceof Error ? error : new Error(String(error));
194
- }
195
237
  async function streamAnthropicMessages(client, model, request) {
196
238
  const { system, messages } = toAnthropicMessages(request.messages);
197
239
  const anthropicTools = toAnthropicTools(request.activeTools);
240
+ const modelCaps = (0, model_capabilities_1.getModelCapabilities)(model);
241
+ const maxTokens = modelCaps.maxOutputTokens ?? 16384;
198
242
  const params = {
199
243
  model,
200
- max_tokens: 4096,
244
+ max_tokens: maxTokens,
201
245
  messages,
202
246
  stream: true,
247
+ thinking: { type: "adaptive" },
248
+ output_config: { effort: request.reasoningEffort ?? "medium" },
203
249
  };
204
- if (system)
205
- params.system = system;
250
+ // The Anthropic API requires a Claude Code identification block in the system
251
+ // prompt when using OAuth setup tokens (sk-ant-oat01). Without it, Opus/Sonnet
252
+ // 4.6 requests are rejected with 400. This is the API's validation that the
253
+ // token is being used by a Claude Code client.
254
+ const claudeCodePreamble = { type: "text", text: "You are Claude Code, Anthropic's official CLI for Claude." };
255
+ if (system) {
256
+ params.system = [claudeCodePreamble, { type: "text", text: system }];
257
+ }
258
+ else {
259
+ params.system = [claudeCodePreamble];
260
+ }
206
261
  if (anthropicTools.length > 0)
207
262
  params.tools = anthropicTools;
208
263
  if (request.toolChoiceRequired && anthropicTools.length > 0) {
209
- params.tool_choice = { type: "any" };
264
+ // Thinking (adaptive or enabled) only supports tool_choice "auto" or "none".
265
+ // "any" forces tool use which is incompatible with extended thinking.
266
+ params.tool_choice = params.thinking ? { type: "auto" } : /* v8 ignore next -- no-thinking path: thinking always set for 4.6 models @preserve */ { type: "any" };
210
267
  }
211
268
  let response;
212
269
  try {
213
270
  response = await client.messages.create(params, request.signal ? { signal: request.signal } : {});
214
271
  }
215
272
  catch (error) {
216
- throw withAnthropicAuthGuidance(error);
273
+ throw error instanceof Error ? error : new Error(String(error));
217
274
  }
218
275
  let content = "";
219
276
  let streamStarted = false;
220
277
  let usage;
221
278
  const toolCalls = new Map();
222
- const answerStreamer = new streaming_1.FinalAnswerStreamer(request.callbacks);
279
+ const thinkingBlocks = new Map();
280
+ const redactedBlocks = new Map();
281
+ const answerStreamer = new streaming_1.SettleStreamer(request.callbacks, request.eagerSettleStreaming);
223
282
  try {
224
283
  for await (const event of response) {
225
284
  if (request.signal?.aborted)
@@ -227,8 +286,14 @@ async function streamAnthropicMessages(client, model, request) {
227
286
  const eventType = String(event.type ?? "");
228
287
  if (eventType === "content_block_start") {
229
288
  const block = event.content_block;
230
- if (block?.type === "tool_use") {
231
- const index = Number(event.index);
289
+ const index = Number(event.index);
290
+ if (block?.type === "thinking") {
291
+ thinkingBlocks.set(index, { type: "thinking", thinking: "", signature: "" });
292
+ }
293
+ else if (block?.type === "redacted_thinking") {
294
+ redactedBlocks.set(index, { type: "redacted_thinking", data: String(block.data ?? "") });
295
+ }
296
+ else if (block?.type === "tool_use") {
232
297
  const rawInput = block.input;
233
298
  const input = rawInput && typeof rawInput === "object"
234
299
  ? JSON.stringify(rawInput)
@@ -239,9 +304,9 @@ async function streamAnthropicMessages(client, model, request) {
239
304
  name,
240
305
  arguments: input,
241
306
  });
242
- // Activate eager streaming for sole final_answer tool call
243
- /* v8 ignore next -- final_answer streaming activation, tested via FinalAnswerStreamer unit tests @preserve */
244
- if (name === "final_answer" && toolCalls.size === 1) {
307
+ // Activate eager streaming for sole settle tool call
308
+ /* v8 ignore next -- settle streaming activation, tested via SettleStreamer unit tests @preserve */
309
+ if (name === "settle" && toolCalls.size === 1) {
245
310
  answerStreamer.activate();
246
311
  }
247
312
  }
@@ -265,7 +330,19 @@ async function streamAnthropicMessages(client, model, request) {
265
330
  request.callbacks.onModelStreamStart();
266
331
  streamStarted = true;
267
332
  }
268
- request.callbacks.onReasoningChunk(String(delta?.thinking ?? ""));
333
+ const thinkingText = String(delta?.thinking ?? "");
334
+ request.callbacks.onReasoningChunk(thinkingText);
335
+ const thinkingIndex = Number(event.index);
336
+ const thinkingBlock = thinkingBlocks.get(thinkingIndex);
337
+ if (thinkingBlock)
338
+ thinkingBlock.thinking += thinkingText;
339
+ continue;
340
+ }
341
+ if (deltaType === "signature_delta") {
342
+ const sigIndex = Number(event.index);
343
+ const sigBlock = thinkingBlocks.get(sigIndex);
344
+ if (sigBlock)
345
+ sigBlock.signature += String(delta?.signature ?? "");
269
346
  continue;
270
347
  }
271
348
  if (deltaType === "input_json_delta") {
@@ -274,8 +351,8 @@ async function streamAnthropicMessages(client, model, request) {
274
351
  if (existing) {
275
352
  const partialJson = String(delta?.partial_json ?? "");
276
353
  existing.arguments = mergeAnthropicToolArguments(existing.arguments, partialJson);
277
- /* v8 ignore next -- final_answer delta streaming, tested via FinalAnswerStreamer unit tests @preserve */
278
- if (existing.name === "final_answer" && toolCalls.size === 1) {
354
+ /* v8 ignore next -- settle delta streaming, tested via SettleStreamer unit tests @preserve */
355
+ if (existing.name === "settle" && toolCalls.size === 1) {
279
356
  answerStreamer.processDelta(partialJson);
280
357
  }
281
358
  }
@@ -299,48 +376,98 @@ async function streamAnthropicMessages(client, model, request) {
299
376
  }
300
377
  }
301
378
  catch (error) {
302
- throw withAnthropicAuthGuidance(error);
379
+ throw error instanceof Error ? error : /* v8 ignore next -- defensive: stream errors are always Error @preserve */ new Error(String(error));
303
380
  }
381
+ // Collect all thinking blocks (regular + redacted) sorted by index to preserve ordering
382
+ const allThinkingIndices = [...thinkingBlocks.keys(), ...redactedBlocks.keys()].sort((a, b) => a - b);
383
+ const outputItems = allThinkingIndices.map((idx) => {
384
+ const tb = thinkingBlocks.get(idx);
385
+ if (tb)
386
+ return tb;
387
+ return redactedBlocks.get(idx);
388
+ });
304
389
  return {
305
390
  content,
306
391
  toolCalls: [...toolCalls.values()],
307
- outputItems: [],
392
+ outputItems,
308
393
  usage,
309
- finalAnswerStreamed: answerStreamer.streamed,
394
+ settleStreamed: answerStreamer.streamed,
310
395
  };
311
396
  }
312
- function createAnthropicProviderRuntime() {
397
+ function createAnthropicProviderRuntime(model, anthropicConfig = (0, config_1.getAnthropicConfig)()) {
313
398
  (0, runtime_1.emitNervesEvent)({
314
399
  component: "engine",
315
400
  event: "engine.provider_init",
316
401
  message: "anthropic provider init",
317
402
  meta: { provider: "anthropic" },
318
403
  });
319
- const anthropicConfig = (0, config_1.getAnthropicConfig)();
320
- if (!(anthropicConfig.model && anthropicConfig.setupToken)) {
321
- throw new Error(getAnthropicReauthGuidance("provider 'anthropic' is selected in agent.json but providers.anthropic.model/setupToken is incomplete in secrets.json."));
404
+ if (!anthropicConfig.setupToken) {
405
+ throw new Error(getAnthropicReauthGuidance("provider 'anthropic' is selected in agent.json but providers.anthropic.setupToken is missing in secrets.json."));
322
406
  }
323
- const credential = resolveAnthropicSetupTokenCredential();
324
- const client = new sdk_1.default({
325
- authToken: credential.token,
326
- timeout: 30000,
327
- maxRetries: 0,
328
- defaultHeaders: {
329
- "anthropic-beta": ANTHROPIC_OAUTH_BETA_HEADER,
330
- },
331
- });
407
+ const modelCaps = (0, model_capabilities_1.getModelCapabilities)(model);
408
+ const capabilities = new Set();
409
+ if (modelCaps.reasoningEffort)
410
+ capabilities.add("reasoning-effort");
411
+ const credential = resolveAnthropicSetupTokenCredential(anthropicConfig);
412
+ const refreshToken = anthropicConfig.refreshToken;
413
+ const expiresAt = anthropicConfig.expiresAt;
414
+ function createClient(token) {
415
+ return new sdk_1.default({
416
+ authToken: token,
417
+ maxRetries: 0,
418
+ defaultHeaders: {
419
+ "anthropic-beta": ANTHROPIC_OAUTH_BETA_HEADER,
420
+ "anthropic-dangerous-direct-browser-access": "true",
421
+ "user-agent": "claude-cli/2.1.2 (external, cli)",
422
+ "x-app": "cli",
423
+ },
424
+ });
425
+ }
426
+ let currentToken = credential.token;
427
+ let client = createClient(currentToken);
428
+ /* v8 ignore start -- token refresh: dynamic import + ensureFreshToken, tested via integration @preserve */
429
+ async function ensureClient() {
430
+ try {
431
+ const { ensureFreshToken } = await Promise.resolve().then(() => __importStar(require("./anthropic-token")));
432
+ const { getAgentName } = await Promise.resolve().then(() => __importStar(require("../identity")));
433
+ const freshToken = await ensureFreshToken(currentToken, refreshToken, expiresAt, getAgentName());
434
+ if (freshToken !== currentToken) {
435
+ currentToken = freshToken;
436
+ client = createClient(freshToken);
437
+ }
438
+ }
439
+ catch {
440
+ // refresh failed — use existing client
441
+ }
442
+ return client;
443
+ }
444
+ /* v8 ignore stop */
332
445
  return {
333
446
  id: "anthropic",
334
- model: anthropicConfig.model,
335
- client,
447
+ model,
448
+ /* v8 ignore next -- getter: returns mutable client ref @preserve */
449
+ get client() { return client; },
450
+ capabilities,
451
+ supportedReasoningEfforts: modelCaps.reasoningEffort,
336
452
  resetTurnState(_messages) {
337
453
  // Anthropic request payload is derived from canonical messages each turn.
338
454
  },
339
455
  appendToolOutput(_callId, _output) {
340
456
  // Anthropic uses canonical messages for tool_result tracking.
341
457
  },
342
- streamTurn(request) {
343
- return streamAnthropicMessages(client, anthropicConfig.model, request);
458
+ async streamTurn(request) {
459
+ const freshClient = await ensureClient();
460
+ return streamAnthropicMessages(freshClient, model, request);
461
+ },
462
+ /* v8 ignore start -- ping: tested via provider-ping.test.ts @preserve */
463
+ async ping(signal) {
464
+ const freshClient = await ensureClient();
465
+ await freshClient.messages.create({ model: "claude-haiku-4-5-20251001", max_tokens: 1, messages: [{ role: "user", content: "ping" }] }, { signal, headers: { "anthropic-beta": "claude-code-20250219,oauth-2025-04-20" } });
466
+ },
467
+ /* v8 ignore stop */
468
+ /* v8 ignore next 3 -- delegation: classification logic tested via classifyAnthropicError @preserve */
469
+ classifyError(error) {
470
+ return classifyAnthropicError(error);
344
471
  },
345
472
  };
346
473
  }
@@ -1,35 +1,117 @@
1
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
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.classifyAzureError = classifyAzureError;
37
+ exports.createAzureTokenProvider = createAzureTokenProvider;
3
38
  exports.createAzureProviderRuntime = createAzureProviderRuntime;
4
39
  const openai_1 = require("openai");
5
40
  const config_1 = require("../config");
6
41
  const runtime_1 = require("../../nerves/runtime");
7
42
  const streaming_1 = require("../streaming");
8
- function createAzureProviderRuntime() {
43
+ const model_capabilities_1 = require("../model-capabilities");
44
+ const error_classification_1 = require("./error-classification");
45
+ const COGNITIVE_SERVICES_SCOPE = "https://cognitiveservices.azure.com/.default";
46
+ function classifyAzureError(error) {
47
+ return (0, error_classification_1.classifyHttpError)(error);
48
+ }
49
+ // @azure/identity is imported dynamically (below) rather than at the top level
50
+ // because it's a heavy package (~30+ transitive deps) and we only need it when
51
+ // using the managed-identity auth path. API-key users and other providers
52
+ // shouldn't pay the cold-start cost.
53
+ function createAzureTokenProvider(managedIdentityClientId) {
54
+ let credential = null;
55
+ return async () => {
56
+ try {
57
+ if (!credential) {
58
+ const { DefaultAzureCredential } = await Promise.resolve().then(() => __importStar(require("@azure/identity")));
59
+ const credentialOptions = managedIdentityClientId
60
+ ? { managedIdentityClientId }
61
+ : undefined;
62
+ credential = new DefaultAzureCredential(credentialOptions);
63
+ }
64
+ const tokenResponse = await credential.getToken(COGNITIVE_SERVICES_SCOPE);
65
+ return tokenResponse.token;
66
+ }
67
+ catch (err) {
68
+ const detail = err instanceof Error ? err.message : String(err);
69
+ throw new Error(`Azure OpenAI authentication failed: ${detail}\n` +
70
+ "To fix this, either:\n" +
71
+ " 1. Set providers.azure.apiKey in secrets.json, or\n" +
72
+ " 2. Run 'az login' to authenticate with your Azure account (for local dev), or\n" +
73
+ " 3. Attach a managed identity to your App Service and set providers.azure.managedIdentityClientId in secrets.json (for deployed environments)");
74
+ }
75
+ };
76
+ }
77
+ function createAzureProviderRuntime(model, azureConfig = (0, config_1.getAzureConfig)()) {
78
+ const useApiKey = !!azureConfig.apiKey;
79
+ const authMethod = useApiKey ? "key" : "managed-identity";
9
80
  (0, runtime_1.emitNervesEvent)({
10
81
  component: "engine",
11
82
  event: "engine.provider_init",
12
83
  message: "azure provider init",
13
- meta: { provider: "azure" },
84
+ meta: { provider: "azure", authMethod },
14
85
  });
15
- const azureConfig = (0, config_1.getAzureConfig)();
16
- if (!(azureConfig.apiKey && azureConfig.endpoint && azureConfig.deployment && azureConfig.modelName)) {
86
+ if (!(azureConfig.endpoint && azureConfig.deployment)) {
17
87
  throw new Error("provider 'azure' is selected in agent.json but providers.azure is incomplete in secrets.json.");
18
88
  }
19
- const client = new openai_1.AzureOpenAI({
20
- apiKey: azureConfig.apiKey,
89
+ const modelCaps = (0, model_capabilities_1.getModelCapabilities)(model);
90
+ const capabilities = new Set();
91
+ if (modelCaps.reasoningEffort)
92
+ capabilities.add("reasoning-effort");
93
+ const clientOptions = {
21
94
  endpoint: azureConfig.endpoint.replace(/\/openai.*$/, ""),
22
95
  deployment: azureConfig.deployment,
23
96
  apiVersion: azureConfig.apiVersion,
24
- timeout: 30000,
25
97
  maxRetries: 0,
26
- });
98
+ };
99
+ if (useApiKey) {
100
+ clientOptions.apiKey = azureConfig.apiKey;
101
+ }
102
+ else {
103
+ const managedIdentityClientId = azureConfig.managedIdentityClientId || undefined;
104
+ clientOptions.azureADTokenProvider = createAzureTokenProvider(managedIdentityClientId);
105
+ }
106
+ const client = new openai_1.AzureOpenAI(clientOptions);
27
107
  let nativeInput = null;
28
108
  let nativeInstructions = "";
29
109
  return {
30
110
  id: "azure",
31
- model: azureConfig.modelName,
111
+ model,
32
112
  client,
113
+ capabilities,
114
+ supportedReasoningEfforts: modelCaps.reasoningEffort,
33
115
  resetTurnState(messages) {
34
116
  const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
35
117
  nativeInput = input;
@@ -48,7 +130,7 @@ function createAzureProviderRuntime() {
48
130
  input: nativeInput,
49
131
  instructions: nativeInstructions,
50
132
  tools: (0, streaming_1.toResponsesTools)(request.activeTools),
51
- reasoning: { effort: "medium", summary: "detailed" },
133
+ reasoning: { effort: request.reasoningEffort ?? "medium", summary: "detailed" },
52
134
  stream: true,
53
135
  store: false,
54
136
  include: ["reasoning.encrypted_content"],
@@ -57,10 +139,19 @@ function createAzureProviderRuntime() {
57
139
  params.metadata = { trace_id: request.traceId };
58
140
  if (request.toolChoiceRequired)
59
141
  params.tool_choice = "required";
60
- const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal);
142
+ const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal, request.eagerSettleStreaming);
61
143
  for (const item of result.outputItems)
62
144
  nativeInput.push(item);
63
145
  return result;
64
146
  },
147
+ /* v8 ignore start -- ping: tested via provider-ping.test.ts @preserve */
148
+ async ping(signal) {
149
+ await this.client.responses.create({ model: this.model, input: "ping", max_output_tokens: 16 }, { signal });
150
+ },
151
+ /* v8 ignore stop */
152
+ /* v8 ignore next 3 -- delegation: classification logic tested via classifyAzureError @preserve */
153
+ classifyError(error) {
154
+ return classifyAzureError(error);
155
+ },
65
156
  };
66
157
  }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isNetworkError = isNetworkError;
4
+ exports.classifyHttpError = classifyHttpError;
5
+ const runtime_1 = require("../../nerves/runtime");
6
+ // Node socket / DNS error codes that indicate a transient network failure.
7
+ const NETWORK_ERROR_CODES = new Set([
8
+ "ECONNRESET",
9
+ "ECONNREFUSED",
10
+ "ENOTFOUND",
11
+ "ETIMEDOUT",
12
+ "EPIPE",
13
+ "EAI_AGAIN",
14
+ "EHOSTUNREACH",
15
+ "ENETUNREACH",
16
+ "ECONNABORTED",
17
+ ]);
18
+ // Substrings the OpenAI/Anthropic SDKs use when wrapping fetch/socket failures
19
+ // into Error.message instead of an err.code.
20
+ const NETWORK_ERROR_MESSAGE_PATTERNS = [
21
+ "fetch failed",
22
+ "socket hang up",
23
+ "getaddrinfo",
24
+ "request timed out", // OpenAI SDK timeout — see SDK source
25
+ "request timeout",
26
+ "connection error",
27
+ ];
28
+ // True if the error looks like a transient network issue (no HTTP status, just
29
+ // a socket/DNS/timeout failure from the underlying transport).
30
+ function isNetworkError(error) {
31
+ const code = error.code || "";
32
+ if (NETWORK_ERROR_CODES.has(code))
33
+ return true;
34
+ const msg = (error.message || "").toLowerCase();
35
+ return NETWORK_ERROR_MESSAGE_PATTERNS.some((pat) => msg.includes(pat));
36
+ }
37
+ // Standard HTTP error → ProviderErrorClassification mapping. Providers wrap
38
+ // this with their own overrides.
39
+ function classifyHttpError(error, overrides) {
40
+ const status = error.status;
41
+ if (overrides?.isAuthFailure?.(error) || status === 401 || status === 403) {
42
+ return "auth-failure";
43
+ }
44
+ if (status === 429) {
45
+ if (overrides?.isUsageLimit?.(error))
46
+ return "usage-limit";
47
+ return "rate-limit";
48
+ }
49
+ if (overrides?.isServerError?.(error) || (status !== undefined && status >= 500)) {
50
+ return "server-error";
51
+ }
52
+ if (isNetworkError(error))
53
+ return "network-error";
54
+ return "unknown";
55
+ }
56
+ /* v8 ignore start — module-level observability event */
57
+ (0, runtime_1.emitNervesEvent)({
58
+ component: "engine",
59
+ event: "engine.error_classification_loaded",
60
+ message: "shared provider error classification loaded",
61
+ meta: {},
62
+ });
63
+ /* v8 ignore stop */