@open-multi-agent/core 1.4.0
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/LICENSE +21 -0
- package/README.md +373 -0
- package/dist/agent/agent.d.ts +153 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +559 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/loop-detector.d.ts +39 -0
- package/dist/agent/loop-detector.d.ts.map +1 -0
- package/dist/agent/loop-detector.js +122 -0
- package/dist/agent/loop-detector.js.map +1 -0
- package/dist/agent/pool.d.ts +158 -0
- package/dist/agent/pool.d.ts.map +1 -0
- package/dist/agent/pool.js +320 -0
- package/dist/agent/pool.js.map +1 -0
- package/dist/agent/runner.d.ts +242 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +943 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/structured-output.d.ts +33 -0
- package/dist/agent/structured-output.d.ts.map +1 -0
- package/dist/agent/structured-output.js +116 -0
- package/dist/agent/structured-output.js.map +1 -0
- package/dist/cli/oma.d.ts +30 -0
- package/dist/cli/oma.d.ts.map +1 -0
- package/dist/cli/oma.js +433 -0
- package/dist/cli/oma.js.map +1 -0
- package/dist/dashboard/layout-tasks.d.ts +23 -0
- package/dist/dashboard/layout-tasks.d.ts.map +1 -0
- package/dist/dashboard/layout-tasks.js +79 -0
- package/dist/dashboard/layout-tasks.js.map +1 -0
- package/dist/dashboard/render-team-run-dashboard.d.ts +11 -0
- package/dist/dashboard/render-team-run-dashboard.d.ts.map +1 -0
- package/dist/dashboard/render-team-run-dashboard.js +456 -0
- package/dist/dashboard/render-team-run-dashboard.js.map +1 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +92 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/adapter.d.ts +54 -0
- package/dist/llm/adapter.d.ts.map +1 -0
- package/dist/llm/adapter.js +101 -0
- package/dist/llm/adapter.js.map +1 -0
- package/dist/llm/anthropic.d.ts +57 -0
- package/dist/llm/anthropic.d.ts.map +1 -0
- package/dist/llm/anthropic.js +432 -0
- package/dist/llm/anthropic.js.map +1 -0
- package/dist/llm/azure-openai.d.ts +74 -0
- package/dist/llm/azure-openai.d.ts.map +1 -0
- package/dist/llm/azure-openai.js +267 -0
- package/dist/llm/azure-openai.js.map +1 -0
- package/dist/llm/bedrock.d.ts +41 -0
- package/dist/llm/bedrock.d.ts.map +1 -0
- package/dist/llm/bedrock.js +345 -0
- package/dist/llm/bedrock.js.map +1 -0
- package/dist/llm/copilot.d.ts +92 -0
- package/dist/llm/copilot.d.ts.map +1 -0
- package/dist/llm/copilot.js +433 -0
- package/dist/llm/copilot.js.map +1 -0
- package/dist/llm/deepseek.d.ts +21 -0
- package/dist/llm/deepseek.d.ts.map +1 -0
- package/dist/llm/deepseek.js +24 -0
- package/dist/llm/deepseek.js.map +1 -0
- package/dist/llm/gemini.d.ts +65 -0
- package/dist/llm/gemini.d.ts.map +1 -0
- package/dist/llm/gemini.js +427 -0
- package/dist/llm/gemini.js.map +1 -0
- package/dist/llm/grok.d.ts +21 -0
- package/dist/llm/grok.d.ts.map +1 -0
- package/dist/llm/grok.js +24 -0
- package/dist/llm/grok.js.map +1 -0
- package/dist/llm/minimax.d.ts +21 -0
- package/dist/llm/minimax.d.ts.map +1 -0
- package/dist/llm/minimax.js +24 -0
- package/dist/llm/minimax.js.map +1 -0
- package/dist/llm/openai-common.d.ts +65 -0
- package/dist/llm/openai-common.d.ts.map +1 -0
- package/dist/llm/openai-common.js +286 -0
- package/dist/llm/openai-common.js.map +1 -0
- package/dist/llm/openai.d.ts +63 -0
- package/dist/llm/openai.d.ts.map +1 -0
- package/dist/llm/openai.js +256 -0
- package/dist/llm/openai.js.map +1 -0
- package/dist/llm/qiniu.d.ts +21 -0
- package/dist/llm/qiniu.d.ts.map +1 -0
- package/dist/llm/qiniu.js +24 -0
- package/dist/llm/qiniu.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +2 -0
- package/dist/mcp.js.map +1 -0
- package/dist/memory/shared.d.ts +162 -0
- package/dist/memory/shared.d.ts.map +1 -0
- package/dist/memory/shared.js +294 -0
- package/dist/memory/shared.js.map +1 -0
- package/dist/memory/store.d.ts +72 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +121 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +245 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +1400 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/scheduler.d.ts +112 -0
- package/dist/orchestrator/scheduler.d.ts.map +1 -0
- package/dist/orchestrator/scheduler.js +256 -0
- package/dist/orchestrator/scheduler.js.map +1 -0
- package/dist/task/queue.d.ts +191 -0
- package/dist/task/queue.d.ts.map +1 -0
- package/dist/task/queue.js +408 -0
- package/dist/task/queue.js.map +1 -0
- package/dist/task/task.d.ts +90 -0
- package/dist/task/task.d.ts.map +1 -0
- package/dist/task/task.js +206 -0
- package/dist/task/task.js.map +1 -0
- package/dist/team/messaging.d.ts +106 -0
- package/dist/team/messaging.d.ts.map +1 -0
- package/dist/team/messaging.js +183 -0
- package/dist/team/messaging.js.map +1 -0
- package/dist/team/team.d.ts +141 -0
- package/dist/team/team.d.ts.map +1 -0
- package/dist/team/team.js +293 -0
- package/dist/team/team.js.map +1 -0
- package/dist/tool/built-in/bash.d.ts +12 -0
- package/dist/tool/built-in/bash.d.ts.map +1 -0
- package/dist/tool/built-in/bash.js +133 -0
- package/dist/tool/built-in/bash.js.map +1 -0
- package/dist/tool/built-in/delegate.d.ts +29 -0
- package/dist/tool/built-in/delegate.d.ts.map +1 -0
- package/dist/tool/built-in/delegate.js +92 -0
- package/dist/tool/built-in/delegate.js.map +1 -0
- package/dist/tool/built-in/file-edit.d.ts +14 -0
- package/dist/tool/built-in/file-edit.d.ts.map +1 -0
- package/dist/tool/built-in/file-edit.js +130 -0
- package/dist/tool/built-in/file-edit.js.map +1 -0
- package/dist/tool/built-in/file-read.d.ts +12 -0
- package/dist/tool/built-in/file-read.d.ts.map +1 -0
- package/dist/tool/built-in/file-read.js +82 -0
- package/dist/tool/built-in/file-read.js.map +1 -0
- package/dist/tool/built-in/file-write.d.ts +11 -0
- package/dist/tool/built-in/file-write.d.ts.map +1 -0
- package/dist/tool/built-in/file-write.js +70 -0
- package/dist/tool/built-in/file-write.js.map +1 -0
- package/dist/tool/built-in/fs-walk.d.ts +23 -0
- package/dist/tool/built-in/fs-walk.d.ts.map +1 -0
- package/dist/tool/built-in/fs-walk.js +78 -0
- package/dist/tool/built-in/fs-walk.js.map +1 -0
- package/dist/tool/built-in/glob.d.ts +12 -0
- package/dist/tool/built-in/glob.d.ts.map +1 -0
- package/dist/tool/built-in/glob.js +82 -0
- package/dist/tool/built-in/glob.js.map +1 -0
- package/dist/tool/built-in/grep.d.ts +15 -0
- package/dist/tool/built-in/grep.d.ts.map +1 -0
- package/dist/tool/built-in/grep.js +218 -0
- package/dist/tool/built-in/grep.js.map +1 -0
- package/dist/tool/built-in/index.d.ts +48 -0
- package/dist/tool/built-in/index.d.ts.map +1 -0
- package/dist/tool/built-in/index.js +56 -0
- package/dist/tool/built-in/index.js.map +1 -0
- package/dist/tool/executor.d.ts +100 -0
- package/dist/tool/executor.d.ts.map +1 -0
- package/dist/tool/executor.js +184 -0
- package/dist/tool/executor.js.map +1 -0
- package/dist/tool/framework.d.ts +167 -0
- package/dist/tool/framework.d.ts.map +1 -0
- package/dist/tool/framework.js +402 -0
- package/dist/tool/framework.js.map +1 -0
- package/dist/tool/mcp.d.ts +31 -0
- package/dist/tool/mcp.d.ts.map +1 -0
- package/dist/tool/mcp.js +175 -0
- package/dist/tool/mcp.js.map +1 -0
- package/dist/tool/text-tool-extractor.d.ts +32 -0
- package/dist/tool/text-tool-extractor.d.ts.map +1 -0
- package/dist/tool/text-tool-extractor.js +195 -0
- package/dist/tool/text-tool-extractor.js.map +1 -0
- package/dist/types.d.ts +916 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/keywords.d.ts +18 -0
- package/dist/utils/keywords.d.ts.map +1 -0
- package/dist/utils/keywords.js +32 -0
- package/dist/utils/keywords.js.map +1 -0
- package/dist/utils/semaphore.d.ts +49 -0
- package/dist/utils/semaphore.d.ts.map +1 -0
- package/dist/utils/semaphore.js +89 -0
- package/dist/utils/semaphore.js.map +1 -0
- package/dist/utils/tokens.d.ts +7 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +30 -0
- package/dist/utils/tokens.js.map +1 -0
- package/dist/utils/trace.d.ts +12 -0
- package/dist/utils/trace.d.ts.map +1 -0
- package/dist/utils/trace.js +30 -0
- package/dist/utils/trace.js.map +1 -0
- package/docs/DECISIONS.md +49 -0
- package/docs/cli.md +265 -0
- package/docs/context-management.md +24 -0
- package/docs/featured-partner.md +28 -0
- package/docs/observability.md +56 -0
- package/docs/providers.md +78 -0
- package/docs/shared-memory.md +27 -0
- package/docs/tool-configuration.md +152 -0
- package/package.json +96 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Anthropic Claude adapter implementing {@link LLMAdapter}.
|
|
3
|
+
*
|
|
4
|
+
* Converts between the framework's internal {@link ContentBlock} types and the
|
|
5
|
+
* Anthropic SDK's wire format, handling tool definitions, system prompts, and
|
|
6
|
+
* both batch and streaming response paths.
|
|
7
|
+
*
|
|
8
|
+
* API key resolution order:
|
|
9
|
+
* 1. `apiKey` constructor argument
|
|
10
|
+
* 2. `ANTHROPIC_API_KEY` environment variable
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { AnthropicAdapter } from './anthropic.js'
|
|
15
|
+
*
|
|
16
|
+
* const adapter = new AnthropicAdapter()
|
|
17
|
+
* const response = await adapter.chat(messages, {
|
|
18
|
+
* model: 'claude-opus-4-6',
|
|
19
|
+
* maxTokens: 1024,
|
|
20
|
+
* })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
// Internal helpers
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
/**
|
|
28
|
+
* Convert a single framework {@link ContentBlock} into an Anthropic
|
|
29
|
+
* {@link ContentBlockParam} suitable for the `messages` array, or `null`
|
|
30
|
+
* when the block has no faithful representation on the wire (e.g. a
|
|
31
|
+
* reasoning block from another provider that lacks an Anthropic signature).
|
|
32
|
+
*
|
|
33
|
+
* `tool_result` blocks are only valid inside `user`-role messages, which is
|
|
34
|
+
* handled by {@link toAnthropicMessages} based on role context.
|
|
35
|
+
*/
|
|
36
|
+
function toAnthropicContentBlockParam(block) {
|
|
37
|
+
switch (block.type) {
|
|
38
|
+
case 'reasoning': {
|
|
39
|
+
// Anthropic strictly validates the signature on echoed thinking
|
|
40
|
+
// blocks, so we only round-trip blocks that originated here:
|
|
41
|
+
// - `redactedData` -> `redacted_thinking` (opaque, signature lives inside)
|
|
42
|
+
// - `signature` -> `thinking` block with text + signature
|
|
43
|
+
// Cross-provider reasoning (e.g. Gemini thought summaries) and
|
|
44
|
+
// unsigned reasoning text from a single-turn final response carry no
|
|
45
|
+
// valid signature, so dropping them is safer than risking an API
|
|
46
|
+
// rejection on the next turn.
|
|
47
|
+
if (block.redactedData !== undefined) {
|
|
48
|
+
const param = {
|
|
49
|
+
type: 'redacted_thinking',
|
|
50
|
+
data: block.redactedData,
|
|
51
|
+
};
|
|
52
|
+
return param;
|
|
53
|
+
}
|
|
54
|
+
if (block.signature !== undefined) {
|
|
55
|
+
const param = {
|
|
56
|
+
type: 'thinking',
|
|
57
|
+
thinking: block.text,
|
|
58
|
+
signature: block.signature,
|
|
59
|
+
};
|
|
60
|
+
return param;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
case 'text': {
|
|
65
|
+
const param = { type: 'text', text: block.text };
|
|
66
|
+
return param;
|
|
67
|
+
}
|
|
68
|
+
case 'tool_use': {
|
|
69
|
+
const param = {
|
|
70
|
+
type: 'tool_use',
|
|
71
|
+
id: block.id,
|
|
72
|
+
name: block.name,
|
|
73
|
+
input: block.input,
|
|
74
|
+
};
|
|
75
|
+
return param;
|
|
76
|
+
}
|
|
77
|
+
case 'tool_result': {
|
|
78
|
+
const param = {
|
|
79
|
+
type: 'tool_result',
|
|
80
|
+
tool_use_id: block.tool_use_id,
|
|
81
|
+
content: block.content,
|
|
82
|
+
is_error: block.is_error,
|
|
83
|
+
};
|
|
84
|
+
return param;
|
|
85
|
+
}
|
|
86
|
+
case 'image': {
|
|
87
|
+
// Anthropic only accepts a subset of MIME types; we pass them through
|
|
88
|
+
// trusting the caller to supply a valid media_type value.
|
|
89
|
+
const param = {
|
|
90
|
+
type: 'image',
|
|
91
|
+
source: {
|
|
92
|
+
type: 'base64',
|
|
93
|
+
media_type: block.source.media_type,
|
|
94
|
+
data: block.source.data,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
return param;
|
|
98
|
+
}
|
|
99
|
+
default: {
|
|
100
|
+
// Exhaustiveness guard — TypeScript will flag this at compile time if a
|
|
101
|
+
// new variant is added to ContentBlock without updating this switch.
|
|
102
|
+
const _exhaustive = block;
|
|
103
|
+
throw new Error(`Unhandled content block type: ${JSON.stringify(_exhaustive)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Convert framework messages into Anthropic's `MessageParam[]` format.
|
|
109
|
+
*
|
|
110
|
+
* The Anthropic API requires strict user/assistant alternation. We do not
|
|
111
|
+
* enforce that here — the caller is responsible for producing a valid
|
|
112
|
+
* conversation history.
|
|
113
|
+
*/
|
|
114
|
+
function toAnthropicMessages(messages) {
|
|
115
|
+
return messages.map((msg) => ({
|
|
116
|
+
role: msg.role,
|
|
117
|
+
content: msg.content
|
|
118
|
+
.map(toAnthropicContentBlockParam)
|
|
119
|
+
.filter((p) => p !== null),
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Convert framework {@link LLMToolDef}s into Anthropic's `Tool` objects.
|
|
124
|
+
*
|
|
125
|
+
* The `inputSchema` on {@link LLMToolDef} is already a plain JSON Schema
|
|
126
|
+
* object, so we just need to reshape the wrapper.
|
|
127
|
+
*/
|
|
128
|
+
function toAnthropicTools(tools) {
|
|
129
|
+
return tools.map((t) => ({
|
|
130
|
+
name: t.name,
|
|
131
|
+
description: t.description,
|
|
132
|
+
input_schema: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
...t.inputSchema,
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Convert an Anthropic SDK `ContentBlock` into a framework {@link ContentBlock}.
|
|
140
|
+
*
|
|
141
|
+
* We only map the subset of SDK types that the framework exposes. Unknown
|
|
142
|
+
* variants are converted to a text block carrying a stringified
|
|
143
|
+
* representation so data is never silently dropped.
|
|
144
|
+
*/
|
|
145
|
+
function fromAnthropicContentBlock(block) {
|
|
146
|
+
switch (block.type) {
|
|
147
|
+
case 'thinking': {
|
|
148
|
+
// `signature` is required by the API to continue a multi-turn extended
|
|
149
|
+
// thinking conversation. Carry it on the framework block so the next
|
|
150
|
+
// turn can echo the original reasoning back unchanged.
|
|
151
|
+
const reasoning = {
|
|
152
|
+
type: 'reasoning',
|
|
153
|
+
text: block.thinking,
|
|
154
|
+
signature: block.signature,
|
|
155
|
+
};
|
|
156
|
+
return reasoning;
|
|
157
|
+
}
|
|
158
|
+
case 'redacted_thinking': {
|
|
159
|
+
// Anthropic returns redacted thinking when its safety system replaces
|
|
160
|
+
// the raw reasoning text with an opaque encrypted payload. The block
|
|
161
|
+
// must still be echoed back on subsequent turns, so we carry the
|
|
162
|
+
// payload via `redactedData` and leave `text` empty.
|
|
163
|
+
const reasoning = {
|
|
164
|
+
type: 'reasoning',
|
|
165
|
+
text: '',
|
|
166
|
+
redactedData: block.data,
|
|
167
|
+
};
|
|
168
|
+
return reasoning;
|
|
169
|
+
}
|
|
170
|
+
case 'text': {
|
|
171
|
+
const text = { type: 'text', text: block.text };
|
|
172
|
+
return text;
|
|
173
|
+
}
|
|
174
|
+
case 'tool_use': {
|
|
175
|
+
const toolUse = {
|
|
176
|
+
type: 'tool_use',
|
|
177
|
+
id: block.id,
|
|
178
|
+
name: block.name,
|
|
179
|
+
input: block.input,
|
|
180
|
+
};
|
|
181
|
+
return toolUse;
|
|
182
|
+
}
|
|
183
|
+
default: {
|
|
184
|
+
// Graceful degradation for SDK types we don't model.
|
|
185
|
+
const fallback = {
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: `[unsupported block type: ${block.type}]`,
|
|
188
|
+
};
|
|
189
|
+
return fallback;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Convert the framework's {@link ThinkingConfig} into Anthropic's
|
|
195
|
+
* `thinking` request param. Returns `undefined` when the caller hasn't
|
|
196
|
+
* opted in, leaving the field absent from the request payload.
|
|
197
|
+
*
|
|
198
|
+
* Validates against the API's two `budget_tokens` constraints:
|
|
199
|
+
* 1. `budget_tokens >= 1024` (SDK-documented minimum, smaller budgets
|
|
200
|
+
* yield no useful reasoning)
|
|
201
|
+
* 2. `budget_tokens < max_tokens` (docs: "budget_tokens must be set to a
|
|
202
|
+
* value less than max_tokens"). Throws early with a clear message
|
|
203
|
+
* rather than letting Anthropic return a 400.
|
|
204
|
+
*
|
|
205
|
+
* Defaults `budgetTokens` to 1024 when enabled without an explicit value;
|
|
206
|
+
* combined with the second constraint, this means a caller passing
|
|
207
|
+
* `thinking.enabled = true` MUST also set `maxTokens > 1024`.
|
|
208
|
+
*
|
|
209
|
+
* Model compatibility: emits `{type: 'enabled', budget_tokens}` which is
|
|
210
|
+
* supported by Claude Sonnet 3.7 and all Claude 4.x models up to and
|
|
211
|
+
* including 4.6 (deprecated on 4.6 in favor of `adaptive`). Claude Opus 4.7+
|
|
212
|
+
* accepts only `{type: 'adaptive'}` and rejects this shape with HTTP 400.
|
|
213
|
+
* Adaptive thinking support is tracked as a follow-up to RFC #200's phase 1.
|
|
214
|
+
*
|
|
215
|
+
* The `interleaved-thinking-2025-05-14` beta header (which would relax the
|
|
216
|
+
* `budget_tokens < max_tokens` rule for Claude 4.x manual mode) is not yet
|
|
217
|
+
* wired up — see RFC #200 phase 2.
|
|
218
|
+
*/
|
|
219
|
+
function toAnthropicThinkingParam(thinking, maxTokens) {
|
|
220
|
+
if (thinking === undefined || !thinking.enabled)
|
|
221
|
+
return undefined;
|
|
222
|
+
const budget = thinking.budgetTokens ?? 1024;
|
|
223
|
+
if (budget < 1024) {
|
|
224
|
+
throw new Error(`[anthropic] thinking.budgetTokens must be >= 1024 (got ${budget}); ` +
|
|
225
|
+
`the Anthropic API enforces this minimum.`);
|
|
226
|
+
}
|
|
227
|
+
if (budget >= maxTokens) {
|
|
228
|
+
throw new Error(`[anthropic] thinking.budgetTokens (${budget}) must be < maxTokens (${maxTokens}); ` +
|
|
229
|
+
`the Anthropic API rejects requests where budget_tokens >= max_tokens. ` +
|
|
230
|
+
`Either lower thinking.budgetTokens or raise maxTokens.`);
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
type: 'enabled',
|
|
234
|
+
budget_tokens: budget,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Adapter implementation
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
/**
|
|
241
|
+
* LLM adapter backed by the Anthropic Claude API.
|
|
242
|
+
*
|
|
243
|
+
* Thread-safe — a single instance may be shared across concurrent agent runs.
|
|
244
|
+
* The underlying SDK client is stateless across requests.
|
|
245
|
+
*/
|
|
246
|
+
export class AnthropicAdapter {
|
|
247
|
+
name = 'anthropic';
|
|
248
|
+
#client;
|
|
249
|
+
constructor(apiKey, baseURL) {
|
|
250
|
+
this.#client = new Anthropic({
|
|
251
|
+
apiKey: apiKey ?? process.env['ANTHROPIC_API_KEY'],
|
|
252
|
+
baseURL,
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
// -------------------------------------------------------------------------
|
|
256
|
+
// chat()
|
|
257
|
+
// -------------------------------------------------------------------------
|
|
258
|
+
/**
|
|
259
|
+
* Send a synchronous (non-streaming) chat request and return the complete
|
|
260
|
+
* {@link LLMResponse}.
|
|
261
|
+
*
|
|
262
|
+
* Throws an `Anthropic.APIError` on non-2xx responses. Callers should catch
|
|
263
|
+
* and handle these (e.g. rate limits, context window exceeded).
|
|
264
|
+
*/
|
|
265
|
+
async chat(messages, options) {
|
|
266
|
+
const anthropicMessages = toAnthropicMessages(messages);
|
|
267
|
+
const effectiveMaxTokens = options.maxTokens ?? 4096;
|
|
268
|
+
const response = await this.#client.messages.create({
|
|
269
|
+
// Sampling params first so extraBody can override them. Structural
|
|
270
|
+
// fields (model/messages/system/tools/thinking) come after extraBody
|
|
271
|
+
// so users cannot accidentally clobber them via extraBody.
|
|
272
|
+
max_tokens: effectiveMaxTokens,
|
|
273
|
+
temperature: options.temperature,
|
|
274
|
+
top_p: options.topP,
|
|
275
|
+
top_k: options.topK,
|
|
276
|
+
...options.extraBody,
|
|
277
|
+
model: options.model,
|
|
278
|
+
messages: anthropicMessages,
|
|
279
|
+
system: options.systemPrompt,
|
|
280
|
+
tools: options.tools ? toAnthropicTools(options.tools) : undefined,
|
|
281
|
+
thinking: toAnthropicThinkingParam(options.thinking, effectiveMaxTokens),
|
|
282
|
+
// Cast covers arbitrary `extraBody` keys not declared by the SDK.
|
|
283
|
+
}, {
|
|
284
|
+
signal: options.abortSignal,
|
|
285
|
+
});
|
|
286
|
+
const content = response.content.map(fromAnthropicContentBlock);
|
|
287
|
+
return {
|
|
288
|
+
id: response.id,
|
|
289
|
+
content,
|
|
290
|
+
model: response.model,
|
|
291
|
+
stop_reason: response.stop_reason ?? 'end_turn',
|
|
292
|
+
usage: {
|
|
293
|
+
input_tokens: response.usage.input_tokens,
|
|
294
|
+
output_tokens: response.usage.output_tokens,
|
|
295
|
+
},
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
// -------------------------------------------------------------------------
|
|
299
|
+
// stream()
|
|
300
|
+
// -------------------------------------------------------------------------
|
|
301
|
+
/**
|
|
302
|
+
* Send a streaming chat request and yield {@link StreamEvent}s as they
|
|
303
|
+
* arrive from the API.
|
|
304
|
+
*
|
|
305
|
+
* Sequence guarantees:
|
|
306
|
+
* - Zero or more `text` events containing incremental deltas
|
|
307
|
+
* - Zero or more `reasoning` events containing incremental thinking deltas
|
|
308
|
+
* - Zero or more `tool_use` events when the model calls a tool (emitted once
|
|
309
|
+
* per tool use, after input JSON has been fully assembled)
|
|
310
|
+
* - Exactly one terminal event: `done` (with the complete {@link LLMResponse}
|
|
311
|
+
* as `data`) or `error` (with an `Error` as `data`)
|
|
312
|
+
*/
|
|
313
|
+
async *stream(messages, options) {
|
|
314
|
+
const anthropicMessages = toAnthropicMessages(messages);
|
|
315
|
+
const effectiveMaxTokens = options.maxTokens ?? 4096;
|
|
316
|
+
// MessageStream gives us typed events and handles SSE reconnect internally.
|
|
317
|
+
const stream = this.#client.messages.stream({
|
|
318
|
+
// See chat() above for the rationale behind this field ordering.
|
|
319
|
+
max_tokens: effectiveMaxTokens,
|
|
320
|
+
temperature: options.temperature,
|
|
321
|
+
top_p: options.topP,
|
|
322
|
+
top_k: options.topK,
|
|
323
|
+
...options.extraBody,
|
|
324
|
+
model: options.model,
|
|
325
|
+
messages: anthropicMessages,
|
|
326
|
+
system: options.systemPrompt,
|
|
327
|
+
tools: options.tools ? toAnthropicTools(options.tools) : undefined,
|
|
328
|
+
thinking: toAnthropicThinkingParam(options.thinking, effectiveMaxTokens),
|
|
329
|
+
}, {
|
|
330
|
+
signal: options.abortSignal,
|
|
331
|
+
});
|
|
332
|
+
// Accumulate tool-use input JSON as it streams in.
|
|
333
|
+
// key = content block index, value = partially assembled input JSON string
|
|
334
|
+
const toolInputBuffers = new Map();
|
|
335
|
+
try {
|
|
336
|
+
for await (const event of stream) {
|
|
337
|
+
switch (event.type) {
|
|
338
|
+
case 'content_block_start': {
|
|
339
|
+
const block = event.content_block;
|
|
340
|
+
if (block.type === 'tool_use') {
|
|
341
|
+
toolInputBuffers.set(event.index, {
|
|
342
|
+
id: block.id,
|
|
343
|
+
name: block.name,
|
|
344
|
+
json: '',
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
case 'content_block_delta': {
|
|
350
|
+
const delta = event.delta;
|
|
351
|
+
switch (delta.type) {
|
|
352
|
+
case 'text_delta': {
|
|
353
|
+
const textEvent = { type: 'text', data: delta.text };
|
|
354
|
+
yield textEvent;
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
case 'thinking_delta': {
|
|
358
|
+
const reasoningEvent = { type: 'reasoning', data: delta.thinking };
|
|
359
|
+
yield reasoningEvent;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
case 'input_json_delta': {
|
|
363
|
+
const buf = toolInputBuffers.get(event.index);
|
|
364
|
+
if (buf !== undefined) {
|
|
365
|
+
buf.json += delta.partial_json;
|
|
366
|
+
}
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
default:
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
case 'content_block_stop': {
|
|
375
|
+
const buf = toolInputBuffers.get(event.index);
|
|
376
|
+
if (buf !== undefined) {
|
|
377
|
+
// Parse the accumulated JSON and emit a tool_use event.
|
|
378
|
+
let parsedInput = {};
|
|
379
|
+
try {
|
|
380
|
+
const parsed = JSON.parse(buf.json);
|
|
381
|
+
if (parsed !== null &&
|
|
382
|
+
typeof parsed === 'object' &&
|
|
383
|
+
!Array.isArray(parsed)) {
|
|
384
|
+
parsedInput = parsed;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch {
|
|
388
|
+
// Malformed JSON from the model — surface as an empty object
|
|
389
|
+
// rather than crashing the stream.
|
|
390
|
+
}
|
|
391
|
+
const toolUseBlock = {
|
|
392
|
+
type: 'tool_use',
|
|
393
|
+
id: buf.id,
|
|
394
|
+
name: buf.name,
|
|
395
|
+
input: parsedInput,
|
|
396
|
+
};
|
|
397
|
+
const toolUseEvent = { type: 'tool_use', data: toolUseBlock };
|
|
398
|
+
yield toolUseEvent;
|
|
399
|
+
toolInputBuffers.delete(event.index);
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
// message_start, message_delta, message_stop — we handle the final
|
|
404
|
+
// response via stream.finalMessage() below rather than piecemeal.
|
|
405
|
+
default:
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// Await the fully assembled final message (token counts, stop_reason, etc.)
|
|
410
|
+
const finalMessage = await stream.finalMessage();
|
|
411
|
+
const content = finalMessage.content.map(fromAnthropicContentBlock);
|
|
412
|
+
const finalResponse = {
|
|
413
|
+
id: finalMessage.id,
|
|
414
|
+
content,
|
|
415
|
+
model: finalMessage.model,
|
|
416
|
+
stop_reason: finalMessage.stop_reason ?? 'end_turn',
|
|
417
|
+
usage: {
|
|
418
|
+
input_tokens: finalMessage.usage.input_tokens,
|
|
419
|
+
output_tokens: finalMessage.usage.output_tokens,
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
const doneEvent = { type: 'done', data: finalResponse };
|
|
423
|
+
yield doneEvent;
|
|
424
|
+
}
|
|
425
|
+
catch (err) {
|
|
426
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
427
|
+
const errorEvent = { type: 'error', data: error };
|
|
428
|
+
yield errorEvent;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
//# sourceMappingURL=anthropic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/llm/anthropic.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Azure OpenAI adapter implementing {@link LLMAdapter}.
|
|
3
|
+
*
|
|
4
|
+
* Azure OpenAI uses regional deployment endpoints and API versioning that differ
|
|
5
|
+
* from standard OpenAI:
|
|
6
|
+
*
|
|
7
|
+
* - Endpoint: `https://{resource-name}.openai.azure.com`
|
|
8
|
+
* - API version: Query parameter (e.g., `?api-version=2024-10-21`)
|
|
9
|
+
* - Model/Deployment: Users deploy models with custom names; the `model` field
|
|
10
|
+
* in agent config should contain the Azure deployment name, not the underlying
|
|
11
|
+
* model name (e.g., `model: 'my-gpt4-deployment'`)
|
|
12
|
+
*
|
|
13
|
+
* The OpenAI SDK provides an `AzureOpenAI` client class that handles these
|
|
14
|
+
* Azure-specific requirements. This adapter uses that client while reusing all
|
|
15
|
+
* message conversion logic from `openai-common.ts`.
|
|
16
|
+
*
|
|
17
|
+
* Environment variable resolution order:
|
|
18
|
+
* 1. Constructor arguments
|
|
19
|
+
* 2. `AZURE_OPENAI_API_KEY` environment variable
|
|
20
|
+
* 3. `AZURE_OPENAI_ENDPOINT` environment variable
|
|
21
|
+
* 4. `AZURE_OPENAI_API_VERSION` environment variable (defaults to '2024-10-21')
|
|
22
|
+
* 5. `AZURE_OPENAI_DEPLOYMENT` as an optional fallback when `model` is blank
|
|
23
|
+
*
|
|
24
|
+
* Note: Azure introduced a next-generation v1 API (August 2025) that uses the standard
|
|
25
|
+
* OpenAI() client with baseURL set to `{endpoint}/openai/v1/` and requires no api-version.
|
|
26
|
+
* That path is not yet supported by this adapter. To use it, pass `provider: 'openai'`
|
|
27
|
+
* with `baseURL: 'https://{resource}.openai.azure.com/openai/v1/'` in your agent config.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { AzureOpenAIAdapter } from './azure-openai.js'
|
|
32
|
+
*
|
|
33
|
+
* const adapter = new AzureOpenAIAdapter()
|
|
34
|
+
* const response = await adapter.chat(messages, {
|
|
35
|
+
* model: 'my-gpt4-deployment', // Azure deployment name, not 'gpt-4'
|
|
36
|
+
* maxTokens: 1024,
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
import type { LLMAdapter, LLMChatOptions, LLMMessage, LLMResponse, LLMStreamOptions, StreamEvent } from '../types.js';
|
|
41
|
+
/**
|
|
42
|
+
* LLM adapter backed by Azure OpenAI Chat Completions API.
|
|
43
|
+
*
|
|
44
|
+
* Thread-safe — a single instance may be shared across concurrent agent runs.
|
|
45
|
+
*/
|
|
46
|
+
export declare class AzureOpenAIAdapter implements LLMAdapter {
|
|
47
|
+
#private;
|
|
48
|
+
readonly name: string;
|
|
49
|
+
/**
|
|
50
|
+
* @param apiKey - Azure OpenAI API key (falls back to AZURE_OPENAI_API_KEY env var)
|
|
51
|
+
* @param endpoint - Azure endpoint URL (falls back to AZURE_OPENAI_ENDPOINT env var)
|
|
52
|
+
* @param apiVersion - API version string (falls back to AZURE_OPENAI_API_VERSION, defaults to '2024-10-21')
|
|
53
|
+
*/
|
|
54
|
+
constructor(apiKey?: string, endpoint?: string, apiVersion?: string);
|
|
55
|
+
/**
|
|
56
|
+
* Send a synchronous (non-streaming) chat request and return the complete
|
|
57
|
+
* {@link LLMResponse}.
|
|
58
|
+
*
|
|
59
|
+
* Throws an `AzureOpenAI.APIError` on non-2xx responses. Callers should catch and
|
|
60
|
+
* handle these (e.g. rate limits, context length exceeded, deployment not found).
|
|
61
|
+
*/
|
|
62
|
+
chat(messages: LLMMessage[], options: LLMChatOptions): Promise<LLMResponse>;
|
|
63
|
+
/**
|
|
64
|
+
* Send a streaming chat request and yield {@link StreamEvent}s incrementally.
|
|
65
|
+
*
|
|
66
|
+
* Sequence guarantees match {@link OpenAIAdapter.stream}:
|
|
67
|
+
* - Zero or more `text` events
|
|
68
|
+
* - Zero or more `tool_use` events (emitted once per tool call, after
|
|
69
|
+
* arguments have been fully assembled)
|
|
70
|
+
* - Exactly one terminal event: `done` or `error`
|
|
71
|
+
*/
|
|
72
|
+
stream(messages: LLMMessage[], options: LLMStreamOptions): AsyncIterable<StreamEvent>;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=azure-openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure-openai.d.ts","sourceRoot":"","sources":["../../src/llm/azure-openai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAOH,OAAO,KAAK,EAEV,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,WAAW,EAGZ,MAAM,aAAa,CAAA;AA8BpB;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,UAAU;;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAiB;IAItC;;;;OAIG;gBACS,MAAM,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAYnE;;;;;;OAMG;IACG,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC;IAqCjF;;;;;;;;OAQG;IACI,MAAM,CACX,QAAQ,EAAE,UAAU,EAAE,EACtB,OAAO,EAAE,gBAAgB,GACxB,aAAa,CAAC,WAAW,CAAC;CAiK9B"}
|