@ouro.bot/cli 0.1.0-alpha.3 → 0.1.0-alpha.300

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