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