@ouro.bot/cli 0.0.1-alpha.0 → 0.1.0-alpha.2

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 (119) hide show
  1. package/AdoptionSpecialist.ouro/agent.json +20 -0
  2. package/AdoptionSpecialist.ouro/psyche/SOUL.md +22 -0
  3. package/AdoptionSpecialist.ouro/psyche/identities/basilisk.md +31 -0
  4. package/AdoptionSpecialist.ouro/psyche/identities/jafar.md +31 -0
  5. package/AdoptionSpecialist.ouro/psyche/identities/jormungandr.md +31 -0
  6. package/AdoptionSpecialist.ouro/psyche/identities/kaa.md +31 -0
  7. package/AdoptionSpecialist.ouro/psyche/identities/medusa.md +31 -0
  8. package/AdoptionSpecialist.ouro/psyche/identities/monty.md +31 -0
  9. package/AdoptionSpecialist.ouro/psyche/identities/nagini.md +31 -0
  10. package/AdoptionSpecialist.ouro/psyche/identities/ouroboros.md +31 -0
  11. package/AdoptionSpecialist.ouro/psyche/identities/python.md +31 -0
  12. package/AdoptionSpecialist.ouro/psyche/identities/quetzalcoatl.md +31 -0
  13. package/AdoptionSpecialist.ouro/psyche/identities/sir-hiss.md +31 -0
  14. package/AdoptionSpecialist.ouro/psyche/identities/the-serpent.md +31 -0
  15. package/AdoptionSpecialist.ouro/psyche/identities/the-snake.md +31 -0
  16. package/README.md +224 -6
  17. package/dist/heart/agent-entry.js +17 -0
  18. package/dist/heart/api-error.js +34 -0
  19. package/dist/heart/config.js +296 -0
  20. package/dist/heart/core.js +515 -0
  21. package/dist/heart/daemon/daemon-cli.js +675 -0
  22. package/dist/heart/daemon/daemon-entry.js +74 -0
  23. package/dist/heart/daemon/daemon.js +313 -0
  24. package/dist/heart/daemon/hatch-flow.js +285 -0
  25. package/dist/heart/daemon/hatch-specialist.js +107 -0
  26. package/dist/heart/daemon/health-monitor.js +79 -0
  27. package/dist/heart/daemon/log-tailer.js +146 -0
  28. package/dist/heart/daemon/message-router.js +98 -0
  29. package/dist/heart/daemon/os-cron.js +260 -0
  30. package/dist/heart/daemon/ouro-bot-entry.js +23 -0
  31. package/dist/heart/daemon/ouro-bot-wrapper.js +90 -0
  32. package/dist/heart/daemon/ouro-entry.js +23 -0
  33. package/dist/heart/daemon/ouro-uti.js +212 -0
  34. package/dist/heart/daemon/process-manager.js +237 -0
  35. package/dist/heart/daemon/runtime-logging.js +98 -0
  36. package/dist/heart/daemon/subagent-installer.js +125 -0
  37. package/dist/heart/daemon/task-scheduler.js +240 -0
  38. package/dist/heart/harness.js +26 -0
  39. package/dist/heart/identity.js +281 -0
  40. package/dist/heart/kicks.js +144 -0
  41. package/dist/heart/primitives.js +4 -0
  42. package/dist/heart/providers/anthropic.js +329 -0
  43. package/dist/heart/providers/azure.js +66 -0
  44. package/dist/heart/providers/minimax.js +53 -0
  45. package/dist/heart/providers/openai-codex.js +162 -0
  46. package/dist/heart/streaming.js +412 -0
  47. package/dist/heart/turn-coordinator.js +62 -0
  48. package/dist/inner-worker-entry.js +4 -0
  49. package/dist/mind/associative-recall.js +197 -0
  50. package/dist/mind/bundle-manifest.js +118 -0
  51. package/dist/mind/context.js +302 -0
  52. package/dist/mind/first-impressions.js +43 -0
  53. package/dist/mind/format.js +56 -0
  54. package/dist/mind/friends/channel.js +41 -0
  55. package/dist/mind/friends/resolver.js +84 -0
  56. package/dist/mind/friends/store-file.js +171 -0
  57. package/dist/mind/friends/store.js +4 -0
  58. package/dist/mind/friends/tokens.js +26 -0
  59. package/dist/mind/friends/types.js +21 -0
  60. package/dist/mind/memory.js +388 -0
  61. package/dist/mind/pending.js +93 -0
  62. package/dist/mind/phrases.js +43 -0
  63. package/dist/mind/prompt-refresh.js +20 -0
  64. package/dist/mind/prompt.js +352 -0
  65. package/dist/mind/token-estimate.js +119 -0
  66. package/dist/nerves/cli-logging.js +31 -0
  67. package/dist/nerves/coverage/audit-rules.js +81 -0
  68. package/dist/nerves/coverage/audit.js +200 -0
  69. package/dist/nerves/coverage/cli-main.js +5 -0
  70. package/dist/nerves/coverage/cli.js +51 -0
  71. package/dist/nerves/coverage/contract.js +23 -0
  72. package/dist/nerves/coverage/file-completeness.js +56 -0
  73. package/dist/nerves/coverage/run-artifacts.js +77 -0
  74. package/dist/nerves/coverage/source-scanner.js +34 -0
  75. package/dist/nerves/index.js +152 -0
  76. package/dist/nerves/runtime.js +38 -0
  77. package/dist/repertoire/ado-client.js +211 -0
  78. package/dist/repertoire/ado-context.js +73 -0
  79. package/dist/repertoire/ado-semantic.js +841 -0
  80. package/dist/repertoire/ado-templates.js +146 -0
  81. package/dist/repertoire/coding/index.js +36 -0
  82. package/dist/repertoire/coding/manager.js +489 -0
  83. package/dist/repertoire/coding/monitor.js +60 -0
  84. package/dist/repertoire/coding/reporter.js +45 -0
  85. package/dist/repertoire/coding/spawner.js +102 -0
  86. package/dist/repertoire/coding/tools.js +167 -0
  87. package/dist/repertoire/coding/types.js +2 -0
  88. package/dist/repertoire/data/ado-endpoints.json +122 -0
  89. package/dist/repertoire/data/graph-endpoints.json +212 -0
  90. package/dist/repertoire/github-client.js +64 -0
  91. package/dist/repertoire/graph-client.js +118 -0
  92. package/dist/repertoire/skills.js +156 -0
  93. package/dist/repertoire/tasks/board.js +122 -0
  94. package/dist/repertoire/tasks/index.js +210 -0
  95. package/dist/repertoire/tasks/lifecycle.js +80 -0
  96. package/dist/repertoire/tasks/middleware.js +65 -0
  97. package/dist/repertoire/tasks/parser.js +173 -0
  98. package/dist/repertoire/tasks/scanner.js +132 -0
  99. package/dist/repertoire/tasks/transitions.js +145 -0
  100. package/dist/repertoire/tasks/types.js +2 -0
  101. package/dist/repertoire/tools-base.js +714 -0
  102. package/dist/repertoire/tools-github.js +53 -0
  103. package/dist/repertoire/tools-teams.js +308 -0
  104. package/dist/repertoire/tools.js +199 -0
  105. package/dist/senses/cli-entry.js +15 -0
  106. package/dist/senses/cli.js +604 -0
  107. package/dist/senses/commands.js +98 -0
  108. package/dist/senses/inner-dialog-worker.js +61 -0
  109. package/dist/senses/inner-dialog.js +231 -0
  110. package/dist/senses/session-lock.js +119 -0
  111. package/dist/senses/teams-entry.js +15 -0
  112. package/dist/senses/teams.js +696 -0
  113. package/dist/senses/trust-gate.js +150 -0
  114. package/package.json +34 -11
  115. package/subagents/README.md +73 -0
  116. package/subagents/work-doer.md +233 -0
  117. package/subagents/work-merger.md +624 -0
  118. package/subagents/work-planner.md +373 -0
  119. package/bin/ouro.js +0 -6
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ // TODO: Kicks enforce "any action" but not "meaningful action". After a narration
3
+ // kick, the model can satisfy the constraint by calling a no-op tool like
4
+ // get_current_time({}). We need to detect trivial compliance and either re-kick
5
+ // or discount the tool call. Ideally, the kick message would suggest a specific
6
+ // tool call based on conversation context (what the user asked, what tools are
7
+ // relevant) rather than just saying "call a tool". That's a bigger piece of work —
8
+ // it requires the kick system to be context-aware.
9
+ // See ouroboros' observation: "i'm not chickening out. i'm satisfying a crude
10
+ // constraint. poorly."
11
+ //
12
+ // A kick is a self-correction. When the harness detects a malformed response,
13
+ // it injects an assistant-role message as if the model caught its own mistake.
14
+ //
15
+ // Kicks are:
16
+ // - assistant role (self-correction, not external rebuke)
17
+ // - first person ("I" not "you")
18
+ // - forward-looking (what I'm doing next, not what I did wrong)
19
+ // - short (one sentence)
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.hasToolIntent = hasToolIntent;
22
+ exports.detectKick = detectKick;
23
+ const KICK_MESSAGES = {
24
+ empty: "I sent an empty message by accident — let me try again.",
25
+ narration: "I narrated instead of acting. Using the tool now -- if done, calling final_answer.",
26
+ tool_required: "tool-required is on — I need to call a tool. use /tool-required to turn it off.",
27
+ };
28
+ const TOOL_INTENT_PATTERNS = [
29
+ // Explicit intent — "let me", "I'll", "I will"
30
+ /\blet me\b/i,
31
+ /\bi'll\b/i,
32
+ /\bi will\b/i,
33
+ /\bi would like to\b/i,
34
+ /\bi want to\b/i,
35
+ // "going to" variants
36
+ /\bi'm going to\b/i,
37
+ /\bgoing to\b/i,
38
+ /\bi am going to\b/i,
39
+ // Present continuous — "i'm checking", "i am querying"
40
+ /\bi'm \w+ing\b/i,
41
+ /\bi am \w+ing\b/i,
42
+ // Action announcements — "I need to", "I should", "I can"
43
+ /\bi need to\b/i,
44
+ /\bi should\b/i,
45
+ /\bi can\b/i,
46
+ // Obligation — "I have to", "I must"
47
+ /\bi have to\b/i,
48
+ /\bwe have to\b/i,
49
+ /\bi must\b/i,
50
+ /\bwe must\b/i,
51
+ // First person plural intent
52
+ /\bwe need to\b/i,
53
+ /\bwe should\b/i,
54
+ /\bwe can\b/i,
55
+ /\bwe'll\b/i,
56
+ /\bwe will\b/i,
57
+ /\bwe're going to\b/i,
58
+ /\bwe are going to\b/i,
59
+ /\blet's\b/i,
60
+ // Gerund phase shifts — "entering", "starting", "proceeding", "switching"
61
+ /\bentering\b/i,
62
+ /\bstarting with\b/i,
63
+ /\bproceeding\b/i,
64
+ /\bswitching to\b/i,
65
+ // Temporal narration — "first", "now I/we", "next turn", "next, I"
66
+ /\bfirst,?\s+i\b/i,
67
+ /\bnow i\b/i,
68
+ /\bnow we\b/i,
69
+ /\bnext turn\b/i,
70
+ /\bnext,?\s+i\b/i,
71
+ /\bnext,?\s+we\b/i,
72
+ // Sequential narration — "then I/we", "after that", "once I/we", "before I/we"
73
+ /\bthen i\b/i,
74
+ /\bthen we\b/i,
75
+ /\bafter that\b/i,
76
+ /\bonce i\b/i,
77
+ /\bonce we\b/i,
78
+ /\bbefore i\b/i,
79
+ /\bbefore we\b/i,
80
+ // Future intent — "about to", "gonna"
81
+ /\babout to\b/i,
82
+ /\bgonna\b/i,
83
+ // Hedged intent — "allow me to", "time to"
84
+ /\ballow me to\b/i,
85
+ /\btime to\b/i,
86
+ // Movement narration — "moving on", "moving to"
87
+ /\bmoving on\b/i,
88
+ /\bmoving to\b/i,
89
+ // Self-narration — "my next step", "my plan", "the plan is", "tool calls only"
90
+ /\bmy next step\b/i,
91
+ /\bmy plan\b/i,
92
+ /\bthe plan is\b/i,
93
+ /\btool calls only\b/i,
94
+ // "Continuing" at start of any line — narration filler (multiline so ^ matches after \n)
95
+ /^continuing\b/im,
96
+ // "continues" anywhere — progress narration ("The work continues", "continues to be complex")
97
+ /\bcontinues\b/i,
98
+ // "Next up" at start of text — e.g. "Next up:", "Next up, I'll..."
99
+ /^next up\b/i,
100
+ ];
101
+ // Normalize curly quotes/apostrophes to straight so patterns match consistently
102
+ function normalize(text) {
103
+ return text.replace(/[\u2018\u2019\u2032]/g, "'").replace(/[\u201C\u201D]/g, '"');
104
+ }
105
+ function hasToolIntent(text) {
106
+ return TOOL_INTENT_PATTERNS.some((p) => p.test(normalize(text)));
107
+ }
108
+ // Detect what kind of kick is needed, or null if response is fine.
109
+ // Priority: empty > narration > tool_required
110
+ function detectKick(content, options) {
111
+ const isEmpty = !content?.trim();
112
+ if (isEmpty) {
113
+ (0, runtime_1.emitNervesEvent)({
114
+ level: "error",
115
+ event: "engine.error",
116
+ component: "engine",
117
+ message: "empty assistant content detected",
118
+ meta: { reason: "empty" },
119
+ });
120
+ return { reason: "empty", message: KICK_MESSAGES.empty };
121
+ }
122
+ if (hasToolIntent(content)) {
123
+ (0, runtime_1.emitNervesEvent)({
124
+ level: "error",
125
+ event: "engine.error",
126
+ component: "engine",
127
+ message: "narration-style response detected",
128
+ meta: { reason: "narration" },
129
+ });
130
+ return { reason: "narration", message: KICK_MESSAGES.narration };
131
+ }
132
+ if (options?.toolChoiceRequired) {
133
+ (0, runtime_1.emitNervesEvent)({
134
+ level: "error",
135
+ event: "engine.error",
136
+ component: "engine",
137
+ message: "tool-required mode response missing tool call",
138
+ meta: { reason: "tool_required" },
139
+ });
140
+ return { reason: "tool_required", message: KICK_MESSAGES.tool_required };
141
+ }
142
+ return null;
143
+ }
144
+ const runtime_1 = require("../nerves/runtime");
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HARNESS_BOOTSTRAP_PHASES = void 0;
4
+ exports.HARNESS_BOOTSTRAP_PHASES = ["bundle", "psyche", "inner-dialog"];
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createAnthropicProviderRuntime = createAnthropicProviderRuntime;
7
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
8
+ const config_1 = require("../config");
9
+ const identity_1 = require("../identity");
10
+ const runtime_1 = require("../../nerves/runtime");
11
+ const ANTHROPIC_SETUP_TOKEN_PREFIX = "sk-ant-oat01-";
12
+ const ANTHROPIC_SETUP_TOKEN_MIN_LENGTH = 80;
13
+ const ANTHROPIC_OAUTH_BETA_HEADER = "claude-code-20250219,oauth-2025-04-20,fine-grained-tool-streaming-2025-05-14,interleaved-thinking-2025-05-14";
14
+ function getAnthropicSecretsPathForGuidance() {
15
+ return (0, identity_1.getAgentSecretsPath)();
16
+ }
17
+ function getAnthropicAgentNameForGuidance() {
18
+ return (0, identity_1.getAgentName)();
19
+ }
20
+ function getAnthropicSetupTokenInstructions() {
21
+ const agentName = getAnthropicAgentNameForGuidance();
22
+ return [
23
+ "Fix:",
24
+ ` 1. Run \`npm run auth:claude-setup-token -- --agent ${agentName}\``,
25
+ " (or run `claude setup-token` and paste the token manually)",
26
+ ` 2. Open ${getAnthropicSecretsPathForGuidance()}`,
27
+ " 3. Confirm providers.anthropic.setupToken is set",
28
+ ].join("\n");
29
+ }
30
+ function getAnthropicReauthGuidance(reason) {
31
+ return [
32
+ "Anthropic configuration error.",
33
+ reason,
34
+ getAnthropicSetupTokenInstructions(),
35
+ ].join("\n");
36
+ }
37
+ function resolveAnthropicSetupTokenCredential() {
38
+ const anthropicConfig = (0, config_1.getAnthropicConfig)();
39
+ const token = anthropicConfig.setupToken?.trim();
40
+ if (!token) {
41
+ throw new Error(getAnthropicReauthGuidance("Anthropic provider is selected but no setup-token credential was found."));
42
+ }
43
+ if (!token.startsWith(ANTHROPIC_SETUP_TOKEN_PREFIX)) {
44
+ throw new Error(getAnthropicReauthGuidance(`Anthropic credential is not a setup-token (expected prefix ${ANTHROPIC_SETUP_TOKEN_PREFIX}).`));
45
+ }
46
+ if (token.length < ANTHROPIC_SETUP_TOKEN_MIN_LENGTH) {
47
+ throw new Error(getAnthropicReauthGuidance("Anthropic setup-token looks too short."));
48
+ }
49
+ return { token };
50
+ }
51
+ function toAnthropicTextContent(content) {
52
+ if (typeof content === "string")
53
+ return content;
54
+ if (!Array.isArray(content))
55
+ return "";
56
+ return content
57
+ .filter((part) => (typeof part === "object" &&
58
+ part !== null &&
59
+ part.type === "text"))
60
+ .map((part) => (typeof part.text === "string" ? part.text : ""))
61
+ .join("\n");
62
+ }
63
+ function parseToolCallInput(argumentsJson) {
64
+ if (!argumentsJson.trim())
65
+ return {};
66
+ try {
67
+ const parsed = JSON.parse(argumentsJson);
68
+ return parsed && typeof parsed === "object" ? parsed : {};
69
+ }
70
+ catch {
71
+ return {};
72
+ }
73
+ }
74
+ function toAnthropicMessages(messages) {
75
+ let system;
76
+ const converted = [];
77
+ for (const msg of messages) {
78
+ if (msg.role === "system") {
79
+ if (!system) {
80
+ const text = toAnthropicTextContent(msg.content);
81
+ system = text || undefined;
82
+ }
83
+ continue;
84
+ }
85
+ if (msg.role === "user") {
86
+ converted.push({
87
+ role: "user",
88
+ content: toAnthropicTextContent(msg.content),
89
+ });
90
+ continue;
91
+ }
92
+ if (msg.role === "assistant") {
93
+ const assistant = msg;
94
+ const blocks = [];
95
+ const text = toAnthropicTextContent(assistant.content);
96
+ if (text) {
97
+ blocks.push({ type: "text", text });
98
+ }
99
+ if (assistant.tool_calls) {
100
+ for (const toolCall of assistant.tool_calls) {
101
+ blocks.push({
102
+ type: "tool_use",
103
+ id: toolCall.id,
104
+ name: toolCall.function.name,
105
+ input: parseToolCallInput(toolCall.function.arguments),
106
+ });
107
+ }
108
+ }
109
+ if (blocks.length === 0) {
110
+ blocks.push({ type: "text", text: "" });
111
+ }
112
+ converted.push({ role: "assistant", content: blocks });
113
+ continue;
114
+ }
115
+ if (msg.role === "tool") {
116
+ const tool = msg;
117
+ converted.push({
118
+ role: "user",
119
+ content: [
120
+ {
121
+ type: "tool_result",
122
+ tool_use_id: tool.tool_call_id,
123
+ content: toAnthropicTextContent(tool.content),
124
+ },
125
+ ],
126
+ });
127
+ }
128
+ }
129
+ return { system, messages: converted };
130
+ }
131
+ function toAnthropicTools(tools) {
132
+ return tools.map((tool) => ({
133
+ name: tool.function.name,
134
+ description: tool.function.description ?? "",
135
+ input_schema: tool.function.parameters ?? { type: "object", properties: {} },
136
+ }));
137
+ }
138
+ function toAnthropicUsage(raw) {
139
+ const inputTokens = Number(raw.input_tokens ?? 0) || 0;
140
+ const cacheCreateTokens = Number(raw.cache_creation_input_tokens ?? 0) || 0;
141
+ const cacheReadTokens = Number(raw.cache_read_input_tokens ?? 0) || 0;
142
+ const outputTokens = Number(raw.output_tokens ?? 0) || 0;
143
+ const totalInputTokens = inputTokens + cacheCreateTokens + cacheReadTokens;
144
+ return {
145
+ input_tokens: totalInputTokens,
146
+ output_tokens: outputTokens,
147
+ reasoning_tokens: 0,
148
+ total_tokens: totalInputTokens + outputTokens,
149
+ };
150
+ }
151
+ function mergeAnthropicToolArguments(current, partial) {
152
+ if (!partial)
153
+ return current;
154
+ const trimmedCurrent = current.trim();
155
+ const trimmedPartial = partial.trim();
156
+ // If streaming restarts with a full JSON object/array fragment, trust it.
157
+ if (trimmedPartial.startsWith("{") || trimmedPartial.startsWith("[")) {
158
+ return partial;
159
+ }
160
+ // Anthropic can emit block.input as a complete object and then emit
161
+ // additional members as ',\"k\":v' deltas; merge those safely.
162
+ if (trimmedCurrent.startsWith("{") && trimmedCurrent.endsWith("}")) {
163
+ const inner = trimmedCurrent.slice(1, -1).trim();
164
+ let suffix = partial;
165
+ if (!inner && suffix.startsWith(",")) {
166
+ suffix = suffix.slice(1);
167
+ }
168
+ return `{${inner}${suffix}}`;
169
+ }
170
+ return current + partial;
171
+ }
172
+ 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
+ const lower = error.message.toLowerCase();
179
+ return (lower.includes("oauth authentication") ||
180
+ lower.includes("authentication failed") ||
181
+ lower.includes("unauthorized") ||
182
+ lower.includes("invalid api key"));
183
+ }
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
+ async function streamAnthropicMessages(client, model, request) {
192
+ const { system, messages } = toAnthropicMessages(request.messages);
193
+ const anthropicTools = toAnthropicTools(request.activeTools);
194
+ const params = {
195
+ model,
196
+ max_tokens: 4096,
197
+ messages,
198
+ stream: true,
199
+ };
200
+ if (system)
201
+ params.system = system;
202
+ if (anthropicTools.length > 0)
203
+ params.tools = anthropicTools;
204
+ if (request.toolChoiceRequired && anthropicTools.length > 0) {
205
+ params.tool_choice = { type: "any" };
206
+ }
207
+ let response;
208
+ try {
209
+ response = await client.messages.create(params, request.signal ? { signal: request.signal } : {});
210
+ }
211
+ catch (error) {
212
+ throw withAnthropicAuthGuidance(error);
213
+ }
214
+ let content = "";
215
+ let streamStarted = false;
216
+ let usage;
217
+ const toolCalls = new Map();
218
+ try {
219
+ for await (const event of response) {
220
+ if (request.signal?.aborted)
221
+ break;
222
+ const eventType = String(event.type ?? "");
223
+ if (eventType === "content_block_start") {
224
+ const block = event.content_block;
225
+ if (block?.type === "tool_use") {
226
+ const index = Number(event.index);
227
+ const rawInput = block.input;
228
+ const input = rawInput && typeof rawInput === "object"
229
+ ? JSON.stringify(rawInput)
230
+ : "";
231
+ toolCalls.set(index, {
232
+ id: String(block.id ?? ""),
233
+ name: String(block.name ?? ""),
234
+ arguments: input,
235
+ });
236
+ }
237
+ continue;
238
+ }
239
+ if (eventType === "content_block_delta") {
240
+ const delta = event.delta;
241
+ const deltaType = String(delta?.type ?? "");
242
+ if (deltaType === "text_delta") {
243
+ if (!streamStarted) {
244
+ request.callbacks.onModelStreamStart();
245
+ streamStarted = true;
246
+ }
247
+ const text = String(delta?.text ?? "");
248
+ content += text;
249
+ request.callbacks.onTextChunk(text);
250
+ continue;
251
+ }
252
+ if (deltaType === "thinking_delta") {
253
+ if (!streamStarted) {
254
+ request.callbacks.onModelStreamStart();
255
+ streamStarted = true;
256
+ }
257
+ request.callbacks.onReasoningChunk(String(delta?.thinking ?? ""));
258
+ continue;
259
+ }
260
+ if (deltaType === "input_json_delta") {
261
+ const index = Number(event.index);
262
+ const existing = toolCalls.get(index);
263
+ if (existing) {
264
+ existing.arguments = mergeAnthropicToolArguments(existing.arguments, String(delta?.partial_json ?? ""));
265
+ }
266
+ continue;
267
+ }
268
+ }
269
+ if (eventType === "content_block_stop") {
270
+ const index = Number(event.index);
271
+ const existing = toolCalls.get(index);
272
+ if (existing && existing.arguments.trim().length === 0) {
273
+ existing.arguments = "{}";
274
+ }
275
+ continue;
276
+ }
277
+ if (eventType === "message_delta") {
278
+ const rawUsage = event.usage;
279
+ if (rawUsage && typeof rawUsage === "object") {
280
+ usage = toAnthropicUsage(rawUsage);
281
+ }
282
+ }
283
+ }
284
+ }
285
+ catch (error) {
286
+ throw withAnthropicAuthGuidance(error);
287
+ }
288
+ return {
289
+ content,
290
+ toolCalls: [...toolCalls.values()],
291
+ outputItems: [],
292
+ usage,
293
+ };
294
+ }
295
+ function createAnthropicProviderRuntime() {
296
+ (0, runtime_1.emitNervesEvent)({
297
+ component: "engine",
298
+ event: "engine.provider_init",
299
+ message: "anthropic provider init",
300
+ meta: { provider: "anthropic" },
301
+ });
302
+ 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."));
305
+ }
306
+ 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
+ });
315
+ return {
316
+ id: "anthropic",
317
+ model: anthropicConfig.model,
318
+ client,
319
+ resetTurnState(_messages) {
320
+ // Anthropic request payload is derived from canonical messages each turn.
321
+ },
322
+ appendToolOutput(_callId, _output) {
323
+ // Anthropic uses canonical messages for tool_result tracking.
324
+ },
325
+ streamTurn(request) {
326
+ return streamAnthropicMessages(client, anthropicConfig.model, request);
327
+ },
328
+ };
329
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAzureProviderRuntime = createAzureProviderRuntime;
4
+ const openai_1 = require("openai");
5
+ const config_1 = require("../config");
6
+ const runtime_1 = require("../../nerves/runtime");
7
+ const streaming_1 = require("../streaming");
8
+ function createAzureProviderRuntime() {
9
+ (0, runtime_1.emitNervesEvent)({
10
+ component: "engine",
11
+ event: "engine.provider_init",
12
+ message: "azure provider init",
13
+ meta: { provider: "azure" },
14
+ });
15
+ const azureConfig = (0, config_1.getAzureConfig)();
16
+ if (!(azureConfig.apiKey && azureConfig.endpoint && azureConfig.deployment && azureConfig.modelName)) {
17
+ throw new Error("provider 'azure' is selected in agent.json but providers.azure is incomplete in secrets.json.");
18
+ }
19
+ const client = new openai_1.AzureOpenAI({
20
+ apiKey: azureConfig.apiKey,
21
+ endpoint: azureConfig.endpoint.replace(/\/openai.*$/, ""),
22
+ deployment: azureConfig.deployment,
23
+ apiVersion: azureConfig.apiVersion,
24
+ timeout: 30000,
25
+ maxRetries: 0,
26
+ });
27
+ let nativeInput = null;
28
+ let nativeInstructions = "";
29
+ return {
30
+ id: "azure",
31
+ model: azureConfig.modelName,
32
+ client,
33
+ resetTurnState(messages) {
34
+ const { instructions, input } = (0, streaming_1.toResponsesInput)(messages);
35
+ nativeInput = input;
36
+ nativeInstructions = instructions;
37
+ },
38
+ appendToolOutput(callId, output) {
39
+ if (!nativeInput)
40
+ return;
41
+ nativeInput.push({ type: "function_call_output", call_id: callId, output });
42
+ },
43
+ async streamTurn(request) {
44
+ if (!nativeInput)
45
+ this.resetTurnState(request.messages);
46
+ const params = {
47
+ model: this.model,
48
+ input: nativeInput,
49
+ instructions: nativeInstructions,
50
+ tools: (0, streaming_1.toResponsesTools)(request.activeTools),
51
+ reasoning: { effort: "medium", summary: "detailed" },
52
+ stream: true,
53
+ store: false,
54
+ include: ["reasoning.encrypted_content"],
55
+ };
56
+ if (request.traceId)
57
+ params.metadata = { trace_id: request.traceId };
58
+ if (request.toolChoiceRequired)
59
+ params.tool_choice = "required";
60
+ const result = await (0, streaming_1.streamResponsesApi)(this.client, params, request.callbacks, request.signal);
61
+ for (const item of result.outputItems)
62
+ nativeInput.push(item);
63
+ return result;
64
+ },
65
+ };
66
+ }
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMinimaxProviderRuntime = createMinimaxProviderRuntime;
7
+ const openai_1 = __importDefault(require("openai"));
8
+ const config_1 = require("../config");
9
+ const runtime_1 = require("../../nerves/runtime");
10
+ const streaming_1 = require("../streaming");
11
+ function createMinimaxProviderRuntime() {
12
+ (0, runtime_1.emitNervesEvent)({
13
+ component: "engine",
14
+ event: "engine.provider_init",
15
+ message: "minimax provider init",
16
+ meta: { provider: "minimax" },
17
+ });
18
+ const minimaxConfig = (0, config_1.getMinimaxConfig)();
19
+ if (!minimaxConfig.apiKey) {
20
+ throw new Error("provider 'minimax' is selected in agent.json but providers.minimax.apiKey is missing in secrets.json.");
21
+ }
22
+ const client = new openai_1.default({
23
+ apiKey: minimaxConfig.apiKey,
24
+ baseURL: "https://api.minimaxi.chat/v1",
25
+ timeout: 30000,
26
+ maxRetries: 0,
27
+ });
28
+ return {
29
+ id: "minimax",
30
+ model: minimaxConfig.model,
31
+ client,
32
+ resetTurnState(_messages) {
33
+ // No provider-owned turn state for chat-completions providers.
34
+ },
35
+ appendToolOutput(_callId, _output) {
36
+ // Chat-completions providers rely on canonical messages only.
37
+ },
38
+ streamTurn(request) {
39
+ const params = {
40
+ messages: request.messages,
41
+ tools: request.activeTools,
42
+ stream: true,
43
+ };
44
+ if (this.model)
45
+ params.model = this.model;
46
+ if (request.traceId)
47
+ params.metadata = { trace_id: request.traceId };
48
+ if (request.toolChoiceRequired)
49
+ params.tool_choice = "required";
50
+ return (0, streaming_1.streamChatCompletion)(this.client, params, request.callbacks, request.signal);
51
+ },
52
+ };
53
+ }