@codeworksh/aikit 0.3.1 → 0.4.1-dev.20260530133305
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 +116 -152
- package/cli.d.mts +1 -0
- package/cli.mjs +308 -0
- package/cli.mjs.map +1 -0
- package/codex-DfYk740t.mjs +521 -0
- package/codex-DfYk740t.mjs.map +1 -0
- package/index.d.mts +7145 -19
- package/index.mjs +1217 -3120
- package/index.mjs.map +1 -1
- package/oauth/openai/codex.d.mts +107 -0
- package/oauth/openai/codex.mjs +2 -0
- package/package.json +23 -21
- package/registry-CYfzJ6lk.mjs +5136 -0
- package/registry-CYfzJ6lk.mjs.map +1 -0
- package/agent/codemode/drivers/drivers.d.mts +0 -7
- package/agent/codemode/drivers/drivers.mjs +0 -122
- package/agent/codemode/drivers/drivers.mjs.map +0 -1
- package/codemode-SiETGR3z.d.mts +0 -8410
package/index.mjs
CHANGED
|
@@ -1,391 +1,498 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Type,
|
|
3
|
-
import { capitalize, keys, mapValues, pick, pipe } from "remeda";
|
|
4
|
-
import Ajv from "ajv";
|
|
5
|
-
import addFormats from "ajv-formats";
|
|
1
|
+
import { d as NamedError, i as packageForModel, o as resolveLanguageModel, r as loadProviderFactory, s as Model } from "./registry-CYfzJ6lk.mjs";
|
|
2
|
+
import Type$1, { Type, Type as Type$2 } from "typebox";
|
|
6
3
|
import { uuidv7 } from "uuidv7";
|
|
7
|
-
import
|
|
4
|
+
import Value from "typebox/value";
|
|
5
|
+
import { jsonSchema, streamText } from "ai";
|
|
8
6
|
import { parse } from "partial-json";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
githubCopilot: "github-copilot",
|
|
18
|
-
openrouter: "openrouter",
|
|
19
|
-
groq: "groq",
|
|
20
|
-
xai: "xai",
|
|
21
|
-
cerebras: "cerebras",
|
|
22
|
-
zai: "zai",
|
|
23
|
-
opencode: "opencode"
|
|
24
|
-
};
|
|
25
|
-
const KnownProviderSchema = _Provider.KnownProviderSchema = Type.Union([
|
|
26
|
-
Type.Literal(KnownProviderEnum.anthropic),
|
|
27
|
-
Type.Literal(KnownProviderEnum.openai),
|
|
28
|
-
Type.Literal(KnownProviderEnum.githubCopilot),
|
|
29
|
-
Type.Literal(KnownProviderEnum.openrouter),
|
|
30
|
-
Type.Literal(KnownProviderEnum.groq),
|
|
31
|
-
Type.Literal(KnownProviderEnum.xai),
|
|
32
|
-
Type.Literal(KnownProviderEnum.cerebras),
|
|
33
|
-
Type.Literal(KnownProviderEnum.zai),
|
|
34
|
-
Type.Literal(KnownProviderEnum.opencode)
|
|
35
|
-
]);
|
|
36
|
-
_Provider.Info = Type.Object({
|
|
37
|
-
id: KnownProviderSchema,
|
|
38
|
-
name: Type.String(),
|
|
39
|
-
env: Type.Array(Type.String()),
|
|
40
|
-
key: Type.Optional(Type.String()),
|
|
41
|
-
options: Type.Optional(Type.Record(Type.String(), Type.Any()))
|
|
7
|
+
import Schema from "typebox/schema";
|
|
8
|
+
//#region src/message/message.ts
|
|
9
|
+
let Message;
|
|
10
|
+
(function(_Message) {
|
|
11
|
+
const TextContentSchema = _Message.TextContentSchema = Type$1.Object({
|
|
12
|
+
type: Type$1.Literal("text"),
|
|
13
|
+
text: Type$1.String(),
|
|
14
|
+
textSignature: Type$1.Optional(Type$1.String())
|
|
42
15
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
high: Type.Optional(Type.String()),
|
|
48
|
-
xhigh: Type.Optional(Type.String())
|
|
16
|
+
const ImageContentSchema = _Message.ImageContentSchema = Type$1.Object({
|
|
17
|
+
type: Type$1.Literal("image"),
|
|
18
|
+
data: Type$1.String(),
|
|
19
|
+
mimeType: Type$1.String()
|
|
49
20
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
21
|
+
const ThinkingContentSchema = _Message.ThinkingContentSchema = Type$1.Object({
|
|
22
|
+
type: Type$1.Literal("thinking"),
|
|
23
|
+
thinking: Type$1.String(),
|
|
24
|
+
thinkingSignature: Type$1.Optional(Type$1.String()),
|
|
25
|
+
redacted: Type$1.Optional(Type$1.Boolean())
|
|
53
26
|
});
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
27
|
+
const ToolCallBaseSchema = _Message.ToolCallBaseSchema = Type$1.Object({
|
|
28
|
+
type: Type$1.Literal("toolCall"),
|
|
29
|
+
callID: Type$1.String(),
|
|
30
|
+
name: Type$1.String(),
|
|
31
|
+
arguments: Type$1.Record(Type$1.String(), Type$1.Any()),
|
|
32
|
+
thoughtSignature: Type$1.Optional(Type$1.String()),
|
|
33
|
+
time: Type$1.Object({
|
|
34
|
+
start: Type$1.Number(),
|
|
35
|
+
end: Type$1.Number()
|
|
36
|
+
})
|
|
57
37
|
});
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
(function(_ModelCatalog) {
|
|
63
|
-
function modelsDevURL() {
|
|
64
|
-
return process.env.OPENCODE_MODELS_URL || "https://models.dev";
|
|
65
|
-
}
|
|
66
|
-
function modelsDevPath() {
|
|
67
|
-
return process.env.CODEWORK_AIKIT_MODELS_PATH;
|
|
68
|
-
}
|
|
69
|
-
const modelsDevData = _ModelCatalog.modelsDevData = lazy(async () => {
|
|
70
|
-
const path = modelsDevPath();
|
|
71
|
-
if (path) {
|
|
72
|
-
const result = await Filesystem.readJson(path).catch(() => void 0);
|
|
73
|
-
if (result) return result;
|
|
74
|
-
}
|
|
75
|
-
const json = await fetch(`${modelsDevURL()}/api.json`).then((x) => x.text());
|
|
76
|
-
return JSON.parse(json);
|
|
38
|
+
const ToolSuccessResult = _Message.ToolSuccessResult = Type$1.Object({
|
|
39
|
+
content: Type$1.Array(Type$1.Union([TextContentSchema, ImageContentSchema])),
|
|
40
|
+
details: Type$1.Optional(Type$1.Any()),
|
|
41
|
+
isError: Type$1.Literal(false)
|
|
77
42
|
});
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}, 60 * 1e3 * 60).unref();
|
|
95
|
-
})(ModelCatalog || (ModelCatalog = {}));
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region src/model/transform.ts
|
|
98
|
-
function defaultBaseUrl(providerId) {
|
|
99
|
-
switch (providerId) {
|
|
100
|
-
case Provider.KnownProviderEnum.openai: return "https://api.openai.com/v1";
|
|
101
|
-
default: return;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
function resolveDefaultProtocol(providerId) {
|
|
105
|
-
switch (providerId) {
|
|
106
|
-
case Provider.KnownProviderEnum.anthropic: return Model.KnownProtocolEnum.anthropicMessages;
|
|
107
|
-
case Provider.KnownProviderEnum.openai: return Model.KnownProtocolEnum.openaiResponses;
|
|
108
|
-
default: return Model.KnownProtocolEnum.openaiCompletions;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function applyModification(providerId, provider, model) {
|
|
112
|
-
const baseUrl = model.baseUrl ?? provider.baseUrl ?? provider.api ?? defaultBaseUrl(providerId);
|
|
113
|
-
const normalized = {
|
|
114
|
-
id: model.id,
|
|
115
|
-
name: model.name,
|
|
116
|
-
provider: Model.toProviderInfo(providerId, provider),
|
|
117
|
-
baseUrl,
|
|
118
|
-
reasoning: Boolean(model.reasoning),
|
|
119
|
-
input: Model.normalizeInput(model.modalities.input),
|
|
120
|
-
cost: {
|
|
121
|
-
input: model.cost?.input ?? 0,
|
|
122
|
-
output: model.cost?.output ?? 0,
|
|
123
|
-
cacheRead: model.cost?.cache_read ?? 0,
|
|
124
|
-
cacheWrite: model.cost?.cache_write ?? 0
|
|
125
|
-
},
|
|
126
|
-
contextWindow: model.limit?.context ?? 0,
|
|
127
|
-
maxTokens: model.limit?.output ?? 0,
|
|
128
|
-
headers: model.headers ?? provider.headers,
|
|
129
|
-
protocol: resolveDefaultProtocol(providerId)
|
|
130
|
-
};
|
|
131
|
-
if (providerId === Provider.KnownProviderEnum.openai) {
|
|
132
|
-
normalized.supportedProtocols = { openaiCompletions: Model.KnownProtocolEnum.openaiCompletions };
|
|
133
|
-
return normalized;
|
|
134
|
-
} else return normalized;
|
|
135
|
-
}
|
|
136
|
-
//#endregion
|
|
137
|
-
//#region src/model/model.ts
|
|
138
|
-
let Model;
|
|
139
|
-
(function(_Model) {
|
|
140
|
-
const KnownProtocolEnum = _Model.KnownProtocolEnum = {
|
|
141
|
-
anthropicMessages: "anthropic-messages",
|
|
142
|
-
openaiCompletions: "openai-completions",
|
|
143
|
-
openaiResponses: "openai-responses"
|
|
43
|
+
const ToolErrorResult = _Message.ToolErrorResult = Type$1.Object({
|
|
44
|
+
content: Type$1.Array(Type$1.Union([TextContentSchema, ImageContentSchema])),
|
|
45
|
+
details: Type$1.Optional(Type$1.Any()),
|
|
46
|
+
isError: Type$1.Literal(true)
|
|
47
|
+
});
|
|
48
|
+
const ToolRunningPartial = _Message.ToolRunningPartial = Type$1.Object({
|
|
49
|
+
content: Type$1.Optional(Type$1.Array(Type$1.Union([TextContentSchema, ImageContentSchema]))),
|
|
50
|
+
details: Type$1.Optional(Type$1.Any())
|
|
51
|
+
});
|
|
52
|
+
const ToolStatusEnum = _Message.ToolStatusEnum = {
|
|
53
|
+
pending: "pending",
|
|
54
|
+
running: "running",
|
|
55
|
+
completed: "completed",
|
|
56
|
+
error: "error",
|
|
57
|
+
skipped: "skipped",
|
|
58
|
+
aborted: "aborted"
|
|
144
59
|
};
|
|
145
|
-
|
|
146
|
-
Type.Literal(
|
|
147
|
-
Type.
|
|
148
|
-
Type.Literal(KnownProtocolEnum.openaiResponses)
|
|
149
|
-
]);
|
|
150
|
-
const InputSchema = Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]));
|
|
151
|
-
const CostSchema = Type.Object({
|
|
152
|
-
input: Type.Number(),
|
|
153
|
-
output: Type.Number(),
|
|
154
|
-
cacheRead: Type.Number(),
|
|
155
|
-
cacheWrite: Type.Number()
|
|
60
|
+
const ToolRunningSchema = _Message.ToolRunningSchema = Type$1.Object({
|
|
61
|
+
status: Type$1.Literal(ToolStatusEnum.running),
|
|
62
|
+
partial: Type$1.Optional(ToolRunningPartial)
|
|
156
63
|
});
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
openaiCompletions: Type.Optional(Type.Literal(KnownProtocolEnum.openaiCompletions)),
|
|
161
|
-
openaiResponses: Type.Optional(Type.Literal(KnownProtocolEnum.openaiResponses))
|
|
64
|
+
const ToolCompletedSchema = _Message.ToolCompletedSchema = Type$1.Object({
|
|
65
|
+
status: Type$1.Literal(ToolStatusEnum.completed),
|
|
66
|
+
result: ToolSuccessResult
|
|
162
67
|
});
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
provider: Provider.Info,
|
|
167
|
-
baseUrl: Type.String(),
|
|
168
|
-
reasoning: Type.Boolean(),
|
|
169
|
-
input: InputSchema,
|
|
170
|
-
cost: CostSchema,
|
|
171
|
-
contextWindow: Type.Number(),
|
|
172
|
-
maxTokens: Type.Number(),
|
|
173
|
-
headers: HeadersSchema,
|
|
174
|
-
supportedProtocols: Type.Optional(Type.Partial(SupportedProtocolsSchema))
|
|
68
|
+
const ToolErrorSchema = _Message.ToolErrorSchema = Type$1.Object({
|
|
69
|
+
status: Type$1.Literal(ToolStatusEnum.error),
|
|
70
|
+
result: ToolErrorResult
|
|
175
71
|
});
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
180
|
-
reasoningEffortMap: Type.Optional(Provider.ReasoningEffortMapSchema),
|
|
181
|
-
supportsUsageInStreaming: Type.Optional(Type.Boolean()),
|
|
182
|
-
maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
|
|
183
|
-
requiresToolResultName: Type.Optional(Type.Boolean()),
|
|
184
|
-
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
|
185
|
-
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
|
186
|
-
thinkingFormat: Type.Optional(Type.Union([
|
|
187
|
-
Type.Literal("openai"),
|
|
188
|
-
Type.Literal("openrouter"),
|
|
189
|
-
Type.Literal("zai"),
|
|
190
|
-
Type.Literal("qwen"),
|
|
191
|
-
Type.Literal("qwen-chat-template")
|
|
192
|
-
])),
|
|
193
|
-
openRouterRouting: Type.Optional(Provider.OpenRouterRoutingSchema),
|
|
194
|
-
vercelGatewayRouting: Type.Optional(Provider.VercelGatewayRoutingSchema),
|
|
195
|
-
zaiToolStream: Type.Optional(Type.Boolean()),
|
|
196
|
-
supportsStrictMode: Type.Optional(Type.Boolean())
|
|
72
|
+
const ToolSkippedSchema = _Message.ToolSkippedSchema = Type$1.Object({
|
|
73
|
+
status: Type$1.Literal(ToolStatusEnum.skipped),
|
|
74
|
+
result: ToolErrorResult
|
|
197
75
|
});
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
76
|
+
const ToolAbortedSchema = _Message.ToolAbortedSchema = Type$1.Object({
|
|
77
|
+
status: Type$1.Literal(ToolStatusEnum.aborted),
|
|
78
|
+
result: ToolErrorResult
|
|
79
|
+
});
|
|
80
|
+
const ToolCallPendingPart = Type$1.Intersect([ToolCallBaseSchema, Type$1.Object({ status: Type$1.Literal(ToolStatusEnum.pending) })]);
|
|
81
|
+
const ToolCallRunningPart = Type$1.Evaluate(Type$1.Intersect([ToolCallBaseSchema, ToolRunningSchema]));
|
|
82
|
+
const ToolCallCompletedPart = Type$1.Evaluate(Type$1.Intersect([ToolCallBaseSchema, ToolCompletedSchema]));
|
|
83
|
+
const ToolCallErrorPart = Type$1.Evaluate(Type$1.Intersect([ToolCallBaseSchema, ToolErrorSchema]));
|
|
84
|
+
const ToolCallSkippedPart = Type$1.Evaluate(Type$1.Intersect([ToolCallBaseSchema, ToolSkippedSchema]));
|
|
85
|
+
const ToolCallAbortedPart = Type$1.Evaluate(Type$1.Intersect([ToolCallBaseSchema, ToolAbortedSchema]));
|
|
86
|
+
_Message.ToolCallInFlightSchema = Type$1.Object({
|
|
87
|
+
callID: Type$1.String(),
|
|
88
|
+
name: Type$1.String(),
|
|
89
|
+
rawArgs: Type$1.Record(Type$1.String(), Type$1.Unknown()),
|
|
90
|
+
args: Type$1.Optional(Type$1.Unknown())
|
|
91
|
+
});
|
|
92
|
+
const ToolCallSchema = _Message.ToolCallSchema = Type$1.Union([
|
|
93
|
+
ToolCallPendingPart,
|
|
94
|
+
ToolCallRunningPart,
|
|
95
|
+
ToolCallCompletedPart,
|
|
96
|
+
ToolCallErrorPart,
|
|
97
|
+
ToolCallSkippedPart,
|
|
98
|
+
ToolCallAbortedPart
|
|
213
99
|
]);
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
100
|
+
const UsageSchema = _Message.UsageSchema = Type$1.Object({
|
|
101
|
+
input: Type$1.Number(),
|
|
102
|
+
output: Type$1.Number(),
|
|
103
|
+
cacheRead: Type$1.Number(),
|
|
104
|
+
cacheWrite: Type$1.Number(),
|
|
105
|
+
totalTokens: Type$1.Number(),
|
|
106
|
+
cost: Type$1.Object({
|
|
107
|
+
input: Type$1.Number(),
|
|
108
|
+
output: Type$1.Number(),
|
|
109
|
+
cacheRead: Type$1.Number(),
|
|
110
|
+
cacheWrite: Type$1.Number(),
|
|
111
|
+
total: Type$1.Number()
|
|
112
|
+
})
|
|
113
|
+
});
|
|
114
|
+
const StopReasonSchema = _Message.StopReasonSchema = Type$1.Union([
|
|
115
|
+
Type$1.Literal("stop"),
|
|
116
|
+
Type$1.Literal("length"),
|
|
117
|
+
Type$1.Literal("toolUse"),
|
|
118
|
+
Type$1.Literal("error"),
|
|
119
|
+
Type$1.Literal("aborted")
|
|
120
|
+
]);
|
|
121
|
+
const UserMessageSchema = _Message.UserMessageSchema = Type$1.Object({
|
|
122
|
+
messageId: Type$1.String(),
|
|
123
|
+
role: Type$1.Literal("user"),
|
|
124
|
+
time: Type$1.Object({ created: Type$1.Number() }),
|
|
125
|
+
parts: Type$1.Array(Type$1.Union([TextContentSchema, ImageContentSchema]))
|
|
126
|
+
});
|
|
127
|
+
const AssistantMessageSchema = _Message.AssistantMessageSchema = Type$1.Object({
|
|
128
|
+
role: Type$1.Literal("assistant"),
|
|
129
|
+
protocol: Model.KnownProviderEnumSchema,
|
|
130
|
+
provider: Model.ProviderInfo,
|
|
131
|
+
model: Type$1.String(),
|
|
132
|
+
usage: UsageSchema,
|
|
133
|
+
stopReason: StopReasonSchema,
|
|
134
|
+
errorMessage: Type$1.Optional(Type$1.String()),
|
|
135
|
+
time: Type$1.Object({
|
|
136
|
+
created: Type$1.Number(),
|
|
137
|
+
completed: Type$1.Number()
|
|
138
|
+
}),
|
|
139
|
+
parts: Type$1.Array(Type$1.Union([
|
|
140
|
+
TextContentSchema,
|
|
141
|
+
ImageContentSchema,
|
|
142
|
+
ThinkingContentSchema,
|
|
143
|
+
ToolCallSchema
|
|
144
|
+
])),
|
|
145
|
+
responseId: Type$1.Optional(Type$1.String()),
|
|
146
|
+
responseModel: Type$1.Optional(Type$1.String()),
|
|
147
|
+
messageId: Type$1.String()
|
|
148
|
+
});
|
|
149
|
+
const MessageSchema = _Message.MessageSchema = Type$1.Union([UserMessageSchema, AssistantMessageSchema]);
|
|
150
|
+
function createMessageId() {
|
|
151
|
+
return uuidv7();
|
|
228
152
|
}
|
|
229
|
-
|
|
230
|
-
function
|
|
153
|
+
_Message.createMessageId = createMessageId;
|
|
154
|
+
function createUserMessage(message) {
|
|
155
|
+
const { messageId = createMessageId(), ...rest } = message;
|
|
231
156
|
return {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
env: provider.env,
|
|
235
|
-
key: provider.key,
|
|
236
|
-
options: provider.headers
|
|
157
|
+
messageId,
|
|
158
|
+
...rest
|
|
237
159
|
};
|
|
238
160
|
}
|
|
239
|
-
|
|
240
|
-
function
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
_Model.getBuiltInModels = getBuiltInModels;
|
|
247
|
-
const registry = _Model.registry = lazy(async () => {
|
|
248
|
-
const registry = /* @__PURE__ */ new Map();
|
|
249
|
-
const models = await getBuiltInModels();
|
|
250
|
-
for (const [provider, value] of Object.entries(models)) {
|
|
251
|
-
const providerModels = /* @__PURE__ */ new Map();
|
|
252
|
-
for (const [id, model] of Object.entries(value)) providerModels.set(id, model);
|
|
253
|
-
registry.set(provider, providerModels);
|
|
254
|
-
}
|
|
255
|
-
return registry;
|
|
256
|
-
});
|
|
257
|
-
async function getModel(provider, model, overrides) {
|
|
258
|
-
const result = (await registry()).get(provider)?.get(model);
|
|
259
|
-
if (result && overrides) return {
|
|
260
|
-
...result,
|
|
261
|
-
...overrides
|
|
161
|
+
_Message.createUserMessage = createUserMessage;
|
|
162
|
+
function createAssistantMessage(message) {
|
|
163
|
+
const { messageId = createMessageId(), ...rest } = message;
|
|
164
|
+
return {
|
|
165
|
+
messageId,
|
|
166
|
+
...rest
|
|
262
167
|
};
|
|
263
|
-
return result;
|
|
264
|
-
}
|
|
265
|
-
_Model.getModel = getModel;
|
|
266
|
-
async function getProviders() {
|
|
267
|
-
const data = await registry();
|
|
268
|
-
return Array.from(data.keys());
|
|
269
168
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
169
|
+
_Message.createAssistantMessage = createAssistantMessage;
|
|
170
|
+
const ToolSchema = _Message.ToolSchema = Type$1.Object({
|
|
171
|
+
name: Type$1.String(),
|
|
172
|
+
description: Type$1.String(),
|
|
173
|
+
parameters: Type$1.Unsafe({})
|
|
174
|
+
});
|
|
175
|
+
function defineTool(tool) {
|
|
176
|
+
return tool;
|
|
274
177
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
178
|
+
_Message.defineTool = defineTool;
|
|
179
|
+
_Message.ContextSchema = Type$1.Object({
|
|
180
|
+
systemPrompt: Type$1.Optional(Type$1.String()),
|
|
181
|
+
messages: Type$1.Array(MessageSchema),
|
|
182
|
+
tools: Type$1.Optional(Type$1.Array(ToolSchema))
|
|
183
|
+
});
|
|
184
|
+
function isUnresolvedToolCall(toolCall) {
|
|
185
|
+
return toolCall.status === ToolStatusEnum.pending || toolCall.status === ToolStatusEnum.running;
|
|
280
186
|
}
|
|
281
|
-
function
|
|
282
|
-
|
|
187
|
+
function syntheticSkippedToolCall(toolCall) {
|
|
188
|
+
const { status: _status, partial: _partial, ...base } = toolCall;
|
|
189
|
+
return {
|
|
190
|
+
...base,
|
|
191
|
+
status: ToolStatusEnum.skipped,
|
|
192
|
+
result: {
|
|
193
|
+
content: [{
|
|
194
|
+
type: "text",
|
|
195
|
+
text: "No result provided"
|
|
196
|
+
}],
|
|
197
|
+
isError: true
|
|
198
|
+
},
|
|
199
|
+
time: {
|
|
200
|
+
...toolCall.time,
|
|
201
|
+
end: Math.max(toolCall.time.end, Date.now())
|
|
202
|
+
}
|
|
203
|
+
};
|
|
283
204
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
205
|
+
function transformMessages(messages, model, normalizeToolCallId) {
|
|
206
|
+
const toolCallIDMap = /* @__PURE__ */ new Map();
|
|
207
|
+
const transformed = [];
|
|
208
|
+
for (const msg of messages) {
|
|
209
|
+
if (msg.role === "user") {
|
|
210
|
+
transformed.push(msg);
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const assistantMsg = msg;
|
|
214
|
+
const isSameModel = assistantMsg.provider.id === model.provider.id && assistantMsg.protocol === model.protocol && assistantMsg.model === model.id;
|
|
215
|
+
const parts = assistantMsg.parts.flatMap((block) => {
|
|
216
|
+
if (block.type === "thinking") {
|
|
217
|
+
if (isSameModel && block.thinkingSignature) return block;
|
|
218
|
+
if (!block.thinking || block.thinking.trim() === "") return [];
|
|
219
|
+
if (isSameModel) return block;
|
|
220
|
+
return {
|
|
221
|
+
type: "text",
|
|
222
|
+
text: block.thinking
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (block.type === "text") {
|
|
226
|
+
if (isSameModel) return block;
|
|
227
|
+
return {
|
|
228
|
+
type: "text",
|
|
229
|
+
text: block.text
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
if (block.type === "toolCall") {
|
|
233
|
+
const toolCall = block;
|
|
234
|
+
let normalizedToolCall = toolCall;
|
|
235
|
+
if (!isSameModel && toolCall.thoughtSignature) {
|
|
236
|
+
normalizedToolCall = { ...toolCall };
|
|
237
|
+
delete normalizedToolCall.thoughtSignature;
|
|
238
|
+
}
|
|
239
|
+
const normalizedID = toolCallIDMap.get(block.callID);
|
|
240
|
+
if (normalizedID && normalizedID !== block.callID) normalizedToolCall = {
|
|
241
|
+
...normalizedToolCall,
|
|
242
|
+
callID: normalizedID
|
|
243
|
+
};
|
|
244
|
+
else if (!isSameModel && normalizeToolCallId) {
|
|
245
|
+
const nextID = normalizeToolCallId(toolCall.callID, model, assistantMsg);
|
|
246
|
+
if (nextID !== toolCall.callID) {
|
|
247
|
+
toolCallIDMap.set(toolCall.callID, nextID);
|
|
248
|
+
normalizedToolCall = {
|
|
249
|
+
...normalizedToolCall,
|
|
250
|
+
callID: nextID
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return normalizedToolCall;
|
|
255
|
+
}
|
|
256
|
+
return block;
|
|
257
|
+
}).map((block) => {
|
|
258
|
+
if (block.type === "toolCall" && isUnresolvedToolCall(block)) return syntheticSkippedToolCall(block);
|
|
259
|
+
return block;
|
|
260
|
+
});
|
|
261
|
+
transformed.push({
|
|
262
|
+
...assistantMsg,
|
|
263
|
+
parts
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return transformed;
|
|
288
267
|
}
|
|
289
|
-
|
|
290
|
-
})(
|
|
268
|
+
_Message.transformMessages = transformMessages;
|
|
269
|
+
})(Message || (Message = {}));
|
|
291
270
|
//#endregion
|
|
292
|
-
//#region src/
|
|
293
|
-
let
|
|
294
|
-
(function(
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
271
|
+
//#region src/event/event.ts
|
|
272
|
+
let Event;
|
|
273
|
+
(function(_Event) {
|
|
274
|
+
const LLMMessageEventType = _Event.LLMMessageEventType = {
|
|
275
|
+
start: "start",
|
|
276
|
+
textStart: "text.start",
|
|
277
|
+
textDelta: "text.delta",
|
|
278
|
+
textEnd: "text.end",
|
|
279
|
+
thinkingStart: "thinking.start",
|
|
280
|
+
thinkingDelta: "thinking.delta",
|
|
281
|
+
thinkingEnd: "thinking.end",
|
|
282
|
+
toolcallStart: "toolcall.start",
|
|
283
|
+
toolcallDelta: "toolcall.delta",
|
|
284
|
+
toolcallEnd: "toolcall.end",
|
|
285
|
+
toolcallFinal: "toolcall.final",
|
|
286
|
+
done: "done",
|
|
287
|
+
error: "error"
|
|
307
288
|
};
|
|
308
|
-
|
|
309
|
-
Type.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
Type.
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
Type.
|
|
325
|
-
|
|
326
|
-
|
|
289
|
+
_Event.LLMMessageEventSchema = Type$1.Union([
|
|
290
|
+
Type$1.Object({
|
|
291
|
+
type: Type$1.Literal(LLMMessageEventType.start),
|
|
292
|
+
partial: Message.AssistantMessageSchema
|
|
293
|
+
}),
|
|
294
|
+
Type$1.Object({
|
|
295
|
+
type: Type$1.Literal(LLMMessageEventType.textStart),
|
|
296
|
+
partIndex: Type$1.Number(),
|
|
297
|
+
partial: Message.AssistantMessageSchema
|
|
298
|
+
}),
|
|
299
|
+
Type$1.Object({
|
|
300
|
+
type: Type$1.Literal(LLMMessageEventType.textDelta),
|
|
301
|
+
partIndex: Type$1.Number(),
|
|
302
|
+
delta: Type$1.String(),
|
|
303
|
+
partial: Message.AssistantMessageSchema
|
|
304
|
+
}),
|
|
305
|
+
Type$1.Object({
|
|
306
|
+
type: Type$1.Literal(LLMMessageEventType.textEnd),
|
|
307
|
+
partIndex: Type$1.Number(),
|
|
308
|
+
content: Type$1.String(),
|
|
309
|
+
partial: Message.AssistantMessageSchema
|
|
310
|
+
}),
|
|
311
|
+
Type$1.Object({
|
|
312
|
+
type: Type$1.Literal(LLMMessageEventType.thinkingStart),
|
|
313
|
+
partIndex: Type$1.Number(),
|
|
314
|
+
partial: Message.AssistantMessageSchema
|
|
315
|
+
}),
|
|
316
|
+
Type$1.Object({
|
|
317
|
+
type: Type$1.Literal(LLMMessageEventType.thinkingDelta),
|
|
318
|
+
partIndex: Type$1.Number(),
|
|
319
|
+
delta: Type$1.String(),
|
|
320
|
+
partial: Message.AssistantMessageSchema
|
|
321
|
+
}),
|
|
322
|
+
Type$1.Object({
|
|
323
|
+
type: Type$1.Literal(LLMMessageEventType.thinkingEnd),
|
|
324
|
+
partIndex: Type$1.Number(),
|
|
325
|
+
content: Type$1.String(),
|
|
326
|
+
partial: Message.AssistantMessageSchema
|
|
327
|
+
}),
|
|
328
|
+
Type$1.Object({
|
|
329
|
+
type: Type$1.Literal(LLMMessageEventType.toolcallStart),
|
|
330
|
+
partIndex: Type$1.Number(),
|
|
331
|
+
partial: Message.AssistantMessageSchema
|
|
332
|
+
}),
|
|
333
|
+
Type$1.Object({
|
|
334
|
+
type: Type$1.Literal(LLMMessageEventType.toolcallDelta),
|
|
335
|
+
partIndex: Type$1.Number(),
|
|
336
|
+
delta: Type$1.String(),
|
|
337
|
+
partial: Message.AssistantMessageSchema
|
|
338
|
+
}),
|
|
339
|
+
Type$1.Object({
|
|
340
|
+
type: Type$1.Literal(LLMMessageEventType.toolcallEnd),
|
|
341
|
+
partIndex: Type$1.Number(),
|
|
342
|
+
toolCall: Message.ToolCallSchema,
|
|
343
|
+
partial: Message.AssistantMessageSchema
|
|
344
|
+
}),
|
|
345
|
+
Type$1.Object({
|
|
346
|
+
type: Type$1.Literal(LLMMessageEventType.toolcallFinal),
|
|
347
|
+
partIndex: Type$1.Number(),
|
|
348
|
+
toolCall: Message.ToolCallSchema,
|
|
349
|
+
partial: Message.AssistantMessageSchema
|
|
350
|
+
}),
|
|
351
|
+
Type$1.Object({
|
|
352
|
+
type: Type$1.Literal(LLMMessageEventType.done),
|
|
353
|
+
reason: Type$1.Union([
|
|
354
|
+
Type$1.Literal("stop"),
|
|
355
|
+
Type$1.Literal("length"),
|
|
356
|
+
Type$1.Literal("toolUse")
|
|
357
|
+
]),
|
|
358
|
+
message: Message.AssistantMessageSchema
|
|
359
|
+
}),
|
|
360
|
+
Type$1.Object({
|
|
361
|
+
type: Type$1.Literal(LLMMessageEventType.error),
|
|
362
|
+
reason: Type$1.Union([Type$1.Literal("aborted"), Type$1.Literal("error")]),
|
|
363
|
+
error: Message.AssistantMessageSchema
|
|
364
|
+
})
|
|
327
365
|
]);
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
366
|
+
const AgentEventType = _Event.AgentEventType = {
|
|
367
|
+
agentStart: "agent.start",
|
|
368
|
+
agentEnd: "agent.end",
|
|
369
|
+
turnStart: "turn.start",
|
|
370
|
+
turnEnd: "turn.end",
|
|
371
|
+
messageStart: "message.start",
|
|
372
|
+
messagePartStart: "message.part.start",
|
|
373
|
+
messagePartUpdate: "message.part.update",
|
|
374
|
+
messagePartEnd: "message.part.end",
|
|
375
|
+
messageUpdate: "message.update",
|
|
376
|
+
messageEnd: "message.end",
|
|
377
|
+
toolExecutionStart: "tool.execution.start",
|
|
378
|
+
toolExecutionUpdate: "tool.execution.update",
|
|
379
|
+
toolExecutionEnd: "tool.execution.end"
|
|
380
|
+
};
|
|
381
|
+
const UserMessagePart = Type$1.Union([Message.TextContentSchema, Message.ImageContentSchema]);
|
|
382
|
+
const AssistantMessagePart = Type$1.Union([
|
|
383
|
+
Message.TextContentSchema,
|
|
384
|
+
Message.ImageContentSchema,
|
|
385
|
+
Message.ThinkingContentSchema,
|
|
386
|
+
Message.ToolCallSchema
|
|
332
387
|
]);
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
transport: Type.Optional(TransportSchema),
|
|
339
|
-
cacheRetention: Type.Optional(CacheRetentionSchema),
|
|
340
|
-
sessionId: Type.Optional(Type.String()),
|
|
341
|
-
onPayload: Type.Optional(Type.Unsafe()),
|
|
342
|
-
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
343
|
-
maxRetryDelayMs: Type.Optional(Type.Number()),
|
|
344
|
-
metadata: Type.Optional(Type.Record(Type.String(), Type.Unknown()))
|
|
388
|
+
const UserMessagePartStart = Type$1.Object({
|
|
389
|
+
type: Type$1.Literal(AgentEventType.messagePartStart),
|
|
390
|
+
message: Message.UserMessageSchema,
|
|
391
|
+
partIndex: Type$1.Number(),
|
|
392
|
+
part: UserMessagePart
|
|
345
393
|
});
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
394
|
+
const UserMessagePartEnd = Type$1.Object({
|
|
395
|
+
type: Type$1.Literal(AgentEventType.messagePartEnd),
|
|
396
|
+
message: Message.UserMessageSchema,
|
|
397
|
+
partIndex: Type$1.Number(),
|
|
398
|
+
part: UserMessagePart
|
|
399
|
+
});
|
|
400
|
+
const AssistantMessagePartStart = Type$1.Object({
|
|
401
|
+
type: Type$1.Literal(AgentEventType.messagePartStart),
|
|
402
|
+
message: Message.AssistantMessageSchema,
|
|
403
|
+
partIndex: Type$1.Number(),
|
|
404
|
+
part: AssistantMessagePart
|
|
405
|
+
});
|
|
406
|
+
const AssistantMessagePartLLMUpdate = Type$1.Object({
|
|
407
|
+
type: Type$1.Literal(AgentEventType.messagePartUpdate),
|
|
408
|
+
message: Message.AssistantMessageSchema,
|
|
409
|
+
partIndex: Type$1.Number(),
|
|
410
|
+
part: AssistantMessagePart,
|
|
411
|
+
source: Type$1.Literal("llm")
|
|
412
|
+
});
|
|
413
|
+
const AssistantMessagePartToolUpdate = Type$1.Object({
|
|
414
|
+
type: Type$1.Literal(AgentEventType.messagePartUpdate),
|
|
415
|
+
message: Message.AssistantMessageSchema,
|
|
416
|
+
partIndex: Type$1.Number(),
|
|
417
|
+
part: AssistantMessagePart,
|
|
418
|
+
source: Type$1.Literal("tool")
|
|
419
|
+
});
|
|
420
|
+
const AssistantMessagePartEnd = Type$1.Object({
|
|
421
|
+
type: Type$1.Literal(AgentEventType.messagePartEnd),
|
|
422
|
+
message: Message.AssistantMessageSchema,
|
|
423
|
+
partIndex: Type$1.Number(),
|
|
424
|
+
part: AssistantMessagePart
|
|
425
|
+
});
|
|
426
|
+
const ToolExecutionStartSchema = Type$1.Evaluate(Type$1.Intersect([Message.ToolCallInFlightSchema, Type$1.Object({ type: Type$1.Literal(AgentEventType.toolExecutionStart) })]));
|
|
427
|
+
const ToolExecutionUpdateSchema = Type$1.Evaluate(Type$1.Intersect([
|
|
428
|
+
Message.ToolCallInFlightSchema,
|
|
429
|
+
Type$1.Object({ type: Type$1.Literal(AgentEventType.toolExecutionUpdate) }),
|
|
430
|
+
Message.ToolRunningSchema
|
|
431
|
+
]));
|
|
432
|
+
const ToolExecutionEndSchema = Type$1.Evaluate(Type$1.Intersect([
|
|
433
|
+
Message.ToolCallInFlightSchema,
|
|
434
|
+
Type$1.Object({ type: Type$1.Literal(AgentEventType.toolExecutionEnd) }),
|
|
435
|
+
Type$1.Union([Message.ToolCompletedSchema, Message.ToolErrorSchema])
|
|
436
|
+
]));
|
|
437
|
+
_Event.AgentEventSchema = Type$1.Union([
|
|
438
|
+
Type$1.Object({ type: Type$1.Literal(AgentEventType.agentStart) }),
|
|
439
|
+
Type$1.Object({
|
|
440
|
+
type: Type$1.Literal(AgentEventType.agentEnd),
|
|
441
|
+
messages: Type$1.Array(Message.MessageSchema)
|
|
442
|
+
}),
|
|
443
|
+
Type$1.Object({ type: Type$1.Literal(AgentEventType.turnStart) }),
|
|
444
|
+
Type$1.Object({
|
|
445
|
+
type: Type$1.Literal(AgentEventType.turnEnd),
|
|
446
|
+
message: Message.AssistantMessageSchema
|
|
447
|
+
}),
|
|
448
|
+
Type$1.Object({
|
|
449
|
+
type: Type$1.Literal(AgentEventType.messageStart),
|
|
450
|
+
message: Message.MessageSchema
|
|
451
|
+
}),
|
|
452
|
+
Type$1.Union([UserMessagePartStart, UserMessagePartEnd]),
|
|
453
|
+
Type$1.Union([
|
|
454
|
+
AssistantMessagePartStart,
|
|
455
|
+
AssistantMessagePartLLMUpdate,
|
|
456
|
+
AssistantMessagePartToolUpdate,
|
|
457
|
+
AssistantMessagePartEnd
|
|
458
|
+
]),
|
|
459
|
+
Type$1.Object({
|
|
460
|
+
type: Type$1.Literal(AgentEventType.messageUpdate),
|
|
461
|
+
message: Message.MessageSchema
|
|
462
|
+
}),
|
|
463
|
+
Type$1.Object({
|
|
464
|
+
type: Type$1.Literal(AgentEventType.messageEnd),
|
|
465
|
+
message: Message.MessageSchema
|
|
466
|
+
}),
|
|
467
|
+
ToolExecutionStartSchema,
|
|
468
|
+
ToolExecutionUpdateSchema,
|
|
469
|
+
ToolExecutionEndSchema
|
|
470
|
+
]);
|
|
471
|
+
})(Event || (Event = {}));
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/llm.ts
|
|
474
|
+
const llmImpl = async (provider, model, overrides) => Model.getModel(provider, model, overrides);
|
|
475
|
+
const llm = Object.assign(llmImpl, {
|
|
476
|
+
model: Model.getModel,
|
|
477
|
+
models: Model.getModels,
|
|
478
|
+
providers: Model.getProviders,
|
|
479
|
+
registry: Model.registry,
|
|
480
|
+
modelsAreEqual: Model.modelsAreEqual
|
|
481
|
+
});
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/llm/protocol.ts
|
|
484
|
+
let Protocol;
|
|
485
|
+
(function(_Protocol) {
|
|
486
|
+
const ProviderProtocolNotFoundError = _Protocol.ProviderProtocolNotFoundError = NamedError.create("ProviderProtocolNotFoundError", Type$1.Object({ protocol: Model.KnownProviderEnumSchema }));
|
|
487
|
+
const ProtocolMismatchError = _Protocol.ProtocolMismatchError = NamedError.create("ProtocolMismatchError", Type$1.Object({
|
|
488
|
+
actual: Model.KnownProviderEnumSchema,
|
|
489
|
+
expected: Model.KnownProviderEnumSchema
|
|
490
|
+
}));
|
|
491
|
+
_Protocol.ProtocolAuthError = NamedError.create("ProtocolAuthError", Type$1.Object({
|
|
492
|
+
message: Type$1.String(),
|
|
493
|
+
protocol: Type$1.String()
|
|
494
|
+
}));
|
|
495
|
+
const protocolRegistry = /* @__PURE__ */ new Map();
|
|
389
496
|
function wrapStream(protocol, stream) {
|
|
390
497
|
return (model, context, options) => {
|
|
391
498
|
if (model.protocol !== protocol) throw new ProtocolMismatchError({
|
|
@@ -395,65 +502,98 @@ let Stream;
|
|
|
395
502
|
return stream(model, context, options);
|
|
396
503
|
};
|
|
397
504
|
}
|
|
398
|
-
function wrapStreamSimple(protocol, streamSimple) {
|
|
399
|
-
return (model, context, options) => {
|
|
400
|
-
if (model.protocol !== protocol) throw new ProtocolMismatchError({
|
|
401
|
-
actual: model.protocol,
|
|
402
|
-
expected: protocol
|
|
403
|
-
});
|
|
404
|
-
return streamSimple(model, context, options);
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
505
|
function registerProtocolProvider(provider, sourceId) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
506
|
+
const registered = {
|
|
507
|
+
protocol: provider.protocol,
|
|
508
|
+
stream: wrapStream(provider.protocol, provider.stream)
|
|
509
|
+
};
|
|
510
|
+
protocolRegistry.set(provider.protocol, {
|
|
511
|
+
provider: registered,
|
|
414
512
|
sourceId
|
|
415
513
|
});
|
|
416
514
|
}
|
|
417
|
-
|
|
515
|
+
_Protocol.registerProtocolProvider = registerProtocolProvider;
|
|
418
516
|
function getProtocolProvider(protocol) {
|
|
419
|
-
return
|
|
517
|
+
return protocolRegistry.get(protocol)?.provider;
|
|
420
518
|
}
|
|
421
|
-
|
|
519
|
+
_Protocol.getProtocolProvider = getProtocolProvider;
|
|
422
520
|
function resolveProtocolProvider(model) {
|
|
423
521
|
const provider = getProtocolProvider(model.protocol);
|
|
424
|
-
if (!provider) throw new
|
|
522
|
+
if (!provider) throw new ProviderProtocolNotFoundError({ protocol: model.protocol });
|
|
425
523
|
return provider;
|
|
426
524
|
}
|
|
427
|
-
|
|
525
|
+
_Protocol.resolveProtocolProvider = resolveProtocolProvider;
|
|
526
|
+
function getProtocolProviders() {
|
|
527
|
+
return Array.from(protocolRegistry.values(), (entry) => entry.provider);
|
|
528
|
+
}
|
|
529
|
+
_Protocol.getProtocolProviders = getProtocolProviders;
|
|
428
530
|
function stream(model, context, options) {
|
|
429
531
|
return resolveProtocolProvider(model).stream(model, context, options);
|
|
430
532
|
}
|
|
431
|
-
|
|
533
|
+
_Protocol.stream = stream;
|
|
432
534
|
async function complete(model, context, options) {
|
|
433
535
|
return stream(model, context, options).result();
|
|
434
536
|
}
|
|
435
|
-
|
|
436
|
-
function streamSimple(model, context, options) {
|
|
437
|
-
return resolveProtocolProvider(model).streamSimple(model, context, options);
|
|
438
|
-
}
|
|
439
|
-
_Stream.streamSimple = streamSimple;
|
|
440
|
-
async function completeSimple(model, context, options) {
|
|
441
|
-
return streamSimple(model, context, options).result();
|
|
442
|
-
}
|
|
443
|
-
_Stream.completeSimple = completeSimple;
|
|
444
|
-
function getApiProviders() {
|
|
445
|
-
return Array.from(protocolProviderRegistry.values(), (entry) => entry.provider);
|
|
446
|
-
}
|
|
447
|
-
_Stream.getApiProviders = getApiProviders;
|
|
537
|
+
_Protocol.complete = complete;
|
|
448
538
|
function unregisterProtocolProviders(sourceId) {
|
|
449
|
-
for (const [
|
|
539
|
+
for (const [protocol, entry] of protocolRegistry.entries()) if (entry.sourceId === sourceId) protocolRegistry.delete(protocol);
|
|
450
540
|
}
|
|
451
|
-
|
|
541
|
+
_Protocol.unregisterProtocolProviders = unregisterProtocolProviders;
|
|
452
542
|
function clearProtocolProviders() {
|
|
453
|
-
|
|
543
|
+
protocolRegistry.clear();
|
|
454
544
|
}
|
|
455
|
-
|
|
456
|
-
})(
|
|
545
|
+
_Protocol.clearProtocolProviders = clearProtocolProviders;
|
|
546
|
+
})(Protocol || (Protocol = {}));
|
|
547
|
+
//#endregion
|
|
548
|
+
//#region src/llm/shared.ts
|
|
549
|
+
const CacheRetention = Type$2.Union([
|
|
550
|
+
Type$2.Literal("none"),
|
|
551
|
+
Type$2.Literal("short"),
|
|
552
|
+
Type$2.Literal("long")
|
|
553
|
+
]);
|
|
554
|
+
const GenerationOptions = Type$2.Object({
|
|
555
|
+
maxTokens: Type$2.Optional(Type$2.Number()),
|
|
556
|
+
temperature: Type$2.Optional(Type$2.Number()),
|
|
557
|
+
cacheRetention: Type$2.Optional(CacheRetention)
|
|
558
|
+
});
|
|
559
|
+
const HelperOptions = Type$2.Object({
|
|
560
|
+
headers: Type$2.Optional(Type$2.Record(Type$2.String(), Type$2.String())),
|
|
561
|
+
sessionId: Type$2.Optional(Type$2.String()),
|
|
562
|
+
apiKey: Type$2.Optional(Type$2.String()),
|
|
563
|
+
timeoutMs: Type$2.Optional(Type$2.Number()),
|
|
564
|
+
maxRetries: Type$2.Optional(Type$2.Number()),
|
|
565
|
+
signal: Type$2.Optional(Type$2.Unsafe({})),
|
|
566
|
+
onPayload: Type$2.Optional(Type$2.Unsafe({})),
|
|
567
|
+
metadata: Type$2.Optional(Type$2.Record(Type$2.String(), Type$2.Unknown()))
|
|
568
|
+
});
|
|
569
|
+
const ThinkingBudgets = Type$2.Object({
|
|
570
|
+
minimal: Type$2.Optional(Type$2.Number()),
|
|
571
|
+
low: Type$2.Optional(Type$2.Number()),
|
|
572
|
+
medium: Type$2.Optional(Type$2.Number()),
|
|
573
|
+
high: Type$2.Optional(Type$2.Number()),
|
|
574
|
+
xhigh: Type$2.Optional(Type$2.Number())
|
|
575
|
+
});
|
|
576
|
+
const SharedOptions = Type$2.Evaluate(Type$2.Intersect([GenerationOptions, HelperOptions]));
|
|
577
|
+
const DEFAULT_MAX_OUTPUT_TOKENS = 32e3;
|
|
578
|
+
const CONTEXT_WINDOW_OUTPUT_TOLERANCE = 1024;
|
|
579
|
+
function applyDefaultMaxTokens(model, options) {
|
|
580
|
+
const defaultMaxTokens = model.maxTokens > 0 ? model.maxTokens >= model.contextWindow - CONTEXT_WINDOW_OUTPUT_TOLERANCE ? Math.min(model.maxTokens, DEFAULT_MAX_OUTPUT_TOKENS) : model.maxTokens : void 0;
|
|
581
|
+
return {
|
|
582
|
+
...options,
|
|
583
|
+
maxTokens: options?.maxTokens ?? defaultMaxTokens
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
Type$2.Evaluate(Type$2.Intersect([SharedOptions, Type$2.Object({
|
|
587
|
+
baseURL: Type$2.Optional(Type$2.String()),
|
|
588
|
+
method: Type$2.Optional(Model.APIMethodEnumSchema),
|
|
589
|
+
modelId: Type$2.Optional(Type$2.String()),
|
|
590
|
+
reasoning: Type$2.Optional(Model.ActiveThinkingLevel),
|
|
591
|
+
thinkingBudgets: Type$2.Optional(ThinkingBudgets),
|
|
592
|
+
toolChoice: Type$2.Optional(Type$2.Any()),
|
|
593
|
+
activeTools: Type$2.Optional(Type$2.Array(Type$2.String())),
|
|
594
|
+
factoryOptions: Type$2.Optional(Type$2.Record(Type$2.String(), Type$2.Unknown())),
|
|
595
|
+
providerOptions: Type$2.Optional(Type$2.Record(Type$2.String(), Type$2.Record(Type$2.String(), Type$2.Unknown())))
|
|
596
|
+
})]));
|
|
457
597
|
//#endregion
|
|
458
598
|
//#region src/utils/eventstream.ts
|
|
459
599
|
var EventStream = class {
|
|
@@ -512,788 +652,67 @@ var AssistantMessageEventStream = class extends EventStream {
|
|
|
512
652
|
});
|
|
513
653
|
}
|
|
514
654
|
};
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
allErrors: true,
|
|
519
|
-
strict: false,
|
|
520
|
-
coerceTypes: true
|
|
521
|
-
});
|
|
522
|
-
addFormats(ajv);
|
|
523
|
-
/**
|
|
524
|
-
* Validates an arbitrary value against a TypeBox schema and returns the coerced value.
|
|
525
|
-
*/
|
|
526
|
-
function validateSchema(schema, value, label) {
|
|
527
|
-
const validate = ajv.compile(schema);
|
|
528
|
-
const input = structuredClone(value);
|
|
529
|
-
if (validate(input)) return input;
|
|
530
|
-
const errors = validate.errors?.map((err) => {
|
|
531
|
-
return ` - ${err.instancePath ? err.instancePath.substring(1) : err.params?.missingProperty || "root"}: ${err.message}`;
|
|
532
|
-
}).join("\n") || "Unknown Validation Error";
|
|
533
|
-
throw new Error([
|
|
534
|
-
`Validation Failed For ${label}`,
|
|
535
|
-
`${errors}\n`,
|
|
536
|
-
"Received Value:",
|
|
537
|
-
`${JSON.stringify(value, null, 2)}\n`
|
|
538
|
-
].join("\n"));
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Validates tool call arguments against the tool's TypeBox schema
|
|
542
|
-
*/
|
|
543
|
-
function validateToolArguments(tool, toolExecution) {
|
|
544
|
-
return validateSchema(tool.parameters, toolExecution.rawArgs, `Tool "${toolExecution.name}"`);
|
|
655
|
+
/** Factory function for AssistantMessageEventStream (for use in extensions) */
|
|
656
|
+
function createAssistantMessageEventStream() {
|
|
657
|
+
return new AssistantMessageEventStream();
|
|
545
658
|
}
|
|
546
659
|
//#endregion
|
|
547
|
-
//#region src/
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const part = snapshot.parts[partIndex];
|
|
560
|
-
if (!part) throw new Error(`Assistant message part at index ${partIndex} was not found`);
|
|
561
|
-
return {
|
|
562
|
-
message: snapshot,
|
|
563
|
-
part
|
|
564
|
-
};
|
|
660
|
+
//#region src/llm/runtime.ts
|
|
661
|
+
function mergeHeaders(...headerSources) {
|
|
662
|
+
const merged = {};
|
|
663
|
+
for (const headers of headerSources) if (headers) Object.assign(merged, headers);
|
|
664
|
+
return merged;
|
|
665
|
+
}
|
|
666
|
+
function getEnvApiKey(provider) {
|
|
667
|
+
if (typeof process === "undefined") return;
|
|
668
|
+
const candidates = [provider.key, ...provider.env ?? []].filter((name) => Boolean(name));
|
|
669
|
+
for (const name of candidates) {
|
|
670
|
+
const value = process.env[name];
|
|
671
|
+
if (value) return value;
|
|
565
672
|
}
|
|
566
|
-
|
|
567
|
-
|
|
673
|
+
}
|
|
674
|
+
function formatThrownError(error) {
|
|
675
|
+
if (error instanceof Error) return error.stack || error.message || error.name;
|
|
676
|
+
if (typeof error === "string") return error;
|
|
677
|
+
try {
|
|
678
|
+
return JSON.stringify(error);
|
|
679
|
+
} catch {
|
|
680
|
+
return String(error);
|
|
568
681
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
682
|
+
}
|
|
683
|
+
//#endregion
|
|
684
|
+
//#region src/llm/provider.ts
|
|
685
|
+
function cleanHeaders(headers) {
|
|
686
|
+
const result = {};
|
|
687
|
+
for (const [key, value] of Object.entries(headers)) if (value !== null) result[key] = value;
|
|
688
|
+
return result;
|
|
689
|
+
}
|
|
690
|
+
function resolveBaseURL(model, options) {
|
|
691
|
+
return (options.baseURL ?? model.api?.url ?? model.baseUrl) || void 0;
|
|
692
|
+
}
|
|
693
|
+
async function resolveAISDKLanguageModel(model, options) {
|
|
694
|
+
const npm = packageForModel(model);
|
|
695
|
+
const createProvider = await loadProviderFactory(npm);
|
|
696
|
+
const apiKey = options.apiKey ?? getEnvApiKey(model.provider);
|
|
697
|
+
const headers = cleanHeaders(mergeHeaders(model.headers, options.headers));
|
|
698
|
+
const baseURL = resolveBaseURL(model, options);
|
|
699
|
+
const factoryOptions = {
|
|
700
|
+
...model.options,
|
|
701
|
+
...options.factoryOptions
|
|
702
|
+
};
|
|
703
|
+
if (apiKey) factoryOptions.apiKey = apiKey;
|
|
704
|
+
if (Object.keys(headers).length > 0) factoryOptions.headers = headers;
|
|
705
|
+
if (baseURL) factoryOptions.baseURL = baseURL;
|
|
706
|
+
if (npm === "@ai-sdk/openai-compatible") {
|
|
707
|
+
if (!baseURL) throw new Protocol.ProtocolAuthError({
|
|
708
|
+
protocol: model.protocol,
|
|
709
|
+
message: "AI SDK openai-compatible transport requires model.baseUrl, model.api.url, or options.baseURL"
|
|
584
710
|
});
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
const ensureMessageStarted = async (message) => {
|
|
588
|
-
if (started) return;
|
|
589
|
-
started = true;
|
|
590
|
-
await emitEvent(emit, {
|
|
591
|
-
type: "message.start",
|
|
592
|
-
message: snapshotAssistantMessage(message)
|
|
593
|
-
});
|
|
594
|
-
};
|
|
595
|
-
const emitMessageUpdate = async (message) => {
|
|
596
|
-
await emitEvent(emit, {
|
|
597
|
-
type: "message.update",
|
|
598
|
-
message: snapshotAssistantMessage(message)
|
|
599
|
-
});
|
|
600
|
-
};
|
|
601
|
-
const emitPartStart = async (message, partIndex) => {
|
|
602
|
-
await emitEvent(emit, {
|
|
603
|
-
type: "message.part.start",
|
|
604
|
-
partIndex,
|
|
605
|
-
...snapshotAssistantPartEvent(message, partIndex)
|
|
606
|
-
});
|
|
607
|
-
};
|
|
608
|
-
const emitPartUpdate = async (message, partIndex) => {
|
|
609
|
-
await emitEvent(emit, {
|
|
610
|
-
type: "message.part.update",
|
|
611
|
-
partIndex,
|
|
612
|
-
...snapshotAssistantPartEvent(message, partIndex),
|
|
613
|
-
source: "llm"
|
|
614
|
-
});
|
|
615
|
-
};
|
|
616
|
-
const emitPartEnd = async (message, partIndex) => {
|
|
617
|
-
await emitEvent(emit, {
|
|
618
|
-
type: "message.part.end",
|
|
619
|
-
partIndex,
|
|
620
|
-
...snapshotAssistantPartEvent(message, partIndex)
|
|
621
|
-
});
|
|
622
|
-
};
|
|
623
|
-
for await (const event of events) switch (event.type) {
|
|
624
|
-
case "start":
|
|
625
|
-
partialMessage = event.partial;
|
|
626
|
-
await ensureMessageStarted(partialMessage);
|
|
627
|
-
break;
|
|
628
|
-
case "text.start":
|
|
629
|
-
case "thinking.start":
|
|
630
|
-
case "toolcall.start":
|
|
631
|
-
partialMessage = event.partial;
|
|
632
|
-
await ensureMessageStarted(partialMessage);
|
|
633
|
-
await emitPartStart(partialMessage, event.partIndex);
|
|
634
|
-
break;
|
|
635
|
-
case "text.delta":
|
|
636
|
-
case "thinking.delta":
|
|
637
|
-
case "toolcall.delta":
|
|
638
|
-
partialMessage = event.partial;
|
|
639
|
-
await ensureMessageStarted(partialMessage);
|
|
640
|
-
await emitPartUpdate(partialMessage, event.partIndex);
|
|
641
|
-
break;
|
|
642
|
-
case "text.end":
|
|
643
|
-
case "thinking.end":
|
|
644
|
-
case "toolcall.end":
|
|
645
|
-
partialMessage = event.partial;
|
|
646
|
-
await ensureMessageStarted(partialMessage);
|
|
647
|
-
await emitPartEnd(partialMessage, event.partIndex);
|
|
648
|
-
await emitMessageUpdate(partialMessage);
|
|
649
|
-
break;
|
|
650
|
-
case "done":
|
|
651
|
-
await ensureMessageStarted(event.message);
|
|
652
|
-
await emitEvent(emit, {
|
|
653
|
-
type: "message.end",
|
|
654
|
-
message: snapshotAssistantMessage(event.message)
|
|
655
|
-
});
|
|
656
|
-
return event.message;
|
|
657
|
-
case "error":
|
|
658
|
-
await ensureMessageStarted(event.error);
|
|
659
|
-
await emitEvent(emit, {
|
|
660
|
-
type: "message.end",
|
|
661
|
-
message: snapshotAssistantMessage(event.error)
|
|
662
|
-
});
|
|
663
|
-
return event.error;
|
|
664
|
-
}
|
|
665
|
-
const finalMessage = await events.result();
|
|
666
|
-
await ensureMessageStarted(finalMessage);
|
|
667
|
-
await emitEvent(emit, {
|
|
668
|
-
type: "message.end",
|
|
669
|
-
message: snapshotAssistantMessage(finalMessage)
|
|
670
|
-
});
|
|
671
|
-
return finalMessage;
|
|
672
|
-
}
|
|
673
|
-
async function executeToolCalls(config, currentContext, message, toolCalls, emit, signal) {
|
|
674
|
-
if (config.toolExecution === "sequential") return executeToolCallsSequential(config, currentContext, message, toolCalls, emit, signal);
|
|
675
|
-
return executeToolCallsParallel(config, currentContext, message, toolCalls, emit, signal);
|
|
676
|
-
}
|
|
677
|
-
async function executeToolCallsSequential(config, currentContext, message, toolCalls, emit, signal) {
|
|
678
|
-
for (const toolCall of toolCalls) {
|
|
679
|
-
const toolCallInFlight = {
|
|
680
|
-
callID: toolCall.callID,
|
|
681
|
-
name: toolCall.name,
|
|
682
|
-
rawArgs: toolCall.arguments
|
|
683
|
-
};
|
|
684
|
-
await emitEvent(emit, {
|
|
685
|
-
type: "tool.execution.start",
|
|
686
|
-
...toolCallInFlight
|
|
687
|
-
});
|
|
688
|
-
const prepared = await prepareToolCall(config, currentContext, message, toolCallInFlight, signal);
|
|
689
|
-
if (prepared.error) {
|
|
690
|
-
const error = {
|
|
691
|
-
status: "error",
|
|
692
|
-
result: {
|
|
693
|
-
content: [{
|
|
694
|
-
type: "text",
|
|
695
|
-
text: prepared.error.message
|
|
696
|
-
}],
|
|
697
|
-
details: prepared.error.details,
|
|
698
|
-
isError: true
|
|
699
|
-
}
|
|
700
|
-
};
|
|
701
|
-
await emitToolCallTerminalResult(toolCall, prepared.runnable, message, emit, error);
|
|
702
|
-
} else {
|
|
703
|
-
const runnable = {
|
|
704
|
-
toolCall,
|
|
705
|
-
runnable: prepared.runnable,
|
|
706
|
-
tool: prepared.tool
|
|
707
|
-
};
|
|
708
|
-
const executed = await executeRunnableToolCall(runnable, message, emit, signal);
|
|
709
|
-
if (executed.error) {
|
|
710
|
-
const error = {
|
|
711
|
-
status: "error",
|
|
712
|
-
result: {
|
|
713
|
-
content: [{
|
|
714
|
-
type: "text",
|
|
715
|
-
text: executed.error.message
|
|
716
|
-
}],
|
|
717
|
-
details: executed.error.details,
|
|
718
|
-
isError: true
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
await emitToolCallTerminalResult(runnable.toolCall, runnable.runnable, message, emit, error);
|
|
722
|
-
} else await finalizeExecutedToolCall(config, currentContext, runnable.toolCall, runnable.runnable, message, emit, executed.result);
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
async function executeToolCallsParallel(config, currentContext, message, toolCalls, emit, signal) {
|
|
727
|
-
const runnables = [];
|
|
728
|
-
for (const toolCall of toolCalls) {
|
|
729
|
-
const toolCallInFlight = {
|
|
730
|
-
callID: toolCall.callID,
|
|
731
|
-
name: toolCall.name,
|
|
732
|
-
rawArgs: toolCall.arguments
|
|
733
|
-
};
|
|
734
|
-
await emitEvent(emit, {
|
|
735
|
-
type: "tool.execution.start",
|
|
736
|
-
...toolCallInFlight
|
|
737
|
-
});
|
|
738
|
-
const prepared = await prepareToolCall(config, currentContext, message, toolCallInFlight, signal);
|
|
739
|
-
if (prepared.error) {
|
|
740
|
-
const error = {
|
|
741
|
-
status: "error",
|
|
742
|
-
result: {
|
|
743
|
-
content: [{
|
|
744
|
-
type: "text",
|
|
745
|
-
text: prepared.error.message
|
|
746
|
-
}],
|
|
747
|
-
details: prepared.error.details,
|
|
748
|
-
isError: true
|
|
749
|
-
}
|
|
750
|
-
};
|
|
751
|
-
await emitToolCallTerminalResult(toolCall, prepared.runnable, message, emit, error);
|
|
752
|
-
} else runnables.push({
|
|
753
|
-
toolCall,
|
|
754
|
-
runnable: prepared.runnable,
|
|
755
|
-
tool: prepared.tool
|
|
756
|
-
});
|
|
757
|
-
}
|
|
758
|
-
const runningExecutions = runnables.map((runnable) => ({
|
|
759
|
-
runnable,
|
|
760
|
-
execution: executeRunnableToolCall(runnable, message, emit, signal)
|
|
761
|
-
}));
|
|
762
|
-
for (const running of runningExecutions) {
|
|
763
|
-
const executed = await running.execution;
|
|
764
|
-
const { runnable } = running;
|
|
765
|
-
if (executed.error) {
|
|
766
|
-
const error = {
|
|
767
|
-
status: "error",
|
|
768
|
-
result: {
|
|
769
|
-
content: [{
|
|
770
|
-
type: "text",
|
|
771
|
-
text: executed.error.message
|
|
772
|
-
}],
|
|
773
|
-
details: executed.error.details,
|
|
774
|
-
isError: true
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
await emitToolCallTerminalResult(runnable.toolCall, runnable.runnable, message, emit, error);
|
|
778
|
-
} else await finalizeExecutedToolCall(config, currentContext, runnable.toolCall, runnable.runnable, message, emit, executed.result);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
async function prepareToolCall(config, currentContext, assistantMessage, toolCallInFlight, signal) {
|
|
782
|
-
const tool = currentContext.tools?.find((t) => t.name === toolCallInFlight.name);
|
|
783
|
-
if (!tool) return {
|
|
784
|
-
error: {
|
|
785
|
-
kind: "error",
|
|
786
|
-
message: `Tool ${toolCallInFlight.name} Not Found`
|
|
787
|
-
},
|
|
788
|
-
runnable: toolCallInFlight
|
|
789
|
-
};
|
|
790
|
-
try {
|
|
791
|
-
toolCallInFlight.args = validateToolArguments(tool, toolCallInFlight);
|
|
792
|
-
if (config.beforeToolExecution) {
|
|
793
|
-
const beforeResult = await config.beforeToolExecution({
|
|
794
|
-
context: currentContext,
|
|
795
|
-
assistantMessage,
|
|
796
|
-
toolCall: toolCallInFlight
|
|
797
|
-
}, signal);
|
|
798
|
-
if (beforeResult?.block) return {
|
|
799
|
-
error: {
|
|
800
|
-
kind: "blocked",
|
|
801
|
-
message: beforeResult?.reason || "Tool Execution was Blocked",
|
|
802
|
-
details: beforeResult?.details
|
|
803
|
-
},
|
|
804
|
-
runnable: toolCallInFlight
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
return {
|
|
808
|
-
runnable: toolCallInFlight,
|
|
809
|
-
tool
|
|
810
|
-
};
|
|
811
|
-
} catch (err) {
|
|
812
|
-
return {
|
|
813
|
-
error: {
|
|
814
|
-
kind: "error",
|
|
815
|
-
message: err instanceof Error ? err.message : String(err)
|
|
816
|
-
},
|
|
817
|
-
runnable: toolCallInFlight
|
|
818
|
-
};
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
async function executeRunnableToolCall(toolCallRunnable, message, emit, signal) {
|
|
822
|
-
const { toolCall, runnable, tool } = toolCallRunnable;
|
|
823
|
-
const { partIndex, ...pendingPart } = toolCall;
|
|
824
|
-
try {
|
|
825
|
-
return { result: await tool.execute(runnable.callID, runnable.args, signal, async (result) => {
|
|
826
|
-
const runningResult = {
|
|
827
|
-
status: "running",
|
|
828
|
-
partial: result.partial
|
|
829
|
-
};
|
|
830
|
-
await emitEvent(emit, {
|
|
831
|
-
type: "tool.execution.update",
|
|
832
|
-
...runnable,
|
|
833
|
-
...runningResult
|
|
834
|
-
});
|
|
835
|
-
const runningPart = {
|
|
836
|
-
...pendingPart,
|
|
837
|
-
...runningResult
|
|
838
|
-
};
|
|
839
|
-
message.parts[partIndex] = runningPart;
|
|
840
|
-
await emitEvent(emit, {
|
|
841
|
-
type: "message.part.update",
|
|
842
|
-
message,
|
|
843
|
-
partIndex,
|
|
844
|
-
part: runningPart,
|
|
845
|
-
source: "tool"
|
|
846
|
-
});
|
|
847
|
-
}) };
|
|
848
|
-
} catch (err) {
|
|
849
|
-
return { error: { message: err instanceof Error ? err.message : String(err) } };
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
async function emitToolCallTerminalResult(toolCall, runnable, message, emit, result) {
|
|
853
|
-
const { partIndex, ...pendingPart } = toolCall;
|
|
854
|
-
const { time } = pendingPart;
|
|
855
|
-
await emitEvent(emit, {
|
|
856
|
-
type: "tool.execution.end",
|
|
857
|
-
...runnable,
|
|
858
|
-
...result
|
|
859
|
-
});
|
|
860
|
-
const part = {
|
|
861
|
-
...pendingPart,
|
|
862
|
-
...result,
|
|
863
|
-
time: {
|
|
864
|
-
start: time.start,
|
|
865
|
-
end: Date.now()
|
|
866
|
-
}
|
|
867
|
-
};
|
|
868
|
-
message.parts[partIndex] = part;
|
|
869
|
-
await emitEvent(emit, {
|
|
870
|
-
type: "message.part.start",
|
|
871
|
-
message,
|
|
872
|
-
partIndex,
|
|
873
|
-
part
|
|
874
|
-
});
|
|
875
|
-
await emitEvent(emit, {
|
|
876
|
-
type: "message.part.end",
|
|
877
|
-
message,
|
|
878
|
-
partIndex,
|
|
879
|
-
part
|
|
880
|
-
});
|
|
881
|
-
await emitEvent(emit, {
|
|
882
|
-
type: "message.update",
|
|
883
|
-
message
|
|
884
|
-
});
|
|
885
|
-
}
|
|
886
|
-
async function finalizeExecutedToolCall(config, currentContext, toolCall, runnable, message, emit, result, signal) {
|
|
887
|
-
if (config.afterToolExecution) {
|
|
888
|
-
const afterResult = await config.afterToolExecution({
|
|
889
|
-
context: currentContext,
|
|
890
|
-
assistantMessage: message,
|
|
891
|
-
toolCall: runnable,
|
|
892
|
-
result
|
|
893
|
-
}, signal);
|
|
894
|
-
if (afterResult) {
|
|
895
|
-
await emitToolCallTerminalResult(toolCall, runnable, message, emit, afterResult);
|
|
896
|
-
return;
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
await emitToolCallTerminalResult(toolCall, runnable, message, emit, result);
|
|
900
|
-
}
|
|
901
|
-
/**
|
|
902
|
-
* Main core loop shared by run and runContinue.
|
|
903
|
-
*/
|
|
904
|
-
async function runLoop(config, currentContext, newMessages, emit, streamFn, signal) {
|
|
905
|
-
let firstTurn = true;
|
|
906
|
-
let pendingMessages = await config.getSteeringMessages?.() || [];
|
|
907
|
-
while (true) {
|
|
908
|
-
let hasMoreToolCalls = true;
|
|
909
|
-
while (hasMoreToolCalls || pendingMessages.length > 0) {
|
|
910
|
-
if (!firstTurn) await emitEvent(emit, { type: "turn.start" });
|
|
911
|
-
else firstTurn = false;
|
|
912
|
-
if (pendingMessages.length > 0) {
|
|
913
|
-
for (const message of pendingMessages) {
|
|
914
|
-
await emitEvent(emit, {
|
|
915
|
-
type: "message.start",
|
|
916
|
-
message
|
|
917
|
-
});
|
|
918
|
-
for (const [partIndex, part] of message.parts.entries()) {
|
|
919
|
-
await emitEvent(emit, {
|
|
920
|
-
type: "message.part.start",
|
|
921
|
-
message,
|
|
922
|
-
partIndex,
|
|
923
|
-
part
|
|
924
|
-
});
|
|
925
|
-
await emitEvent(emit, {
|
|
926
|
-
type: "message.part.end",
|
|
927
|
-
message,
|
|
928
|
-
partIndex,
|
|
929
|
-
part
|
|
930
|
-
});
|
|
931
|
-
await emitEvent(emit, {
|
|
932
|
-
type: "message.update",
|
|
933
|
-
message
|
|
934
|
-
});
|
|
935
|
-
}
|
|
936
|
-
await emitEvent(emit, {
|
|
937
|
-
type: "message.end",
|
|
938
|
-
message
|
|
939
|
-
});
|
|
940
|
-
currentContext.messages.push(message);
|
|
941
|
-
newMessages.push(message);
|
|
942
|
-
}
|
|
943
|
-
pendingMessages = [];
|
|
944
|
-
}
|
|
945
|
-
const message = await streamAssistantResponse(config, currentContext, emit, streamFn, signal);
|
|
946
|
-
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
947
|
-
currentContext.messages.push(message);
|
|
948
|
-
newMessages.push(message);
|
|
949
|
-
await emitEvent(emit, {
|
|
950
|
-
type: "turn.end",
|
|
951
|
-
message
|
|
952
|
-
});
|
|
953
|
-
await emitEvent(emit, {
|
|
954
|
-
type: "agent.end",
|
|
955
|
-
messages: newMessages
|
|
956
|
-
});
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
const toolCalls = message.parts.map((part, index) => ({
|
|
960
|
-
...part,
|
|
961
|
-
partIndex: index
|
|
962
|
-
})).filter((part) => part.type === "toolCall" && part.status === "pending");
|
|
963
|
-
hasMoreToolCalls = toolCalls.length > 0;
|
|
964
|
-
if (hasMoreToolCalls) await executeToolCalls(config, currentContext, message, toolCalls, emit, signal);
|
|
965
|
-
currentContext.messages.push(message);
|
|
966
|
-
newMessages.push(message);
|
|
967
|
-
await emitEvent(emit, {
|
|
968
|
-
type: "turn.end",
|
|
969
|
-
message
|
|
970
|
-
});
|
|
971
|
-
pendingMessages = await config.getSteeringMessages?.() || [];
|
|
972
|
-
}
|
|
973
|
-
const followUpMessages = await config.getFollowUpMessages?.() || [];
|
|
974
|
-
if (followUpMessages.length > 0) {
|
|
975
|
-
pendingMessages = followUpMessages;
|
|
976
|
-
continue;
|
|
977
|
-
}
|
|
978
|
-
break;
|
|
979
|
-
}
|
|
980
|
-
await emitEvent(emit, {
|
|
981
|
-
type: "agent.end",
|
|
982
|
-
messages: newMessages
|
|
983
|
-
});
|
|
984
|
-
}
|
|
985
|
-
async function runAgentLoop(config, context, prompts, emit, streamFn, signal) {
|
|
986
|
-
/**
|
|
987
|
-
* maintain 2 arrays to represent state, `context` the actual full state sent to the LLM,
|
|
988
|
-
* `newMessages` for intermediate current loop state.
|
|
989
|
-
* think of newMessages as subset of context.messages for the running current loop.
|
|
990
|
-
* they do move at the same speed staring with initial user prompts.
|
|
991
|
-
* */
|
|
992
|
-
const newMessages = [...prompts];
|
|
993
|
-
const currentContext = {
|
|
994
|
-
...context,
|
|
995
|
-
messages: [...context.messages, ...prompts]
|
|
996
|
-
};
|
|
997
|
-
await emitEvent(emit, { type: "agent.start" });
|
|
998
|
-
await emitEvent(emit, { type: "turn.start" });
|
|
999
|
-
for (const prompt of prompts) {
|
|
1000
|
-
await emitEvent(emit, {
|
|
1001
|
-
type: "message.start",
|
|
1002
|
-
message: prompt
|
|
1003
|
-
});
|
|
1004
|
-
for (const [partIndex, part] of prompt.parts.entries()) {
|
|
1005
|
-
await emitEvent(emit, {
|
|
1006
|
-
type: "message.part.start",
|
|
1007
|
-
message: prompt,
|
|
1008
|
-
partIndex,
|
|
1009
|
-
part
|
|
1010
|
-
});
|
|
1011
|
-
await emitEvent(emit, {
|
|
1012
|
-
type: "message.part.end",
|
|
1013
|
-
message: prompt,
|
|
1014
|
-
partIndex,
|
|
1015
|
-
part
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
await emitEvent(emit, {
|
|
1019
|
-
type: "message.end",
|
|
1020
|
-
message: prompt
|
|
1021
|
-
});
|
|
1022
|
-
}
|
|
1023
|
-
await runLoop(config, currentContext, newMessages, emit, streamFn, signal);
|
|
1024
|
-
return newMessages;
|
|
1025
|
-
}
|
|
1026
|
-
_Loop.runAgentLoop = runAgentLoop;
|
|
1027
|
-
async function runAgentLoopContinue(config, context, emit, streamFn, signal) {
|
|
1028
|
-
if (context.messages.length === 0) throw new AgentContextError({ message: "connot continue: no messages in context" });
|
|
1029
|
-
if (context.messages[context.messages.length - 1]?.role === "assistant") throw new AgentContextError({ message: "cannot continue from message role: assistant" });
|
|
1030
|
-
const newMessages = [];
|
|
1031
|
-
const currentContext = { ...context };
|
|
1032
|
-
await emitEvent(emit, { type: "agent.start" });
|
|
1033
|
-
await emitEvent(emit, { type: "turn.start" });
|
|
1034
|
-
await runLoop(config, currentContext, newMessages, emit, streamFn, signal);
|
|
1035
|
-
return newMessages;
|
|
1036
|
-
}
|
|
1037
|
-
_Loop.runAgentLoopContinue = runAgentLoopContinue;
|
|
1038
|
-
function run(config, context, prompts, streamFn, signal) {
|
|
1039
|
-
const stream = createAgentStream();
|
|
1040
|
-
runAgentLoop(config, context, prompts, async (event) => {
|
|
1041
|
-
stream.push(event);
|
|
1042
|
-
}, streamFn, signal).then((messages) => {
|
|
1043
|
-
stream.end(messages);
|
|
1044
|
-
});
|
|
1045
|
-
return stream;
|
|
1046
|
-
}
|
|
1047
|
-
_Loop.run = run;
|
|
1048
|
-
function runContinue(config, context, streamFn, signal) {
|
|
1049
|
-
const stream = createAgentStream();
|
|
1050
|
-
runAgentLoopContinue(config, context, async (event) => {
|
|
1051
|
-
stream.push(event);
|
|
1052
|
-
}, streamFn, signal).then((messages) => {
|
|
1053
|
-
stream.end(messages);
|
|
1054
|
-
});
|
|
1055
|
-
return stream;
|
|
1056
|
-
}
|
|
1057
|
-
_Loop.runContinue = runContinue;
|
|
1058
|
-
})(Loop || (Loop = {}));
|
|
1059
|
-
//#endregion
|
|
1060
|
-
//#region src/agent.ts
|
|
1061
|
-
const agent = {
|
|
1062
|
-
loop: Loop.run,
|
|
1063
|
-
loopContinue: Loop.runContinue
|
|
1064
|
-
};
|
|
1065
|
-
//#endregion
|
|
1066
|
-
//#region src/message/message.ts
|
|
1067
|
-
let Message;
|
|
1068
|
-
(function(_Message) {
|
|
1069
|
-
const TextContentSchema = _Message.TextContentSchema = Type.Object({
|
|
1070
|
-
type: Type.Literal("text"),
|
|
1071
|
-
text: Type.String(),
|
|
1072
|
-
textSignature: Type.Optional(Type.String())
|
|
1073
|
-
});
|
|
1074
|
-
const ImageContentSchema = _Message.ImageContentSchema = Type.Object({
|
|
1075
|
-
type: Type.Literal("image"),
|
|
1076
|
-
data: Type.String(),
|
|
1077
|
-
mimeType: Type.String()
|
|
1078
|
-
});
|
|
1079
|
-
const ThinkingContentSchema = _Message.ThinkingContentSchema = Type.Object({
|
|
1080
|
-
type: Type.Literal("thinking"),
|
|
1081
|
-
thinking: Type.String(),
|
|
1082
|
-
thinkingSignature: Type.Optional(Type.String()),
|
|
1083
|
-
redacted: Type.Optional(Type.Boolean())
|
|
1084
|
-
});
|
|
1085
|
-
const ToolCallBaseSchema = _Message.ToolCallBaseSchema = Type.Object({
|
|
1086
|
-
type: Type.Literal("toolCall"),
|
|
1087
|
-
callID: Type.String(),
|
|
1088
|
-
name: Type.String(),
|
|
1089
|
-
arguments: Type.Record(Type.String(), Type.Any()),
|
|
1090
|
-
thoughtSignature: Type.Optional(Type.String()),
|
|
1091
|
-
time: Type.Object({
|
|
1092
|
-
start: Type.Number(),
|
|
1093
|
-
end: Type.Number()
|
|
1094
|
-
})
|
|
1095
|
-
});
|
|
1096
|
-
const ToolSuccessResult = _Message.ToolSuccessResult = Type.Object({
|
|
1097
|
-
content: Type.Array(Type.Union([TextContentSchema, ImageContentSchema])),
|
|
1098
|
-
details: Type.Optional(Type.Any()),
|
|
1099
|
-
isError: Type.Literal(false)
|
|
1100
|
-
});
|
|
1101
|
-
const ToolErrorResult = _Message.ToolErrorResult = Type.Object({
|
|
1102
|
-
content: Type.Array(Type.Union([TextContentSchema, ImageContentSchema])),
|
|
1103
|
-
details: Type.Optional(Type.Any()),
|
|
1104
|
-
isError: Type.Literal(true)
|
|
1105
|
-
});
|
|
1106
|
-
const ToolRunningPartial = _Message.ToolRunningPartial = Type.Object({
|
|
1107
|
-
content: Type.Optional(Type.Array(Type.Union([TextContentSchema, ImageContentSchema]))),
|
|
1108
|
-
details: Type.Optional(Type.Any())
|
|
1109
|
-
});
|
|
1110
|
-
const ToolStatusEnum = _Message.ToolStatusEnum = {
|
|
1111
|
-
pending: "pending",
|
|
1112
|
-
running: "running",
|
|
1113
|
-
completed: "completed",
|
|
1114
|
-
error: "error",
|
|
1115
|
-
skipped: "skipped",
|
|
1116
|
-
aborted: "aborted"
|
|
1117
|
-
};
|
|
1118
|
-
const ToolRunningSchema = _Message.ToolRunningSchema = Type.Object({
|
|
1119
|
-
status: Type.Literal(ToolStatusEnum.running),
|
|
1120
|
-
partial: Type.Optional(ToolRunningPartial)
|
|
1121
|
-
});
|
|
1122
|
-
const ToolCompletedSchema = _Message.ToolCompletedSchema = Type.Object({
|
|
1123
|
-
status: Type.Literal(ToolStatusEnum.completed),
|
|
1124
|
-
result: ToolSuccessResult
|
|
1125
|
-
});
|
|
1126
|
-
const ToolErrorSchema = _Message.ToolErrorSchema = Type.Object({
|
|
1127
|
-
status: Type.Literal(ToolStatusEnum.error),
|
|
1128
|
-
result: ToolErrorResult
|
|
1129
|
-
});
|
|
1130
|
-
const ToolSkippedSchema = _Message.ToolSkippedSchema = Type.Object({
|
|
1131
|
-
status: Type.Literal(ToolStatusEnum.skipped),
|
|
1132
|
-
result: ToolErrorResult
|
|
1133
|
-
});
|
|
1134
|
-
const ToolAbortedSchema = _Message.ToolAbortedSchema = Type.Object({
|
|
1135
|
-
status: Type.Literal(ToolStatusEnum.aborted),
|
|
1136
|
-
result: ToolErrorResult
|
|
1137
|
-
});
|
|
1138
|
-
const ToolCallPendingPart = Type.Intersect([ToolCallBaseSchema, Type.Object({ status: Type.Literal(ToolStatusEnum.pending) })]);
|
|
1139
|
-
const ToolCallRunningPart = Type.Composite([ToolCallBaseSchema, ToolRunningSchema]);
|
|
1140
|
-
const ToolCallCompletedPart = Type.Composite([ToolCallBaseSchema, ToolCompletedSchema]);
|
|
1141
|
-
const ToolCallErrorPart = Type.Composite([ToolCallBaseSchema, ToolErrorSchema]);
|
|
1142
|
-
const ToolCallSkippedPart = Type.Composite([ToolCallBaseSchema, ToolSkippedSchema]);
|
|
1143
|
-
const ToolCallAbortedPart = Type.Composite([ToolCallBaseSchema, ToolAbortedSchema]);
|
|
1144
|
-
const ToolCallSchema = _Message.ToolCallSchema = Type.Union([
|
|
1145
|
-
ToolCallPendingPart,
|
|
1146
|
-
ToolCallRunningPart,
|
|
1147
|
-
ToolCallCompletedPart,
|
|
1148
|
-
ToolCallErrorPart,
|
|
1149
|
-
ToolCallSkippedPart,
|
|
1150
|
-
ToolCallAbortedPart
|
|
1151
|
-
]);
|
|
1152
|
-
const UsageSchema = _Message.UsageSchema = Type.Object({
|
|
1153
|
-
input: Type.Number(),
|
|
1154
|
-
output: Type.Number(),
|
|
1155
|
-
cacheRead: Type.Number(),
|
|
1156
|
-
cacheWrite: Type.Number(),
|
|
1157
|
-
totalTokens: Type.Number(),
|
|
1158
|
-
cost: Type.Object({
|
|
1159
|
-
input: Type.Number(),
|
|
1160
|
-
output: Type.Number(),
|
|
1161
|
-
cacheRead: Type.Number(),
|
|
1162
|
-
cacheWrite: Type.Number(),
|
|
1163
|
-
total: Type.Number()
|
|
1164
|
-
})
|
|
1165
|
-
});
|
|
1166
|
-
const StopReasonSchema = _Message.StopReasonSchema = Type.Union([
|
|
1167
|
-
Type.Literal("stop"),
|
|
1168
|
-
Type.Literal("length"),
|
|
1169
|
-
Type.Literal("toolUse"),
|
|
1170
|
-
Type.Literal("error"),
|
|
1171
|
-
Type.Literal("aborted")
|
|
1172
|
-
]);
|
|
1173
|
-
const UserMessageSchema = _Message.UserMessageSchema = Type.Object({
|
|
1174
|
-
messageId: Type.String(),
|
|
1175
|
-
role: Type.Literal("user"),
|
|
1176
|
-
time: Type.Object({ created: Type.Number() }),
|
|
1177
|
-
parts: Type.Array(Type.Union([TextContentSchema, ImageContentSchema]))
|
|
1178
|
-
});
|
|
1179
|
-
const AssistantMessageSchema = _Message.AssistantMessageSchema = Type.Object({
|
|
1180
|
-
role: Type.Literal("assistant"),
|
|
1181
|
-
protocol: Model.KnownProtocolSchema,
|
|
1182
|
-
provider: Provider.Info,
|
|
1183
|
-
model: Type.String(),
|
|
1184
|
-
usage: UsageSchema,
|
|
1185
|
-
stopReason: StopReasonSchema,
|
|
1186
|
-
errorMessage: Type.Optional(Type.String()),
|
|
1187
|
-
time: Type.Object({
|
|
1188
|
-
created: Type.Number(),
|
|
1189
|
-
completed: Type.Number()
|
|
1190
|
-
}),
|
|
1191
|
-
parts: Type.Array(Type.Union([
|
|
1192
|
-
TextContentSchema,
|
|
1193
|
-
ImageContentSchema,
|
|
1194
|
-
ThinkingContentSchema,
|
|
1195
|
-
ToolCallSchema
|
|
1196
|
-
])),
|
|
1197
|
-
responseId: Type.Optional(Type.String()),
|
|
1198
|
-
messageId: Type.String()
|
|
1199
|
-
});
|
|
1200
|
-
const MessageSchema = _Message.MessageSchema = Type.Union([UserMessageSchema, AssistantMessageSchema]);
|
|
1201
|
-
function createMessageId() {
|
|
1202
|
-
return uuidv7();
|
|
1203
|
-
}
|
|
1204
|
-
_Message.createMessageId = createMessageId;
|
|
1205
|
-
function createUserMessage(message) {
|
|
1206
|
-
const { messageId = createMessageId(), ...rest } = message;
|
|
1207
|
-
return {
|
|
1208
|
-
messageId,
|
|
1209
|
-
...rest
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
_Message.createUserMessage = createUserMessage;
|
|
1213
|
-
function createAssistantMessage(message) {
|
|
1214
|
-
const { messageId = createMessageId(), ...rest } = message;
|
|
1215
|
-
return {
|
|
1216
|
-
messageId,
|
|
1217
|
-
...rest
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
_Message.createAssistantMessage = createAssistantMessage;
|
|
1221
|
-
const ToolSchema = _Message.ToolSchema = Type.Object({
|
|
1222
|
-
name: Type.String(),
|
|
1223
|
-
description: Type.String(),
|
|
1224
|
-
parameters: Type.Unsafe()
|
|
1225
|
-
});
|
|
1226
|
-
function defineTool(tool) {
|
|
1227
|
-
return tool;
|
|
1228
|
-
}
|
|
1229
|
-
_Message.defineTool = defineTool;
|
|
1230
|
-
_Message.ContextSchema = Type.Object({
|
|
1231
|
-
systemPrompt: Type.Optional(Type.String()),
|
|
1232
|
-
messages: Type.Array(MessageSchema),
|
|
1233
|
-
tools: Type.Optional(Type.Array(ToolSchema))
|
|
1234
|
-
});
|
|
1235
|
-
function transformMessages(messages, model, normalizeToolCallId) {
|
|
1236
|
-
const toolCallIDMap = /* @__PURE__ */ new Map();
|
|
1237
|
-
const transformed = [];
|
|
1238
|
-
for (const msg of messages) {
|
|
1239
|
-
if (msg.role === "user") {
|
|
1240
|
-
transformed.push(msg);
|
|
1241
|
-
continue;
|
|
1242
|
-
}
|
|
1243
|
-
const assistantMsg = msg;
|
|
1244
|
-
const isSameModel = assistantMsg.provider.id === model.provider.id && assistantMsg.protocol === model.protocol && assistantMsg.model === model.id;
|
|
1245
|
-
const parts = assistantMsg.parts.flatMap((block) => {
|
|
1246
|
-
if (block.type === "thinking") {
|
|
1247
|
-
if (isSameModel && block.thinkingSignature) return block;
|
|
1248
|
-
if (!block.thinking || block.thinking.trim() === "") return [];
|
|
1249
|
-
if (isSameModel) return block;
|
|
1250
|
-
return {
|
|
1251
|
-
type: "text",
|
|
1252
|
-
text: block.thinking
|
|
1253
|
-
};
|
|
1254
|
-
}
|
|
1255
|
-
if (block.type === "text") {
|
|
1256
|
-
if (isSameModel) return block;
|
|
1257
|
-
return {
|
|
1258
|
-
type: "text",
|
|
1259
|
-
text: block.text
|
|
1260
|
-
};
|
|
1261
|
-
}
|
|
1262
|
-
if (block.type === "toolCall") {
|
|
1263
|
-
const toolCall = block;
|
|
1264
|
-
let normalizedToolCall = toolCall;
|
|
1265
|
-
if (!isSameModel && toolCall.thoughtSignature) {
|
|
1266
|
-
normalizedToolCall = { ...toolCall };
|
|
1267
|
-
delete normalizedToolCall.thoughtSignature;
|
|
1268
|
-
}
|
|
1269
|
-
const normalizedID = toolCallIDMap.get(block.callID);
|
|
1270
|
-
if (normalizedID && normalizedID !== block.callID) normalizedToolCall = {
|
|
1271
|
-
...normalizedToolCall,
|
|
1272
|
-
callID: normalizedID
|
|
1273
|
-
};
|
|
1274
|
-
else if (!isSameModel && normalizeToolCallId) {
|
|
1275
|
-
const nextID = normalizeToolCallId(toolCall.callID, model, assistantMsg);
|
|
1276
|
-
if (nextID !== toolCall.callID) {
|
|
1277
|
-
toolCallIDMap.set(toolCall.callID, nextID);
|
|
1278
|
-
normalizedToolCall = {
|
|
1279
|
-
...normalizedToolCall,
|
|
1280
|
-
callID: nextID
|
|
1281
|
-
};
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
return normalizedToolCall;
|
|
1285
|
-
}
|
|
1286
|
-
return block;
|
|
1287
|
-
});
|
|
1288
|
-
transformed.push({
|
|
1289
|
-
...assistantMsg,
|
|
1290
|
-
parts
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
return transformed;
|
|
711
|
+
factoryOptions.name ??= model.provider.id;
|
|
712
|
+
factoryOptions.includeUsage ??= true;
|
|
1294
713
|
}
|
|
1295
|
-
|
|
1296
|
-
}
|
|
714
|
+
return resolveLanguageModel(createProvider(factoryOptions), model, options.method);
|
|
715
|
+
}
|
|
1297
716
|
//#endregion
|
|
1298
717
|
//#region src/utils/jsonparse.ts
|
|
1299
718
|
/**
|
|
@@ -1311,6 +730,14 @@ function parseStreamingJson(partialJson) {
|
|
|
1311
730
|
try {
|
|
1312
731
|
return JSON.parse(partialJson);
|
|
1313
732
|
} catch {
|
|
733
|
+
const repaired = repairInvalidJsonStringContent(partialJson);
|
|
734
|
+
if (repaired !== partialJson) try {
|
|
735
|
+
return JSON.parse(repaired);
|
|
736
|
+
} catch {
|
|
737
|
+
try {
|
|
738
|
+
return parse(repaired) ?? {};
|
|
739
|
+
} catch {}
|
|
740
|
+
}
|
|
1314
741
|
try {
|
|
1315
742
|
return parse(partialJson) ?? {};
|
|
1316
743
|
} catch {
|
|
@@ -1318,6 +745,55 @@ function parseStreamingJson(partialJson) {
|
|
|
1318
745
|
}
|
|
1319
746
|
}
|
|
1320
747
|
}
|
|
748
|
+
function repairInvalidJsonStringContent(input) {
|
|
749
|
+
let output = "";
|
|
750
|
+
let inString = false;
|
|
751
|
+
let escaping = false;
|
|
752
|
+
for (const char of input) {
|
|
753
|
+
if (!inString) {
|
|
754
|
+
output += char;
|
|
755
|
+
if (char === "\"") inString = true;
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
if (escaping) {
|
|
759
|
+
if (`"\\/bfnrtu`.includes(char)) output += `\\${char}`;
|
|
760
|
+
else output += `\\\\${char}`;
|
|
761
|
+
escaping = false;
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
if (char === "\\") {
|
|
765
|
+
escaping = true;
|
|
766
|
+
continue;
|
|
767
|
+
}
|
|
768
|
+
if (char === "\"") {
|
|
769
|
+
inString = false;
|
|
770
|
+
output += char;
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
switch (char) {
|
|
774
|
+
case "\b":
|
|
775
|
+
output += "\\b";
|
|
776
|
+
break;
|
|
777
|
+
case "\f":
|
|
778
|
+
output += "\\f";
|
|
779
|
+
break;
|
|
780
|
+
case "\n":
|
|
781
|
+
output += "\\n";
|
|
782
|
+
break;
|
|
783
|
+
case "\r":
|
|
784
|
+
output += "\\r";
|
|
785
|
+
break;
|
|
786
|
+
case " ":
|
|
787
|
+
output += "\\t";
|
|
788
|
+
break;
|
|
789
|
+
default:
|
|
790
|
+
output += char;
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
if (escaping) output += "\\\\";
|
|
795
|
+
return output;
|
|
796
|
+
}
|
|
1321
797
|
//#endregion
|
|
1322
798
|
//#region src/utils/sanitize.ts
|
|
1323
799
|
/**
|
|
@@ -1344,812 +820,542 @@ function sanitizeSurrogates(text) {
|
|
|
1344
820
|
return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
|
|
1345
821
|
}
|
|
1346
822
|
//#endregion
|
|
1347
|
-
//#region src/
|
|
1348
|
-
function
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
823
|
+
//#region src/llm/transform.ts
|
|
824
|
+
function createAssistantMessage(model) {
|
|
825
|
+
return Message.createAssistantMessage({
|
|
826
|
+
role: "assistant",
|
|
827
|
+
parts: [],
|
|
828
|
+
protocol: model.protocol,
|
|
829
|
+
provider: model.provider,
|
|
830
|
+
model: model.id,
|
|
831
|
+
usage: {
|
|
832
|
+
input: 0,
|
|
833
|
+
output: 0,
|
|
834
|
+
cacheRead: 0,
|
|
835
|
+
cacheWrite: 0,
|
|
836
|
+
totalTokens: 0,
|
|
837
|
+
cost: {
|
|
838
|
+
input: 0,
|
|
839
|
+
output: 0,
|
|
840
|
+
cacheRead: 0,
|
|
841
|
+
cacheWrite: 0,
|
|
842
|
+
total: 0
|
|
843
|
+
}
|
|
844
|
+
},
|
|
845
|
+
stopReason: "stop",
|
|
846
|
+
time: {
|
|
847
|
+
created: Date.now(),
|
|
848
|
+
completed: Date.now()
|
|
1365
849
|
}
|
|
1366
|
-
};
|
|
850
|
+
});
|
|
1367
851
|
}
|
|
1368
|
-
|
|
1369
|
-
const
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
"NotebookEdit",
|
|
1381
|
-
"Skill",
|
|
1382
|
-
"Task",
|
|
1383
|
-
"TaskOutput",
|
|
1384
|
-
"TodoWrite",
|
|
1385
|
-
"WebFetch",
|
|
1386
|
-
"WebSearch"
|
|
1387
|
-
].map((t) => [t.toLowerCase(), t]));
|
|
1388
|
-
const toClaudeCodeName = (name) => ccToolLookup.get(name.toLowerCase()) ?? name;
|
|
1389
|
-
const fromClaudeCodeName = (name, tools) => {
|
|
1390
|
-
if (tools && tools.length > 0) {
|
|
1391
|
-
const lowerName = name.toLowerCase();
|
|
1392
|
-
const matchedTool = tools.find((tool) => tool.name.toLowerCase() === lowerName);
|
|
1393
|
-
if (matchedTool) return matchedTool.name;
|
|
1394
|
-
}
|
|
1395
|
-
return name;
|
|
1396
|
-
};
|
|
1397
|
-
function convertContentBlocks(content) {
|
|
1398
|
-
if (!content.some((c) => c.type === "image")) return sanitizeSurrogates(content.map((c) => c.text).join("\n"));
|
|
1399
|
-
const blocks = content.map((block) => {
|
|
1400
|
-
if (block.type === "text") return {
|
|
1401
|
-
type: "text",
|
|
1402
|
-
text: sanitizeSurrogates(block.text)
|
|
1403
|
-
};
|
|
1404
|
-
return {
|
|
852
|
+
function userContent(parts, supportsImages) {
|
|
853
|
+
const content = [];
|
|
854
|
+
for (const part of parts) {
|
|
855
|
+
if (part.type === "text") {
|
|
856
|
+
const text = sanitizeSurrogates(part.text);
|
|
857
|
+
if (text.trim().length > 0) content.push({
|
|
858
|
+
type: "text",
|
|
859
|
+
text
|
|
860
|
+
});
|
|
861
|
+
continue;
|
|
862
|
+
}
|
|
863
|
+
if (supportsImages) content.push({
|
|
1405
864
|
type: "image",
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
data: block.data
|
|
1410
|
-
}
|
|
1411
|
-
};
|
|
1412
|
-
});
|
|
1413
|
-
if (!blocks.some((b) => b.type === "text")) blocks.unshift({
|
|
1414
|
-
type: "text",
|
|
1415
|
-
text: "(see attached image)"
|
|
1416
|
-
});
|
|
1417
|
-
return blocks;
|
|
1418
|
-
}
|
|
1419
|
-
function mergeHeaders(...headerSources) {
|
|
1420
|
-
const merged = {};
|
|
1421
|
-
for (const headers of headerSources) if (headers) Object.assign(merged, headers);
|
|
1422
|
-
return merged;
|
|
1423
|
-
}
|
|
1424
|
-
function isOAuthToken(apiKey) {
|
|
1425
|
-
return apiKey.includes("sk-ant-oat");
|
|
1426
|
-
}
|
|
1427
|
-
function createClient$1(model, apiKey, interleavedThinking, optionsHeaders) {
|
|
1428
|
-
const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
|
|
1429
|
-
if (interleavedThinking) betaFeatures.push("interleaved-thinking-2025-05-14");
|
|
1430
|
-
if (isOAuthToken(apiKey)) {
|
|
1431
|
-
const defaultHeaders = mergeHeaders({
|
|
1432
|
-
accept: "application/json",
|
|
1433
|
-
"anthropic-dangerous-direct-browser-access": "true",
|
|
1434
|
-
"anthropic-beta": `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}`,
|
|
1435
|
-
"user-agent": `claude-cli/${claudeCodeVersion} (external, cli)`,
|
|
1436
|
-
"x-app": "cli"
|
|
1437
|
-
}, model.headers, optionsHeaders);
|
|
1438
|
-
return {
|
|
1439
|
-
client: new Anthropic({
|
|
1440
|
-
apiKey: null,
|
|
1441
|
-
authToken: apiKey,
|
|
1442
|
-
baseURL: model.baseUrl,
|
|
1443
|
-
defaultHeaders,
|
|
1444
|
-
dangerouslyAllowBrowser: true
|
|
1445
|
-
}),
|
|
1446
|
-
isOAuthToken: true
|
|
1447
|
-
};
|
|
865
|
+
image: part.data,
|
|
866
|
+
mediaType: part.mimeType
|
|
867
|
+
});
|
|
1448
868
|
}
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
}
|
|
1454
|
-
return {
|
|
1455
|
-
client: new Anthropic({
|
|
1456
|
-
apiKey,
|
|
1457
|
-
baseURL: model.baseUrl,
|
|
1458
|
-
dangerouslyAllowBrowser: true,
|
|
1459
|
-
defaultHeaders
|
|
1460
|
-
}),
|
|
1461
|
-
isOAuthToken: false
|
|
1462
|
-
};
|
|
1463
|
-
}
|
|
1464
|
-
function normalizeToolCallId(id) {
|
|
1465
|
-
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
869
|
+
if (content.length === 0) return [];
|
|
870
|
+
return [{
|
|
871
|
+
role: "user",
|
|
872
|
+
content
|
|
873
|
+
}];
|
|
1466
874
|
}
|
|
1467
|
-
function
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
sawToolCall = true;
|
|
1475
|
-
if (part.status === "pending" || part.status === "running") sawNonTerminalToolCall = true;
|
|
1476
|
-
else sawTerminalToolCall = true;
|
|
1477
|
-
continue;
|
|
1478
|
-
}
|
|
1479
|
-
if (sawToolCall) throw new Error("Assistant parts after a toolCall are not replayable for Anthropic");
|
|
875
|
+
function sanitizeValue(value) {
|
|
876
|
+
if (typeof value === "string") return sanitizeSurrogates(value);
|
|
877
|
+
if (Array.isArray(value)) return value.map((item) => sanitizeValue(item));
|
|
878
|
+
if (typeof value === "object" && value !== null) {
|
|
879
|
+
const result = {};
|
|
880
|
+
for (const [key, item] of Object.entries(value)) result[key] = sanitizeValue(item);
|
|
881
|
+
return result;
|
|
1480
882
|
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
883
|
+
return value;
|
|
884
|
+
}
|
|
885
|
+
function sanitizeRecord(value) {
|
|
886
|
+
return sanitizeValue(value);
|
|
1484
887
|
}
|
|
1485
|
-
function
|
|
888
|
+
function toolResultOutput(toolCall) {
|
|
889
|
+
const text = toolCall.result.content.filter((content) => content.type === "text").map((content) => sanitizeSurrogates(content.text)).join("\n");
|
|
890
|
+
const images = toolCall.result.content.filter((content) => content.type === "image");
|
|
891
|
+
if (toolCall.result.isError) return {
|
|
892
|
+
type: "error-text",
|
|
893
|
+
value: text || "Tool returned an error"
|
|
894
|
+
};
|
|
895
|
+
if (images.length === 0) return {
|
|
896
|
+
type: "text",
|
|
897
|
+
value: text
|
|
898
|
+
};
|
|
1486
899
|
return {
|
|
1487
|
-
type: "
|
|
1488
|
-
|
|
1489
|
-
content: convertContentBlocks([{
|
|
900
|
+
type: "content",
|
|
901
|
+
value: [...text.length > 0 ? [{
|
|
1490
902
|
type: "text",
|
|
1491
|
-
text
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
}]
|
|
1497
|
-
is_error: true
|
|
903
|
+
text
|
|
904
|
+
}] : [], ...images.map((image) => ({
|
|
905
|
+
type: "image-data",
|
|
906
|
+
data: image.data,
|
|
907
|
+
mediaType: image.mimeType
|
|
908
|
+
}))]
|
|
1498
909
|
};
|
|
1499
910
|
}
|
|
1500
|
-
function
|
|
1501
|
-
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
type: "image",
|
|
1512
|
-
source: {
|
|
1513
|
-
type: "base64",
|
|
1514
|
-
media_type: item.mimeType,
|
|
1515
|
-
data: item.data
|
|
1516
|
-
}
|
|
1517
|
-
};
|
|
1518
|
-
});
|
|
1519
|
-
let filteredBlocks = !model.input.includes("image") ? blocks.filter((b) => b.type !== "image") : blocks;
|
|
1520
|
-
filteredBlocks = filteredBlocks.filter((b) => b.type === "text" ? b.text.trim().length > 0 : true);
|
|
1521
|
-
if (filteredBlocks.length === 0) continue;
|
|
1522
|
-
params.push({
|
|
1523
|
-
role: "user",
|
|
1524
|
-
content: filteredBlocks
|
|
911
|
+
function assistantMessages(message) {
|
|
912
|
+
if (message.stopReason === "error" || message.stopReason === "aborted") return [];
|
|
913
|
+
const assistantContent = [];
|
|
914
|
+
const toolResults = [];
|
|
915
|
+
for (const part of message.parts) {
|
|
916
|
+
if (part.type === "text") {
|
|
917
|
+
const text = sanitizeSurrogates(part.text);
|
|
918
|
+
if (text.trim().length === 0) continue;
|
|
919
|
+
assistantContent.push({
|
|
920
|
+
type: "text",
|
|
921
|
+
text
|
|
1525
922
|
});
|
|
1526
923
|
continue;
|
|
1527
924
|
}
|
|
1528
|
-
if (
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
} else if (block.type === "thinking") {
|
|
1539
|
-
if (block.thinking.trim().length === 0) continue;
|
|
1540
|
-
if (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) assistantBlocks.push({
|
|
1541
|
-
type: "text",
|
|
1542
|
-
text: sanitizeSurrogates(block.thinking)
|
|
1543
|
-
});
|
|
1544
|
-
else assistantBlocks.push({
|
|
1545
|
-
type: "thinking",
|
|
1546
|
-
thinking: sanitizeSurrogates(block.thinking),
|
|
1547
|
-
signature: block.thinkingSignature
|
|
1548
|
-
});
|
|
1549
|
-
} else if (block.type === "toolCall") {
|
|
1550
|
-
assistantBlocks.push({
|
|
1551
|
-
type: "tool_use",
|
|
1552
|
-
id: block.callID,
|
|
1553
|
-
name: isOAuthToken ? toClaudeCodeName(block.name) : block.name,
|
|
1554
|
-
input: block.arguments ?? {}
|
|
1555
|
-
});
|
|
1556
|
-
if (block.status === "pending" || block.status === "running") toolResults.push(buildSyntheticToolResult$1(block));
|
|
1557
|
-
else toolResults.push({
|
|
1558
|
-
type: "tool_result",
|
|
1559
|
-
tool_use_id: block.callID,
|
|
1560
|
-
content: convertContentBlocks(block.result.content),
|
|
1561
|
-
is_error: block.result.isError
|
|
1562
|
-
});
|
|
925
|
+
if (part.type === "thinking") {
|
|
926
|
+
const thinking = sanitizeSurrogates(part.thinking);
|
|
927
|
+
if (thinking.trim().length === 0) continue;
|
|
928
|
+
const reasoning = {
|
|
929
|
+
type: "reasoning",
|
|
930
|
+
text: thinking
|
|
931
|
+
};
|
|
932
|
+
if (part.thinkingSignature) reasoning.providerOptions = { anthropic: { signature: part.thinkingSignature } };
|
|
933
|
+
assistantContent.push(reasoning);
|
|
934
|
+
continue;
|
|
1563
935
|
}
|
|
1564
|
-
if (
|
|
1565
|
-
|
|
1566
|
-
|
|
936
|
+
if (part.type !== "toolCall") continue;
|
|
937
|
+
assistantContent.push({
|
|
938
|
+
type: "tool-call",
|
|
939
|
+
toolCallId: part.callID,
|
|
940
|
+
toolName: part.name,
|
|
941
|
+
input: sanitizeRecord(part.arguments ?? {})
|
|
1567
942
|
});
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
943
|
+
const terminal = part.status === "pending" || part.status === "running" ? void 0 : part;
|
|
944
|
+
toolResults.push({
|
|
945
|
+
type: "tool-result",
|
|
946
|
+
toolCallId: part.callID,
|
|
947
|
+
toolName: part.name,
|
|
948
|
+
output: terminal ? toolResultOutput(terminal) : {
|
|
949
|
+
type: "error-text",
|
|
950
|
+
value: "No result provided"
|
|
951
|
+
}
|
|
1571
952
|
});
|
|
1572
953
|
}
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
954
|
+
const result = [];
|
|
955
|
+
if (assistantContent.length > 0) result.push({
|
|
956
|
+
role: "assistant",
|
|
957
|
+
content: assistantContent
|
|
958
|
+
});
|
|
959
|
+
if (toolResults.length > 0) result.push({
|
|
960
|
+
role: "tool",
|
|
961
|
+
content: toolResults
|
|
962
|
+
});
|
|
963
|
+
return result;
|
|
964
|
+
}
|
|
965
|
+
function convertMessages(context, model) {
|
|
966
|
+
const messages = [];
|
|
967
|
+
const transformedMessages = Message.transformMessages(context.messages, model);
|
|
968
|
+
for (const msg of transformedMessages) {
|
|
969
|
+
if (msg.role === "user") {
|
|
970
|
+
messages.push(...userContent(msg.parts, model.input.includes("image")));
|
|
971
|
+
continue;
|
|
1584
972
|
}
|
|
973
|
+
messages.push(...assistantMessages(msg));
|
|
1585
974
|
}
|
|
1586
|
-
return
|
|
975
|
+
return messages;
|
|
1587
976
|
}
|
|
1588
|
-
function convertTools
|
|
1589
|
-
if (!tools) return
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
type: "object",
|
|
1597
|
-
properties: jsonSchema.properties || {},
|
|
1598
|
-
required: jsonSchema.required || []
|
|
1599
|
-
}
|
|
1600
|
-
};
|
|
1601
|
-
});
|
|
977
|
+
function convertTools(tools) {
|
|
978
|
+
if (!tools || tools.length === 0) return;
|
|
979
|
+
const result = {};
|
|
980
|
+
for (const tool of tools) result[tool.name] = {
|
|
981
|
+
description: tool.description,
|
|
982
|
+
inputSchema: jsonSchema(tool.parameters)
|
|
983
|
+
};
|
|
984
|
+
return result;
|
|
1602
985
|
}
|
|
1603
|
-
function
|
|
986
|
+
function mapFinishReason(reason) {
|
|
1604
987
|
switch (reason) {
|
|
1605
|
-
case "
|
|
1606
|
-
case "
|
|
1607
|
-
case "
|
|
1608
|
-
case "
|
|
1609
|
-
case "
|
|
1610
|
-
|
|
1611
|
-
case "sensitive": return "error";
|
|
1612
|
-
default: throw new Error("Unhandled Anthropic stop reason");
|
|
988
|
+
case "length": return "length";
|
|
989
|
+
case "tool-calls": return "toolUse";
|
|
990
|
+
case "content-filter":
|
|
991
|
+
case "error":
|
|
992
|
+
case "other": return "error";
|
|
993
|
+
default: return "stop";
|
|
1613
994
|
}
|
|
1614
995
|
}
|
|
1615
|
-
function
|
|
1616
|
-
const
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
996
|
+
function mapUsage(usage, model) {
|
|
997
|
+
const cacheRead = usage?.inputTokenDetails?.cacheReadTokens ?? usage?.cachedInputTokens ?? 0;
|
|
998
|
+
const cacheWrite = usage?.inputTokenDetails?.cacheWriteTokens ?? 0;
|
|
999
|
+
const input = usage?.inputTokenDetails?.noCacheTokens ?? Math.max((usage?.inputTokens ?? 0) - cacheRead - cacheWrite, 0);
|
|
1000
|
+
const output = usage?.outputTokens ?? 0;
|
|
1001
|
+
const result = {
|
|
1002
|
+
input,
|
|
1003
|
+
output,
|
|
1004
|
+
cacheRead,
|
|
1005
|
+
cacheWrite,
|
|
1006
|
+
totalTokens: usage?.totalTokens ?? input + cacheRead + cacheWrite + output,
|
|
1007
|
+
cost: {
|
|
1008
|
+
input: 0,
|
|
1009
|
+
output: 0,
|
|
1010
|
+
cacheRead: 0,
|
|
1011
|
+
cacheWrite: 0,
|
|
1012
|
+
total: 0
|
|
1013
|
+
}
|
|
1622
1014
|
};
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
...cacheControl ? { cache_control: cacheControl } : {}
|
|
1638
|
-
}];
|
|
1639
|
-
if (options?.temperature !== void 0 && !options?.thinkingEnabled) params.temperature = options.temperature;
|
|
1640
|
-
if (context.tools) params.tools = convertTools$1(context.tools, isOAuthToken);
|
|
1641
|
-
if (options?.thinkingEnabled && model.reasoning) params.thinking = {
|
|
1642
|
-
type: "enabled",
|
|
1643
|
-
budget_tokens: options.thinkingBudgetTokens || 1024
|
|
1015
|
+
Model.calculateCost(model, result);
|
|
1016
|
+
return result;
|
|
1017
|
+
}
|
|
1018
|
+
function toolCallFromPart(part) {
|
|
1019
|
+
return {
|
|
1020
|
+
type: "toolCall",
|
|
1021
|
+
callID: part.toolCallId,
|
|
1022
|
+
name: part.toolName,
|
|
1023
|
+
arguments: typeof part.input === "object" && part.input !== null ? part.input : {},
|
|
1024
|
+
status: "pending",
|
|
1025
|
+
time: {
|
|
1026
|
+
start: Date.now(),
|
|
1027
|
+
end: Date.now()
|
|
1028
|
+
}
|
|
1644
1029
|
};
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1030
|
+
}
|
|
1031
|
+
function updateToolCallFromInput(block, partialJson) {
|
|
1032
|
+
block.partialJson = partialJson;
|
|
1033
|
+
block.arguments = parseStreamingJson(partialJson);
|
|
1034
|
+
block.time.end = Date.now();
|
|
1035
|
+
}
|
|
1036
|
+
//#endregion
|
|
1037
|
+
//#region src/llm/stream.ts
|
|
1038
|
+
function providerOptionsKey(model) {
|
|
1039
|
+
return model.providerOptionsKey ?? model.protocol;
|
|
1040
|
+
}
|
|
1041
|
+
function mergeProviderOptions(...sources) {
|
|
1042
|
+
const result = {};
|
|
1043
|
+
for (const source of sources) {
|
|
1044
|
+
if (!source) continue;
|
|
1045
|
+
for (const [key, value] of Object.entries(source)) {
|
|
1046
|
+
if (!value) continue;
|
|
1047
|
+
result[key] = {
|
|
1048
|
+
...result[key],
|
|
1049
|
+
...value
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1648
1052
|
}
|
|
1649
|
-
|
|
1650
|
-
return params;
|
|
1053
|
+
return result;
|
|
1651
1054
|
}
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1055
|
+
function configuredCacheRetention(options) {
|
|
1056
|
+
if (options.cacheRetention) return options.cacheRetention;
|
|
1057
|
+
const env = process.env.CODEWORK_CACHE_RETENTION;
|
|
1058
|
+
if (env === "none" || env === "short" || env === "long") return env;
|
|
1059
|
+
}
|
|
1060
|
+
function cacheProviderOptions(model, options) {
|
|
1061
|
+
const retention = configuredCacheRetention(options);
|
|
1062
|
+
const key = providerOptionsKey(model);
|
|
1063
|
+
if (retention === "none") return {};
|
|
1064
|
+
if (key === "openai") {
|
|
1065
|
+
const openai = {};
|
|
1066
|
+
if (options.sessionId) openai.promptCacheKey = options.sessionId;
|
|
1067
|
+
if (retention === "short") openai.promptCacheRetention = "in_memory";
|
|
1068
|
+
if (retention === "long") openai.promptCacheRetention = "24h";
|
|
1069
|
+
return Object.keys(openai).length > 0 ? { [key]: openai } : {};
|
|
1070
|
+
}
|
|
1071
|
+
if ((key === "anthropic" || key === "google-vertex-anthropic") && retention) return { [key]: { cacheControl: {
|
|
1072
|
+
type: "ephemeral",
|
|
1073
|
+
...retention === "long" ? { ttl: "1h" } : {}
|
|
1074
|
+
} } };
|
|
1075
|
+
return {};
|
|
1076
|
+
}
|
|
1077
|
+
const DEFAULT_THINKING_BUDGET_FRACTIONS = {
|
|
1078
|
+
minimal: .05,
|
|
1079
|
+
low: .1,
|
|
1080
|
+
medium: .25,
|
|
1081
|
+
high: .5,
|
|
1082
|
+
xhigh: .8
|
|
1083
|
+
};
|
|
1084
|
+
const MIN_THINKING_BUDGET = 1024;
|
|
1085
|
+
function resolveThinkingBudget(model, options, level) {
|
|
1086
|
+
const explicit = options.thinkingBudgets?.[level];
|
|
1087
|
+
if (explicit !== void 0) return explicit;
|
|
1088
|
+
const key = providerOptionsKey(model);
|
|
1089
|
+
if (key === "anthropic" || key === "google-vertex-anthropic") {
|
|
1090
|
+
const fraction = DEFAULT_THINKING_BUDGET_FRACTIONS[level];
|
|
1091
|
+
return Math.max(Math.floor(model.maxTokens * fraction), MIN_THINKING_BUDGET);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
function reasoningProviderOptions(model, options) {
|
|
1095
|
+
const requestedLevel = options.reasoning;
|
|
1096
|
+
if (!requestedLevel) return {};
|
|
1097
|
+
const level = Model.clampThinkingLevel(model, requestedLevel);
|
|
1098
|
+
if (level === "off") return {};
|
|
1099
|
+
const mapped = model.thinkingLevelMap?.[level] ?? level;
|
|
1100
|
+
if (!mapped) return {};
|
|
1101
|
+
const key = providerOptionsKey(model);
|
|
1102
|
+
const budget = resolveThinkingBudget(model, options, level);
|
|
1103
|
+
if (key === "openai" || key === "xai") return { [key]: { reasoningEffort: mapped } };
|
|
1104
|
+
if (key === "openrouter") return { [key]: { reasoning: { effort: mapped === "off" ? "none" : mapped } } };
|
|
1105
|
+
if (key === "google" || key === "google-vertex") {
|
|
1106
|
+
const thinkingLevel = mapped === "xhigh" ? "high" : mapped;
|
|
1107
|
+
return { [key]: { thinkingConfig: {
|
|
1108
|
+
thinkingLevel,
|
|
1109
|
+
includeThoughts: true,
|
|
1110
|
+
...budget !== void 0 ? { thinkingBudget: budget } : {}
|
|
1111
|
+
} } };
|
|
1112
|
+
}
|
|
1113
|
+
if (key === "anthropic" || key === "google-vertex-anthropic") return { [key]: { thinking: {
|
|
1114
|
+
type: "enabled",
|
|
1115
|
+
budgetTokens: budget ?? MIN_THINKING_BUDGET
|
|
1116
|
+
} } };
|
|
1117
|
+
return {};
|
|
1118
|
+
}
|
|
1119
|
+
function resolveProviderOptions(model, options) {
|
|
1120
|
+
return mergeProviderOptions(model.providerOptions, cacheProviderOptions(model, options), reasoningProviderOptions(model, options), options.providerOptions);
|
|
1121
|
+
}
|
|
1122
|
+
function partIndex(output, block) {
|
|
1123
|
+
return output.parts.indexOf(block);
|
|
1124
|
+
}
|
|
1125
|
+
function ensureTextBlock(output, id, stream) {
|
|
1126
|
+
const existing = output.parts.find((part) => part.type === "text" && part.streamId === id);
|
|
1127
|
+
if (existing) return existing;
|
|
1128
|
+
const block = {
|
|
1129
|
+
type: "text",
|
|
1130
|
+
text: "",
|
|
1131
|
+
streamId: id
|
|
1132
|
+
};
|
|
1133
|
+
output.parts.push(block);
|
|
1134
|
+
stream.push({
|
|
1135
|
+
type: "text.start",
|
|
1136
|
+
partIndex: partIndex(output, block),
|
|
1137
|
+
partial: output
|
|
1138
|
+
});
|
|
1139
|
+
return block;
|
|
1140
|
+
}
|
|
1141
|
+
function ensureThinkingBlock(output, id, stream) {
|
|
1142
|
+
const existing = output.parts.find((part) => part.type === "thinking" && part.streamId === id);
|
|
1143
|
+
if (existing) return existing;
|
|
1144
|
+
const block = {
|
|
1145
|
+
type: "thinking",
|
|
1146
|
+
thinking: "",
|
|
1147
|
+
streamId: id
|
|
1148
|
+
};
|
|
1149
|
+
output.parts.push(block);
|
|
1150
|
+
stream.push({
|
|
1151
|
+
type: "thinking.start",
|
|
1152
|
+
partIndex: partIndex(output, block),
|
|
1153
|
+
partial: output
|
|
1154
|
+
});
|
|
1155
|
+
return block;
|
|
1156
|
+
}
|
|
1157
|
+
function ensureToolCallBlock(output, id, name, stream, emitStart) {
|
|
1158
|
+
const existing = output.parts.find((part) => part.type === "toolCall" && part.callID === id);
|
|
1159
|
+
if (existing) {
|
|
1160
|
+
if (!existing.name && name) existing.name = name;
|
|
1161
|
+
return existing;
|
|
1162
|
+
}
|
|
1163
|
+
const block = {
|
|
1164
|
+
type: "toolCall",
|
|
1165
|
+
callID: id,
|
|
1166
|
+
name,
|
|
1167
|
+
arguments: {},
|
|
1168
|
+
status: "pending",
|
|
1169
|
+
time: {
|
|
1170
|
+
start: Date.now(),
|
|
1171
|
+
end: Date.now()
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
output.parts.push(block);
|
|
1175
|
+
if (emitStart) stream.push({
|
|
1176
|
+
type: "toolcall.start",
|
|
1177
|
+
partIndex: partIndex(output, block),
|
|
1178
|
+
partial: output
|
|
1179
|
+
});
|
|
1180
|
+
return block;
|
|
1181
|
+
}
|
|
1182
|
+
function finishTextBlock(output, id, stream) {
|
|
1183
|
+
const block = output.parts.find((part) => part.type === "text" && part.streamId === id);
|
|
1184
|
+
if (!block) return;
|
|
1185
|
+
const index = partIndex(output, block);
|
|
1186
|
+
delete block.streamId;
|
|
1187
|
+
stream.push({
|
|
1188
|
+
type: "text.end",
|
|
1189
|
+
partIndex: index,
|
|
1190
|
+
content: block.text,
|
|
1191
|
+
partial: output
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
function finishThinkingBlock(output, id, stream) {
|
|
1195
|
+
const block = output.parts.find((part) => part.type === "thinking" && part.streamId === id);
|
|
1196
|
+
if (!block) return;
|
|
1197
|
+
const index = partIndex(output, block);
|
|
1198
|
+
delete block.streamId;
|
|
1199
|
+
stream.push({
|
|
1200
|
+
type: "thinking.end",
|
|
1201
|
+
partIndex: index,
|
|
1202
|
+
content: block.thinking,
|
|
1203
|
+
partial: output
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
function finishToolInput(output, id, stream) {
|
|
1207
|
+
const block = output.parts.find((part) => part.type === "toolCall" && part.callID === id);
|
|
1208
|
+
if (!block) return;
|
|
1209
|
+
const index = partIndex(output, block);
|
|
1210
|
+
delete block.partialJson;
|
|
1211
|
+
stream.push({
|
|
1212
|
+
type: "toolcall.end",
|
|
1213
|
+
partIndex: index,
|
|
1214
|
+
toolCall: block,
|
|
1215
|
+
partial: output
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
function finalizeToolCall(output, part, stream) {
|
|
1219
|
+
const existing = output.parts.find((item) => item.type === "toolCall" && item.callID === part.toolCallId);
|
|
1220
|
+
const block = existing ?? toolCallFromPart(part);
|
|
1221
|
+
block.callID = part.toolCallId;
|
|
1222
|
+
block.name = part.toolName;
|
|
1223
|
+
block.arguments = typeof part.input === "object" && part.input !== null ? part.input : {};
|
|
1224
|
+
block.time.end = Date.now();
|
|
1225
|
+
delete block.partialJson;
|
|
1226
|
+
if (!existing) output.parts.push(block);
|
|
1227
|
+
const index = partIndex(output, block);
|
|
1228
|
+
stream.push({
|
|
1229
|
+
type: "toolcall.final",
|
|
1230
|
+
partIndex: index,
|
|
1231
|
+
toolCall: block,
|
|
1232
|
+
partial: output
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
function handlePart(part, output, model, stream) {
|
|
1236
|
+
switch (part.type) {
|
|
1237
|
+
case "text-start":
|
|
1238
|
+
ensureTextBlock(output, part.id, stream);
|
|
1239
|
+
break;
|
|
1240
|
+
case "text-delta": {
|
|
1241
|
+
const block = ensureTextBlock(output, part.id, stream);
|
|
1242
|
+
block.text += part.text;
|
|
1701
1243
|
stream.push({
|
|
1702
|
-
type: "
|
|
1244
|
+
type: "text.delta",
|
|
1245
|
+
partIndex: partIndex(output, block),
|
|
1246
|
+
delta: part.text,
|
|
1703
1247
|
partial: output
|
|
1704
1248
|
});
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
text: "",
|
|
1719
|
-
index: event.index
|
|
1720
|
-
};
|
|
1721
|
-
output.parts.push(block);
|
|
1722
|
-
stream.push({
|
|
1723
|
-
type: "text.start",
|
|
1724
|
-
partIndex: output.parts.length - 1,
|
|
1725
|
-
partial: output
|
|
1726
|
-
});
|
|
1727
|
-
} else if (event.content_block.type === "thinking") {
|
|
1728
|
-
const block = {
|
|
1729
|
-
type: "thinking",
|
|
1730
|
-
thinking: "",
|
|
1731
|
-
thinkingSignature: "",
|
|
1732
|
-
index: event.index
|
|
1733
|
-
};
|
|
1734
|
-
output.parts.push(block);
|
|
1735
|
-
stream.push({
|
|
1736
|
-
type: "thinking.start",
|
|
1737
|
-
partIndex: output.parts.length - 1,
|
|
1738
|
-
partial: output
|
|
1739
|
-
});
|
|
1740
|
-
} else if (event.content_block.type === "redacted_thinking") {
|
|
1741
|
-
const block = {
|
|
1742
|
-
type: "thinking",
|
|
1743
|
-
thinking: "[Reasoning redacted]",
|
|
1744
|
-
thinkingSignature: event.content_block.data,
|
|
1745
|
-
redacted: true,
|
|
1746
|
-
index: event.index
|
|
1747
|
-
};
|
|
1748
|
-
output.parts.push(block);
|
|
1749
|
-
stream.push({
|
|
1750
|
-
type: "thinking.start",
|
|
1751
|
-
partIndex: output.parts.length - 1,
|
|
1752
|
-
partial: output
|
|
1753
|
-
});
|
|
1754
|
-
} else if (event.content_block.type === "tool_use") {
|
|
1755
|
-
const block = {
|
|
1756
|
-
type: "toolCall",
|
|
1757
|
-
callID: event.content_block.id,
|
|
1758
|
-
name: isOAuthToken ? fromClaudeCodeName(event.content_block.name, context.tools) : event.content_block.name,
|
|
1759
|
-
arguments: event.content_block.input ?? {},
|
|
1760
|
-
partialJson: "",
|
|
1761
|
-
status: "pending",
|
|
1762
|
-
time: {
|
|
1763
|
-
start: Date.now(),
|
|
1764
|
-
end: Date.now()
|
|
1765
|
-
},
|
|
1766
|
-
index: event.index
|
|
1767
|
-
};
|
|
1768
|
-
output.parts.push(block);
|
|
1769
|
-
stream.push({
|
|
1770
|
-
type: "toolcall.start",
|
|
1771
|
-
partIndex: output.parts.length - 1,
|
|
1772
|
-
partial: output
|
|
1773
|
-
});
|
|
1774
|
-
}
|
|
1775
|
-
} else if (event.type === "content_block_delta") {
|
|
1776
|
-
const partIndex = blocks.findIndex((b) => b.index === event.index);
|
|
1777
|
-
const block = blocks[partIndex];
|
|
1778
|
-
if (!block) continue;
|
|
1779
|
-
if (event.delta.type === "text_delta" && block.type === "text") {
|
|
1780
|
-
block.text += event.delta.text;
|
|
1781
|
-
stream.push({
|
|
1782
|
-
type: "text.delta",
|
|
1783
|
-
partIndex,
|
|
1784
|
-
delta: event.delta.text,
|
|
1785
|
-
partial: output
|
|
1786
|
-
});
|
|
1787
|
-
} else if (event.delta.type === "thinking_delta" && block.type === "thinking") {
|
|
1788
|
-
block.thinking += event.delta.thinking;
|
|
1789
|
-
stream.push({
|
|
1790
|
-
type: "thinking.delta",
|
|
1791
|
-
partIndex,
|
|
1792
|
-
delta: event.delta.thinking,
|
|
1793
|
-
partial: output
|
|
1794
|
-
});
|
|
1795
|
-
} else if (event.delta.type === "input_json_delta" && block.type === "toolCall") {
|
|
1796
|
-
block.partialJson += event.delta.partial_json;
|
|
1797
|
-
block.arguments = parseStreamingJson(block.partialJson);
|
|
1798
|
-
stream.push({
|
|
1799
|
-
type: "toolcall.delta",
|
|
1800
|
-
partIndex,
|
|
1801
|
-
delta: event.delta.partial_json,
|
|
1802
|
-
partial: output
|
|
1803
|
-
});
|
|
1804
|
-
} else if (event.delta.type === "signature_delta" && block.type === "thinking") {
|
|
1805
|
-
block.thinkingSignature = block.thinkingSignature || "";
|
|
1806
|
-
block.thinkingSignature += event.delta.signature;
|
|
1807
|
-
}
|
|
1808
|
-
} else if (event.type === "content_block_stop") {
|
|
1809
|
-
const partIndex = blocks.findIndex((b) => b.index === event.index);
|
|
1810
|
-
const block = blocks[partIndex];
|
|
1811
|
-
if (block) {
|
|
1812
|
-
delete block.index;
|
|
1813
|
-
if (block.type === "text") stream.push({
|
|
1814
|
-
type: "text.end",
|
|
1815
|
-
partIndex,
|
|
1816
|
-
content: block.text,
|
|
1817
|
-
partial: output
|
|
1818
|
-
});
|
|
1819
|
-
else if (block.type === "thinking") stream.push({
|
|
1820
|
-
type: "thinking.end",
|
|
1821
|
-
partIndex,
|
|
1822
|
-
content: block.thinking,
|
|
1823
|
-
partial: output
|
|
1824
|
-
});
|
|
1825
|
-
else if (block.type === "toolCall") {
|
|
1826
|
-
block.arguments = parseStreamingJson(block.partialJson);
|
|
1827
|
-
delete block.partialJson;
|
|
1828
|
-
stream.push({
|
|
1829
|
-
type: "toolcall.end",
|
|
1830
|
-
partIndex,
|
|
1831
|
-
toolCall: block,
|
|
1832
|
-
partial: output
|
|
1833
|
-
});
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
} else if (event.type === "message_delta") {
|
|
1837
|
-
if (event.delta.stop_reason) output.stopReason = mapStopReason$1(event.delta.stop_reason);
|
|
1838
|
-
if (event.usage.input_tokens != null) output.usage.input = event.usage.input_tokens;
|
|
1839
|
-
if (event.usage.output_tokens != null) output.usage.output = event.usage.output_tokens;
|
|
1840
|
-
if (event.usage.cache_read_input_tokens != null) output.usage.cacheRead = event.usage.cache_read_input_tokens;
|
|
1841
|
-
if (event.usage.cache_creation_input_tokens != null) output.usage.cacheWrite = event.usage.cache_creation_input_tokens;
|
|
1842
|
-
output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
1843
|
-
Model.calculateCost(model, output.usage);
|
|
1844
|
-
}
|
|
1845
|
-
if (options?.signal?.aborted) throw new Error("Request was aborted");
|
|
1846
|
-
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
|
|
1847
|
-
output.time.completed = Date.now();
|
|
1249
|
+
break;
|
|
1250
|
+
}
|
|
1251
|
+
case "text-end":
|
|
1252
|
+
finishTextBlock(output, part.id, stream);
|
|
1253
|
+
break;
|
|
1254
|
+
case "reasoning-start":
|
|
1255
|
+
ensureThinkingBlock(output, part.id, stream);
|
|
1256
|
+
break;
|
|
1257
|
+
case "reasoning-delta": {
|
|
1258
|
+
const block = ensureThinkingBlock(output, part.id, stream);
|
|
1259
|
+
block.thinking += part.text;
|
|
1260
|
+
const sig = (part.providerMetadata?.anthropic)?.signature ?? (part.providerMetadata?.["google-vertex-anthropic"])?.signature;
|
|
1261
|
+
if (typeof sig === "string") block.thinkingSignature = sig;
|
|
1848
1262
|
stream.push({
|
|
1849
|
-
type: "
|
|
1850
|
-
|
|
1851
|
-
|
|
1263
|
+
type: "thinking.delta",
|
|
1264
|
+
partIndex: partIndex(output, block),
|
|
1265
|
+
delta: part.text,
|
|
1266
|
+
partial: output
|
|
1852
1267
|
});
|
|
1853
|
-
|
|
1854
|
-
}
|
|
1855
|
-
|
|
1856
|
-
output.
|
|
1857
|
-
|
|
1858
|
-
|
|
1268
|
+
break;
|
|
1269
|
+
}
|
|
1270
|
+
case "reasoning-end":
|
|
1271
|
+
finishThinkingBlock(output, part.id, stream);
|
|
1272
|
+
break;
|
|
1273
|
+
case "tool-input-start":
|
|
1274
|
+
ensureToolCallBlock(output, part.id, part.toolName, stream, true);
|
|
1275
|
+
break;
|
|
1276
|
+
case "tool-input-delta": {
|
|
1277
|
+
const block = ensureToolCallBlock(output, part.id, "", stream, true);
|
|
1278
|
+
updateToolCallFromInput(block, (block.partialJson ?? "") + part.delta);
|
|
1859
1279
|
stream.push({
|
|
1860
|
-
type: "
|
|
1861
|
-
|
|
1862
|
-
|
|
1280
|
+
type: "toolcall.delta",
|
|
1281
|
+
partIndex: partIndex(output, block),
|
|
1282
|
+
delta: part.delta,
|
|
1283
|
+
partial: output
|
|
1863
1284
|
});
|
|
1864
|
-
|
|
1285
|
+
break;
|
|
1865
1286
|
}
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
stream: streamAnthropic,
|
|
1888
|
-
streamSimple: streamSimpleAnthropic
|
|
1889
|
-
};
|
|
1890
|
-
//#endregion
|
|
1891
|
-
//#region src/provider/providers/github/github.ts
|
|
1892
|
-
function inferCopilotInitiator(messages) {
|
|
1893
|
-
const last = messages[messages.length - 1];
|
|
1894
|
-
return last && last.role !== "user" ? "agent" : "user";
|
|
1895
|
-
}
|
|
1896
|
-
function hasCopilotVisionInput(messages) {
|
|
1897
|
-
return messages.some((msg) => {
|
|
1898
|
-
if (msg.role === "user") return msg.parts.some((c) => c.type === "image");
|
|
1899
|
-
return false;
|
|
1900
|
-
});
|
|
1901
|
-
}
|
|
1902
|
-
function buildCopilotDynamicHeaders(params) {
|
|
1903
|
-
const headers = {
|
|
1904
|
-
"X-Initiator": inferCopilotInitiator(params.messages),
|
|
1905
|
-
"Openai-Intent": "conversation-edits"
|
|
1906
|
-
};
|
|
1907
|
-
if (params.hasImages) headers["Copilot-Vision-Request"] = "true";
|
|
1908
|
-
return headers;
|
|
1909
|
-
}
|
|
1910
|
-
//#endregion
|
|
1911
|
-
//#region src/provider/providers/openai/completions.ts
|
|
1912
|
-
function hasToolHistory(messages) {
|
|
1913
|
-
for (const msg of messages) {
|
|
1914
|
-
if (msg.role !== "assistant") continue;
|
|
1915
|
-
if (msg.parts.some((block) => block.type === "toolCall")) return true;
|
|
1287
|
+
case "tool-input-end":
|
|
1288
|
+
finishToolInput(output, part.id, stream);
|
|
1289
|
+
break;
|
|
1290
|
+
case "tool-call":
|
|
1291
|
+
finalizeToolCall(output, part, stream);
|
|
1292
|
+
break;
|
|
1293
|
+
case "finish-step":
|
|
1294
|
+
output.responseId ||= part.response.id;
|
|
1295
|
+
if (part.response.modelId && part.response.modelId !== model.id) output.responseModel ||= part.response.modelId;
|
|
1296
|
+
output.usage = mapUsage(part.usage, model);
|
|
1297
|
+
output.stopReason = mapFinishReason(part.finishReason);
|
|
1298
|
+
break;
|
|
1299
|
+
case "finish":
|
|
1300
|
+
output.usage = mapUsage(part.totalUsage, model);
|
|
1301
|
+
output.stopReason = mapFinishReason(part.finishReason);
|
|
1302
|
+
break;
|
|
1303
|
+
case "abort":
|
|
1304
|
+
output.stopReason = "aborted";
|
|
1305
|
+
output.errorMessage = part.reason;
|
|
1306
|
+
break;
|
|
1307
|
+
case "error": throw part.error instanceof Error ? part.error : new Error(formatThrownError(part.error));
|
|
1916
1308
|
}
|
|
1917
|
-
return false;
|
|
1918
|
-
}
|
|
1919
|
-
function buildSyntheticToolResult(block, compat) {
|
|
1920
|
-
const message = {
|
|
1921
|
-
role: "tool",
|
|
1922
|
-
content: [
|
|
1923
|
-
"<result>",
|
|
1924
|
-
"No Result Provided",
|
|
1925
|
-
"</result>"
|
|
1926
|
-
].join("\n"),
|
|
1927
|
-
tool_call_id: block.callID
|
|
1928
|
-
};
|
|
1929
|
-
if (compat.requiresToolResultName) message.name = block.name;
|
|
1930
|
-
return message;
|
|
1931
1309
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
1310
|
+
/**
|
|
1311
|
+
* Resolve maxOutputTokens so that (maxOutputTokens + thinkingBudget) does not exceed model.maxTokens.
|
|
1312
|
+
* Without this adjustment @ai-sdk/anthropic logs a warning and silently caps the value.
|
|
1313
|
+
*/
|
|
1314
|
+
function resolveMaxOutputTokens(model, options, providerOptions) {
|
|
1315
|
+
const maxTokens = options.maxTokens;
|
|
1316
|
+
if (maxTokens === void 0) return void 0;
|
|
1317
|
+
const key = providerOptionsKey(model);
|
|
1318
|
+
if (key === "anthropic" || key === "google-vertex-anthropic") {
|
|
1319
|
+
const budgetTokens = ((providerOptions?.[key])?.thinking)?.budgetTokens ?? 0;
|
|
1320
|
+
if (budgetTokens > 0 && maxTokens + budgetTokens > model.maxTokens) return Math.max(model.maxTokens - budgetTokens, 1);
|
|
1321
|
+
}
|
|
1322
|
+
return maxTokens;
|
|
1934
1323
|
}
|
|
1935
|
-
const
|
|
1324
|
+
const stream$1 = (model, context, options) => {
|
|
1936
1325
|
const stream = new AssistantMessageEventStream();
|
|
1326
|
+
const runtimeOptions = applyDefaultMaxTokens(model, options ?? {});
|
|
1937
1327
|
(async () => {
|
|
1938
|
-
const output =
|
|
1939
|
-
role: "assistant",
|
|
1940
|
-
parts: [],
|
|
1941
|
-
protocol: model.protocol,
|
|
1942
|
-
provider: model.provider,
|
|
1943
|
-
model: model.id,
|
|
1944
|
-
usage: {
|
|
1945
|
-
input: 0,
|
|
1946
|
-
output: 0,
|
|
1947
|
-
cacheRead: 0,
|
|
1948
|
-
cacheWrite: 0,
|
|
1949
|
-
totalTokens: 0,
|
|
1950
|
-
cost: {
|
|
1951
|
-
input: 0,
|
|
1952
|
-
output: 0,
|
|
1953
|
-
cacheRead: 0,
|
|
1954
|
-
cacheWrite: 0,
|
|
1955
|
-
total: 0
|
|
1956
|
-
}
|
|
1957
|
-
},
|
|
1958
|
-
stopReason: "stop",
|
|
1959
|
-
time: {
|
|
1960
|
-
created: Date.now(),
|
|
1961
|
-
completed: Date.now()
|
|
1962
|
-
}
|
|
1963
|
-
});
|
|
1328
|
+
const output = createAssistantMessage(model);
|
|
1964
1329
|
try {
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
const
|
|
1968
|
-
|
|
1969
|
-
const
|
|
1330
|
+
const languageModel = await resolveAISDKLanguageModel(model, runtimeOptions);
|
|
1331
|
+
const tools = convertTools(context.tools);
|
|
1332
|
+
const messages = convertMessages(context, model);
|
|
1333
|
+
const providerOptions = resolveProviderOptions(model, runtimeOptions);
|
|
1334
|
+
const activeTools = runtimeOptions.activeTools?.filter((name) => !tools || name in tools);
|
|
1335
|
+
let params = {
|
|
1336
|
+
model: languageModel,
|
|
1337
|
+
system: context.systemPrompt,
|
|
1338
|
+
messages,
|
|
1339
|
+
tools,
|
|
1340
|
+
toolChoice: runtimeOptions.toolChoice,
|
|
1341
|
+
activeTools,
|
|
1342
|
+
maxOutputTokens: resolveMaxOutputTokens(model, runtimeOptions, providerOptions),
|
|
1343
|
+
temperature: runtimeOptions.temperature,
|
|
1344
|
+
providerOptions,
|
|
1345
|
+
abortSignal: runtimeOptions.signal,
|
|
1346
|
+
timeout: runtimeOptions.timeoutMs,
|
|
1347
|
+
maxRetries: runtimeOptions.maxRetries,
|
|
1348
|
+
headers: runtimeOptions.headers
|
|
1349
|
+
};
|
|
1350
|
+
const payload = await runtimeOptions.onPayload?.(params, model);
|
|
1351
|
+
if (payload !== void 0) params = payload;
|
|
1352
|
+
const result = streamText(params);
|
|
1970
1353
|
stream.push({
|
|
1971
1354
|
type: "start",
|
|
1972
1355
|
partial: output
|
|
1973
1356
|
});
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
const activeToolCalls = /* @__PURE__ */ new Map();
|
|
1977
|
-
const finishCurrentBlock = (block) => {
|
|
1978
|
-
if (block) {
|
|
1979
|
-
const partIndex = block.index ?? blocks.indexOf(block);
|
|
1980
|
-
delete block.index;
|
|
1981
|
-
if (block.type === "text") stream.push({
|
|
1982
|
-
type: "text.end",
|
|
1983
|
-
partIndex,
|
|
1984
|
-
content: block.text,
|
|
1985
|
-
partial: output
|
|
1986
|
-
});
|
|
1987
|
-
else if (block.type === "thinking") stream.push({
|
|
1988
|
-
type: "thinking.end",
|
|
1989
|
-
partIndex,
|
|
1990
|
-
content: block.thinking,
|
|
1991
|
-
partial: output
|
|
1992
|
-
});
|
|
1993
|
-
else if (block.type === "toolCall") {
|
|
1994
|
-
if (block.streamIndex !== void 0) activeToolCalls.delete(block.streamIndex);
|
|
1995
|
-
block.arguments = parseStreamingJson(block.partialArgs);
|
|
1996
|
-
delete block.partialArgs;
|
|
1997
|
-
delete block.streamIndex;
|
|
1998
|
-
stream.push({
|
|
1999
|
-
type: "toolcall.end",
|
|
2000
|
-
partIndex,
|
|
2001
|
-
toolCall: block,
|
|
2002
|
-
partial: output
|
|
2003
|
-
});
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
};
|
|
2007
|
-
const flushActiveToolCalls = () => {
|
|
2008
|
-
for (const toolBlock of [...activeToolCalls.values()].sort((a, b) => (a.index ?? 0) - (b.index ?? 0))) finishCurrentBlock(toolBlock);
|
|
2009
|
-
};
|
|
2010
|
-
for await (const chunk of openaiStream) {
|
|
2011
|
-
if (!chunk || typeof chunk !== "object") continue;
|
|
2012
|
-
output.responseId ||= chunk.id;
|
|
2013
|
-
if (chunk.usage) output.usage = parseChunkUsage(chunk.usage, model);
|
|
2014
|
-
const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
|
|
2015
|
-
if (!choice) continue;
|
|
2016
|
-
const choiceWithUsage = choice;
|
|
2017
|
-
if (!chunk.usage && choiceWithUsage.usage) output.usage = parseChunkUsage(choiceWithUsage.usage, model);
|
|
2018
|
-
if (choice.finish_reason) {
|
|
2019
|
-
const finishReasonResult = mapStopReason(choice.finish_reason);
|
|
2020
|
-
output.stopReason = finishReasonResult.stopReason;
|
|
2021
|
-
if (finishReasonResult.errorMessage) output.errorMessage = finishReasonResult.errorMessage;
|
|
2022
|
-
}
|
|
2023
|
-
if (!choice.delta) continue;
|
|
2024
|
-
if (choice.delta.content !== null && choice.delta.content !== void 0 && choice.delta.content.length > 0) {
|
|
2025
|
-
if (activeToolCalls.size > 0) flushActiveToolCalls();
|
|
2026
|
-
if (!currentBlock || currentBlock.type !== "text") {
|
|
2027
|
-
finishCurrentBlock(currentBlock);
|
|
2028
|
-
currentBlock = {
|
|
2029
|
-
type: "text",
|
|
2030
|
-
text: "",
|
|
2031
|
-
index: output.parts.length
|
|
2032
|
-
};
|
|
2033
|
-
output.parts.push(currentBlock);
|
|
2034
|
-
stream.push({
|
|
2035
|
-
type: "text.start",
|
|
2036
|
-
partIndex: currentBlock.index,
|
|
2037
|
-
partial: output
|
|
2038
|
-
});
|
|
2039
|
-
}
|
|
2040
|
-
if (currentBlock.type === "text") {
|
|
2041
|
-
currentBlock.text += choice.delta.content;
|
|
2042
|
-
stream.push({
|
|
2043
|
-
type: "text.delta",
|
|
2044
|
-
partIndex: currentBlock.index,
|
|
2045
|
-
delta: choice.delta.content,
|
|
2046
|
-
partial: output
|
|
2047
|
-
});
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
const reasoningFields = [
|
|
2051
|
-
"reasoning_content",
|
|
2052
|
-
"reasoning",
|
|
2053
|
-
"reasoning_text"
|
|
2054
|
-
];
|
|
2055
|
-
let foundReasoningField = null;
|
|
2056
|
-
for (const field of reasoningFields) {
|
|
2057
|
-
const value = choice.delta[field];
|
|
2058
|
-
if (typeof value === "string" && value.length > 0) {
|
|
2059
|
-
foundReasoningField = field;
|
|
2060
|
-
break;
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
if (foundReasoningField) {
|
|
2064
|
-
if (activeToolCalls.size > 0) flushActiveToolCalls();
|
|
2065
|
-
if (!currentBlock || currentBlock.type !== "thinking") {
|
|
2066
|
-
finishCurrentBlock(currentBlock);
|
|
2067
|
-
currentBlock = {
|
|
2068
|
-
type: "thinking",
|
|
2069
|
-
thinking: "",
|
|
2070
|
-
thinkingSignature: foundReasoningField,
|
|
2071
|
-
index: output.parts.length
|
|
2072
|
-
};
|
|
2073
|
-
output.parts.push(currentBlock);
|
|
2074
|
-
stream.push({
|
|
2075
|
-
type: "thinking.start",
|
|
2076
|
-
partIndex: currentBlock.index,
|
|
2077
|
-
partial: output
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
if (currentBlock.type === "thinking") {
|
|
2081
|
-
const delta = choice.delta[foundReasoningField];
|
|
2082
|
-
if (typeof delta === "string") {
|
|
2083
|
-
currentBlock.thinking += delta;
|
|
2084
|
-
stream.push({
|
|
2085
|
-
type: "thinking.delta",
|
|
2086
|
-
partIndex: currentBlock.index,
|
|
2087
|
-
delta,
|
|
2088
|
-
partial: output
|
|
2089
|
-
});
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
}
|
|
2093
|
-
if (choice.delta.tool_calls) {
|
|
2094
|
-
if (currentBlock) {
|
|
2095
|
-
finishCurrentBlock(currentBlock);
|
|
2096
|
-
currentBlock = null;
|
|
2097
|
-
}
|
|
2098
|
-
for (const toolCall of choice.delta.tool_calls) {
|
|
2099
|
-
const streamIndex = toolCall.index ?? activeToolCalls.size;
|
|
2100
|
-
let toolBlock = activeToolCalls.get(streamIndex);
|
|
2101
|
-
if (!toolBlock) {
|
|
2102
|
-
toolBlock = {
|
|
2103
|
-
type: "toolCall",
|
|
2104
|
-
callID: toolCall.id || "",
|
|
2105
|
-
name: toolCall.function?.name || "",
|
|
2106
|
-
arguments: {},
|
|
2107
|
-
partialArgs: "",
|
|
2108
|
-
index: output.parts.length,
|
|
2109
|
-
streamIndex,
|
|
2110
|
-
status: "pending",
|
|
2111
|
-
time: {
|
|
2112
|
-
start: Date.now(),
|
|
2113
|
-
end: Date.now()
|
|
2114
|
-
}
|
|
2115
|
-
};
|
|
2116
|
-
activeToolCalls.set(streamIndex, toolBlock);
|
|
2117
|
-
output.parts.push(toolBlock);
|
|
2118
|
-
stream.push({
|
|
2119
|
-
type: "toolcall.start",
|
|
2120
|
-
partIndex: toolBlock.index,
|
|
2121
|
-
partial: output
|
|
2122
|
-
});
|
|
2123
|
-
}
|
|
2124
|
-
if (toolCall.id) toolBlock.callID = toolCall.id;
|
|
2125
|
-
if (toolCall.function?.name) toolBlock.name = toolCall.function.name;
|
|
2126
|
-
let delta = "";
|
|
2127
|
-
if (toolCall.function?.arguments) {
|
|
2128
|
-
delta = toolCall.function.arguments;
|
|
2129
|
-
toolBlock.partialArgs = (toolBlock.partialArgs || "") + delta;
|
|
2130
|
-
toolBlock.arguments = parseStreamingJson(toolBlock.partialArgs);
|
|
2131
|
-
}
|
|
2132
|
-
toolBlock.time.end = Date.now();
|
|
2133
|
-
stream.push({
|
|
2134
|
-
type: "toolcall.delta",
|
|
2135
|
-
partIndex: toolBlock.index,
|
|
2136
|
-
delta,
|
|
2137
|
-
partial: output
|
|
2138
|
-
});
|
|
2139
|
-
}
|
|
2140
|
-
}
|
|
2141
|
-
const reasoningDetails = choice.delta.reasoning_details;
|
|
2142
|
-
if (reasoningDetails && Array.isArray(reasoningDetails)) {
|
|
2143
|
-
for (const detail of reasoningDetails) if (detail.type === "reasoning.encrypted" && typeof detail.id === "string" && detail.data !== void 0) {
|
|
2144
|
-
const matchingToolCall = output.parts.find((block) => block.type === "toolCall" && block.callID === detail.id);
|
|
2145
|
-
if (matchingToolCall) matchingToolCall.thoughtSignature = JSON.stringify(detail);
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
finishCurrentBlock(currentBlock);
|
|
2150
|
-
flushActiveToolCalls();
|
|
2151
|
-
if (options?.signal?.aborted) throw new Error("Request was aborted");
|
|
2152
|
-
if (output.stopReason === "aborted") throw new Error("Request was aborted");
|
|
1357
|
+
for await (const part of result.fullStream) handlePart(part, output, model, stream);
|
|
1358
|
+
if (runtimeOptions.signal?.aborted || output.stopReason === "aborted") throw new Error(output.errorMessage || "Request was aborted");
|
|
2153
1359
|
if (output.stopReason === "error") throw new Error(output.errorMessage || "Provider returned an error stop reason");
|
|
2154
1360
|
output.time.completed = Date.now();
|
|
2155
1361
|
stream.push({
|
|
@@ -2160,15 +1366,13 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
2160
1366
|
stream.end();
|
|
2161
1367
|
} catch (error) {
|
|
2162
1368
|
for (const block of output.parts) {
|
|
2163
|
-
delete block.
|
|
2164
|
-
delete block.
|
|
2165
|
-
delete block.
|
|
1369
|
+
delete block.streamId;
|
|
1370
|
+
delete block.streamId;
|
|
1371
|
+
delete block.partialJson;
|
|
2166
1372
|
}
|
|
2167
1373
|
output.time.completed = Date.now();
|
|
2168
|
-
output.stopReason =
|
|
2169
|
-
output.errorMessage =
|
|
2170
|
-
const rawMetadata = error?.error?.metadata?.raw;
|
|
2171
|
-
if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
|
|
1374
|
+
output.stopReason = runtimeOptions.signal?.aborted || output.stopReason === "aborted" ? "aborted" : "error";
|
|
1375
|
+
output.errorMessage = formatThrownError(error);
|
|
2172
1376
|
stream.push({
|
|
2173
1377
|
type: "error",
|
|
2174
1378
|
reason: output.stopReason,
|
|
@@ -2179,1182 +1383,30 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
2179
1383
|
})();
|
|
2180
1384
|
return stream;
|
|
2181
1385
|
};
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
const base = Stream.buildBaseOptions(model, options, apiKey);
|
|
2186
|
-
const simpleReasoning = Model.supportsXhigh(model) ? options?.reasoning : Stream.clampReasoning(options?.reasoning);
|
|
2187
|
-
const reasoningEffort = simpleReasoning && simpleReasoning !== Stream.ThinkingLevelEnum.off ? simpleReasoning : void 0;
|
|
2188
|
-
const toolChoice = options?.toolChoice;
|
|
2189
|
-
return streamOpenAICompletions(model, context, {
|
|
2190
|
-
...base,
|
|
2191
|
-
reasoningEffort,
|
|
2192
|
-
toolChoice
|
|
2193
|
-
});
|
|
2194
|
-
};
|
|
2195
|
-
function buildParams(model, context, options) {
|
|
2196
|
-
const compat = getCompat(model);
|
|
2197
|
-
const messages = convertMessages(model, context, compat);
|
|
2198
|
-
maybeAddOpenRouterAnthropicCacheControl(model, messages);
|
|
2199
|
-
const baseUrl = resolveBaseUrl(model);
|
|
2200
|
-
const params = {
|
|
2201
|
-
model: model.id,
|
|
2202
|
-
messages,
|
|
2203
|
-
stream: true
|
|
2204
|
-
};
|
|
2205
|
-
if (compat.supportsUsageInStreaming !== false) params.stream_options = { include_usage: true };
|
|
2206
|
-
if (compat.supportsStore) params.store = false;
|
|
2207
|
-
if (options?.maxTokens) if (compat.maxTokensField === "max_tokens") params.max_tokens = options.maxTokens;
|
|
2208
|
-
else params.max_completion_tokens = options.maxTokens;
|
|
2209
|
-
if (options?.temperature !== void 0) params.temperature = options.temperature;
|
|
2210
|
-
if (context.tools) {
|
|
2211
|
-
params.tools = convertTools(context.tools, compat);
|
|
2212
|
-
if (compat.zaiToolStream) params.tool_stream = true;
|
|
2213
|
-
} else if (hasToolHistory(context.messages)) params.tools = [];
|
|
2214
|
-
if (options?.toolChoice) params.tool_choice = options.toolChoice;
|
|
2215
|
-
if ((compat.thinkingFormat === "zai" || compat.thinkingFormat === "qwen") && model.reasoning) params.enable_thinking = !!options?.reasoningEffort;
|
|
2216
|
-
else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) params.chat_template_kwargs = { enable_thinking: !!options?.reasoningEffort };
|
|
2217
|
-
else if (compat.thinkingFormat === "openrouter" && model.reasoning) {
|
|
2218
|
-
const openRouterParams = params;
|
|
2219
|
-
if (options?.reasoningEffort) openRouterParams.reasoning = { effort: mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap) };
|
|
2220
|
-
else openRouterParams.reasoning = { effort: "none" };
|
|
2221
|
-
} else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = mapReasoningEffort(options.reasoningEffort, compat.reasoningEffortMap);
|
|
2222
|
-
if (baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) params.provider = model.compat.openRouterRouting;
|
|
2223
|
-
if (baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
|
|
2224
|
-
const routing = model.compat.vercelGatewayRouting;
|
|
2225
|
-
if (routing.only || routing.order) {
|
|
2226
|
-
const gatewayOptions = {};
|
|
2227
|
-
if (routing.only) gatewayOptions.only = routing.only;
|
|
2228
|
-
if (routing.order) gatewayOptions.order = routing.order;
|
|
2229
|
-
params.providerOptions = { gateway: gatewayOptions };
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
return params;
|
|
2233
|
-
}
|
|
2234
|
-
function createClient(model, context, apiKey, optsHeaders) {
|
|
2235
|
-
const baseUrl = resolveBaseUrl(model);
|
|
2236
|
-
if (!apiKey) {
|
|
2237
|
-
if (!process.env.OPENAI_API_KEY) throw new Error("OpenAI API key is required. set OPENAI_API_KEY environment variable or pass it as an argument");
|
|
2238
|
-
apiKey = process.env.OPENAI_API_KEY;
|
|
2239
|
-
}
|
|
2240
|
-
const headers = { ...model.headers };
|
|
2241
|
-
if (model.provider.id === Provider.KnownProviderEnum.githubCopilot) {
|
|
2242
|
-
const hasImages = hasCopilotVisionInput(context.messages);
|
|
2243
|
-
const copilotHeaders = buildCopilotDynamicHeaders({
|
|
2244
|
-
messages: context.messages,
|
|
2245
|
-
hasImages
|
|
2246
|
-
});
|
|
2247
|
-
Object.assign(headers, copilotHeaders);
|
|
2248
|
-
}
|
|
2249
|
-
if (optsHeaders) Object.assign(headers, optsHeaders);
|
|
2250
|
-
return new OpenAI({
|
|
2251
|
-
apiKey,
|
|
2252
|
-
baseURL: baseUrl,
|
|
2253
|
-
dangerouslyAllowBrowser: true,
|
|
2254
|
-
defaultHeaders: headers
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
function mapReasoningEffort(effort, reasoningEffortMap) {
|
|
2258
|
-
return reasoningEffortMap[effort] ?? effort;
|
|
2259
|
-
}
|
|
2260
|
-
function maybeAddOpenRouterAnthropicCacheControl(model, messages) {
|
|
2261
|
-
if (model.provider.id !== Provider.KnownProviderEnum.openrouter || !model.id.startsWith("anthropic/")) return;
|
|
2262
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2263
|
-
const msg = messages[i];
|
|
2264
|
-
if (!msg) continue;
|
|
2265
|
-
if (msg.role !== "user" && msg.role !== "assistant") continue;
|
|
2266
|
-
const content = msg.content;
|
|
2267
|
-
if (typeof content === "string") {
|
|
2268
|
-
msg.content = [Object.assign({
|
|
2269
|
-
type: "text",
|
|
2270
|
-
text: content
|
|
2271
|
-
}, { cache_control: { type: "ephemeral" } })];
|
|
2272
|
-
return;
|
|
2273
|
-
}
|
|
2274
|
-
if (!Array.isArray(content)) continue;
|
|
2275
|
-
for (let j = content.length - 1; j >= 0; j--) {
|
|
2276
|
-
const part = content[j];
|
|
2277
|
-
if (part?.type === "text") {
|
|
2278
|
-
Object.assign(part, { cache_control: { type: "ephemeral" } });
|
|
2279
|
-
return;
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
function convertMessages(model, context, compat) {
|
|
2285
|
-
const params = [];
|
|
2286
|
-
const normalizeToolCallId = (id) => {
|
|
2287
|
-
if (id.includes("|")) return (id.split("|")[0] ?? id).replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
|
|
2288
|
-
if (model.provider.id === Provider.KnownProviderEnum.openai) return id.length > 40 ? id.slice(0, 40) : id;
|
|
2289
|
-
return id;
|
|
2290
|
-
};
|
|
2291
|
-
const transformedMessages = Message.transformMessages(context.messages, model, normalizeToolCallId);
|
|
2292
|
-
if (context.systemPrompt) {
|
|
2293
|
-
const role = model.reasoning && compat.supportsDeveloperRole ? "developer" : "system";
|
|
2294
|
-
params.push({
|
|
2295
|
-
role,
|
|
2296
|
-
content: sanitizeSurrogates(context.systemPrompt)
|
|
2297
|
-
});
|
|
2298
|
-
}
|
|
2299
|
-
let lastRole = null;
|
|
2300
|
-
for (const msg of transformedMessages) {
|
|
2301
|
-
if (compat.requiresAssistantAfterToolResult && lastRole === "tool" && msg.role === "user") {
|
|
2302
|
-
params.push({
|
|
2303
|
-
role: "assistant",
|
|
2304
|
-
content: "I have processed the tool results."
|
|
2305
|
-
});
|
|
2306
|
-
lastRole = "assistant";
|
|
2307
|
-
}
|
|
2308
|
-
if (msg.role === "user") {
|
|
2309
|
-
const content = msg.parts.flatMap((item) => {
|
|
2310
|
-
if (item.type === "text") {
|
|
2311
|
-
const text = sanitizeSurrogates(item.text);
|
|
2312
|
-
if (text.trim().length === 0) return [];
|
|
2313
|
-
return [{
|
|
2314
|
-
type: "text",
|
|
2315
|
-
text
|
|
2316
|
-
}];
|
|
2317
|
-
}
|
|
2318
|
-
if (!model.input.includes("image")) return [];
|
|
2319
|
-
return [{
|
|
2320
|
-
type: "image_url",
|
|
2321
|
-
image_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
2322
|
-
}];
|
|
2323
|
-
});
|
|
2324
|
-
if (content.length === 0) continue;
|
|
2325
|
-
params.push({
|
|
2326
|
-
role: "user",
|
|
2327
|
-
content
|
|
2328
|
-
});
|
|
2329
|
-
lastRole = "user";
|
|
2330
|
-
continue;
|
|
2331
|
-
}
|
|
2332
|
-
const assistantMsg = {
|
|
2333
|
-
role: "assistant",
|
|
2334
|
-
content: compat.requiresAssistantAfterToolResult ? "" : null
|
|
2335
|
-
};
|
|
2336
|
-
const textSegments = msg.parts.filter((block) => block.type === "text").map((block) => sanitizeSurrogates(block.text)).filter((text) => text.trim().length > 0);
|
|
2337
|
-
const nonEmptyThinkingBlocks = msg.parts.filter((block) => block.type === "thinking").filter((block) => block.thinking.trim().length > 0);
|
|
2338
|
-
if (compat.requiresThinkingAsText && nonEmptyThinkingBlocks.length > 0) textSegments.unshift(...nonEmptyThinkingBlocks.map((block) => sanitizeSurrogates(block.thinking)));
|
|
2339
|
-
else if (nonEmptyThinkingBlocks.length > 0) {
|
|
2340
|
-
const signature = nonEmptyThinkingBlocks[0]?.thinkingSignature;
|
|
2341
|
-
if (signature && signature.length > 0) assistantMsg[signature] = nonEmptyThinkingBlocks.map((block) => sanitizeSurrogates(block.thinking)).join("\n");
|
|
2342
|
-
}
|
|
2343
|
-
if (textSegments.length > 0) assistantMsg.content = textSegments.join("");
|
|
2344
|
-
const toolCalls = msg.parts.filter((block) => block.type === "toolCall");
|
|
2345
|
-
if (toolCalls.length > 0) {
|
|
2346
|
-
assistantMsg.tool_calls = toolCalls.map((toolCall) => ({
|
|
2347
|
-
id: toolCall.callID,
|
|
2348
|
-
type: "function",
|
|
2349
|
-
function: {
|
|
2350
|
-
name: toolCall.name,
|
|
2351
|
-
arguments: JSON.stringify(toolCall.arguments)
|
|
2352
|
-
}
|
|
2353
|
-
}));
|
|
2354
|
-
const reasoningDetails = toolCalls.filter((toolCall) => toolCall.thoughtSignature).map((toolCall) => {
|
|
2355
|
-
try {
|
|
2356
|
-
return JSON.parse(toolCall.thoughtSignature);
|
|
2357
|
-
} catch {
|
|
2358
|
-
return null;
|
|
2359
|
-
}
|
|
2360
|
-
}).filter(Boolean);
|
|
2361
|
-
if (reasoningDetails.length > 0) assistantMsg.reasoning_details = reasoningDetails;
|
|
2362
|
-
}
|
|
2363
|
-
const assistantContent = assistantMsg.content;
|
|
2364
|
-
if (!(assistantContent !== null && assistantContent !== void 0 && (typeof assistantContent === "string" ? assistantContent.length > 0 : assistantContent.length > 0)) && !assistantMsg.tool_calls) continue;
|
|
2365
|
-
params.push(assistantMsg);
|
|
2366
|
-
lastRole = "assistant";
|
|
2367
|
-
const imageBlocks = [];
|
|
2368
|
-
for (const toolCall of toolCalls) {
|
|
2369
|
-
if (toolCall.status === "pending" || toolCall.status === "running") {
|
|
2370
|
-
params.push(buildSyntheticToolResult(toolCall, compat));
|
|
2371
|
-
lastRole = "tool";
|
|
2372
|
-
continue;
|
|
2373
|
-
}
|
|
2374
|
-
const textResult = toolCall.result.content.filter((content) => content.type === "text").map((content) => content.text).join("\n");
|
|
2375
|
-
const hasImages = toolCall.result.content.some((content) => content.type === "image");
|
|
2376
|
-
const toolResultMsg = {
|
|
2377
|
-
role: "tool",
|
|
2378
|
-
content: sanitizeSurrogates(textResult.length > 0 ? textResult : "(see attached image)"),
|
|
2379
|
-
tool_call_id: toolCall.callID
|
|
2380
|
-
};
|
|
2381
|
-
if (compat.requiresToolResultName) toolResultMsg.name = toolCall.name;
|
|
2382
|
-
params.push(toolResultMsg);
|
|
2383
|
-
lastRole = "tool";
|
|
2384
|
-
if (hasImages && model.input.includes("image")) {
|
|
2385
|
-
for (const block of toolCall.result.content) if (block.type === "image") imageBlocks.push({
|
|
2386
|
-
type: "image_url",
|
|
2387
|
-
image_url: { url: `data:${block.mimeType};base64,${block.data}` }
|
|
2388
|
-
});
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
if (imageBlocks.length > 0) {
|
|
2392
|
-
if (compat.requiresAssistantAfterToolResult) params.push({
|
|
2393
|
-
role: "assistant",
|
|
2394
|
-
content: "I have processed the tool results."
|
|
2395
|
-
});
|
|
2396
|
-
params.push({
|
|
2397
|
-
role: "user",
|
|
2398
|
-
content: [{
|
|
2399
|
-
type: "text",
|
|
2400
|
-
text: "Attached image(s) from tool result:"
|
|
2401
|
-
}, ...imageBlocks]
|
|
2402
|
-
});
|
|
2403
|
-
lastRole = "user";
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2406
|
-
return params;
|
|
2407
|
-
}
|
|
2408
|
-
function convertTools(tools, compat) {
|
|
2409
|
-
return tools.map((tool) => ({
|
|
2410
|
-
type: "function",
|
|
2411
|
-
function: {
|
|
2412
|
-
name: tool.name,
|
|
2413
|
-
description: tool.description,
|
|
2414
|
-
parameters: tool.parameters,
|
|
2415
|
-
...compat.supportsStrictMode !== false && { strict: false }
|
|
2416
|
-
}
|
|
2417
|
-
}));
|
|
2418
|
-
}
|
|
2419
|
-
function parseChunkUsage(rawUsage, model) {
|
|
2420
|
-
const promptTokens = rawUsage.prompt_tokens || 0;
|
|
2421
|
-
const reportedCachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;
|
|
2422
|
-
const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
|
|
2423
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens || 0;
|
|
2424
|
-
const cacheReadTokens = cacheWriteTokens > 0 ? Math.max(0, reportedCachedTokens - cacheWriteTokens) : reportedCachedTokens;
|
|
2425
|
-
const input = Math.max(0, promptTokens - cacheReadTokens - cacheWriteTokens);
|
|
2426
|
-
const outputTokens = (rawUsage.completion_tokens || 0) + reasoningTokens;
|
|
2427
|
-
const usage = {
|
|
2428
|
-
input,
|
|
2429
|
-
output: outputTokens,
|
|
2430
|
-
cacheRead: cacheReadTokens,
|
|
2431
|
-
cacheWrite: cacheWriteTokens,
|
|
2432
|
-
totalTokens: input + outputTokens + cacheReadTokens + cacheWriteTokens,
|
|
2433
|
-
cost: {
|
|
2434
|
-
input: 0,
|
|
2435
|
-
output: 0,
|
|
2436
|
-
cacheRead: 0,
|
|
2437
|
-
cacheWrite: 0,
|
|
2438
|
-
total: 0
|
|
2439
|
-
}
|
|
2440
|
-
};
|
|
2441
|
-
Model.calculateCost(model, usage);
|
|
2442
|
-
return usage;
|
|
2443
|
-
}
|
|
2444
|
-
function mapStopReason(reason) {
|
|
2445
|
-
if (reason === null) return { stopReason: "stop" };
|
|
2446
|
-
switch (reason) {
|
|
2447
|
-
case "stop":
|
|
2448
|
-
case "end": return { stopReason: "stop" };
|
|
2449
|
-
case "length": return { stopReason: "length" };
|
|
2450
|
-
case "function_call":
|
|
2451
|
-
case "tool_calls": return { stopReason: "toolUse" };
|
|
2452
|
-
case "content_filter": return {
|
|
2453
|
-
stopReason: "error",
|
|
2454
|
-
errorMessage: "Provider finish_reason: content_filter"
|
|
2455
|
-
};
|
|
2456
|
-
case "network_error": return {
|
|
2457
|
-
stopReason: "error",
|
|
2458
|
-
errorMessage: "Provider finish_reason: network_error"
|
|
2459
|
-
};
|
|
2460
|
-
default: return {
|
|
2461
|
-
stopReason: "error",
|
|
2462
|
-
errorMessage: `Provider finish_reason: ${reason}`
|
|
2463
|
-
};
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
function detectCompat(model) {
|
|
2467
|
-
const provider = model.provider.id;
|
|
2468
|
-
const baseUrl = resolveBaseUrl(model);
|
|
2469
|
-
const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
|
|
2470
|
-
const isNonStandard = provider === "cerebras" || baseUrl.includes("cerebras.ai") || provider === "xai" || baseUrl.includes("api.x.ai") || baseUrl.includes("chutes.ai") || baseUrl.includes("deepseek.com") || isZai || provider === "opencode" || baseUrl.includes("opencode.ai");
|
|
2471
|
-
const useMaxTokens = baseUrl.includes("chutes.ai");
|
|
2472
|
-
const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
|
|
2473
|
-
const reasoningEffortMap = (provider === "groq" || baseUrl.includes("groq.com")) && model.id === "qwen/qwen3-32b" ? {
|
|
2474
|
-
minimal: "default",
|
|
2475
|
-
low: "default",
|
|
2476
|
-
medium: "default",
|
|
2477
|
-
high: "default",
|
|
2478
|
-
xhigh: "default"
|
|
2479
|
-
} : {};
|
|
1386
|
+
//#endregion
|
|
1387
|
+
//#region src/llm/index.ts
|
|
1388
|
+
function createAISDKProtocol(protocol) {
|
|
2480
1389
|
return {
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
supportsReasoningEffort: !isGrok && !isZai,
|
|
2484
|
-
reasoningEffortMap,
|
|
2485
|
-
supportsUsageInStreaming: true,
|
|
2486
|
-
maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
|
|
2487
|
-
requiresToolResultName: false,
|
|
2488
|
-
requiresAssistantAfterToolResult: false,
|
|
2489
|
-
requiresThinkingAsText: false,
|
|
2490
|
-
thinkingFormat: isZai ? "zai" : provider === "openrouter" || baseUrl.includes("openrouter.ai") ? "openrouter" : "openai",
|
|
2491
|
-
openRouterRouting: {},
|
|
2492
|
-
vercelGatewayRouting: {},
|
|
2493
|
-
zaiToolStream: false,
|
|
2494
|
-
supportsStrictMode: true
|
|
1390
|
+
protocol,
|
|
1391
|
+
stream: stream$1
|
|
2495
1392
|
};
|
|
2496
1393
|
}
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
|
|
2507
|
-
supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
|
|
2508
|
-
reasoningEffortMap: model.compat.reasoningEffortMap ?? detected.reasoningEffortMap,
|
|
2509
|
-
supportsUsageInStreaming: model.compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
|
|
2510
|
-
maxTokensField: model.compat.maxTokensField ?? detected.maxTokensField,
|
|
2511
|
-
requiresToolResultName: model.compat.requiresToolResultName ?? detected.requiresToolResultName,
|
|
2512
|
-
requiresAssistantAfterToolResult: model.compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
|
|
2513
|
-
requiresThinkingAsText: model.compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
|
|
2514
|
-
thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
|
|
2515
|
-
openRouterRouting: model.compat.openRouterRouting ?? {},
|
|
2516
|
-
vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
|
|
2517
|
-
zaiToolStream: model.compat.zaiToolStream ?? detected.zaiToolStream,
|
|
2518
|
-
supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode
|
|
2519
|
-
};
|
|
1394
|
+
function registerAISDKProtocols() {
|
|
1395
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.anthropic));
|
|
1396
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.google));
|
|
1397
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.googleVertex));
|
|
1398
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.googleVertexAnthropic));
|
|
1399
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.openai));
|
|
1400
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.openaiCompatible));
|
|
1401
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.openrouter));
|
|
1402
|
+
Protocol.registerProtocolProvider(createAISDKProtocol(Model.KnownProviderEnum.xai));
|
|
2520
1403
|
}
|
|
2521
|
-
const openAICompletionsProtocolProvider = {
|
|
2522
|
-
protocol: Model.KnownProtocolEnum.openaiCompletions,
|
|
2523
|
-
stream: streamOpenAICompletions,
|
|
2524
|
-
streamSimple: streamSimpleOpenAICompletions
|
|
2525
|
-
};
|
|
2526
|
-
//#endregion
|
|
2527
|
-
//#region src/provider/register.ts
|
|
2528
|
-
Stream.registerProtocolProvider(anthropicProtocolProvider, "providers/anthropic/index.ts");
|
|
2529
|
-
Stream.registerProtocolProvider(openAICompletionsProtocolProvider, "providers/openai/completions.ts");
|
|
2530
|
-
//#endregion
|
|
2531
|
-
//#region src/agent/agent.ts
|
|
2532
|
-
let Agent;
|
|
2533
|
-
(function(_Agent) {
|
|
2534
|
-
_Agent.ToolTerminalResultSchema = Type.Union([Message.ToolCompletedSchema, Message.ToolErrorSchema]);
|
|
2535
|
-
_Agent.ToolResultSchema = Type.Union([
|
|
2536
|
-
Message.ToolRunningSchema,
|
|
2537
|
-
Message.ToolCompletedSchema,
|
|
2538
|
-
Message.ToolErrorSchema
|
|
2539
|
-
]);
|
|
2540
|
-
function defineTool(tool) {
|
|
2541
|
-
return tool;
|
|
2542
|
-
}
|
|
2543
|
-
_Agent.defineTool = defineTool;
|
|
2544
|
-
_Agent.ToolCallInFlightSchema = Type.Object({
|
|
2545
|
-
callID: Type.String(),
|
|
2546
|
-
name: Type.String(),
|
|
2547
|
-
rawArgs: Type.Record(Type.String(), Type.Unknown()),
|
|
2548
|
-
args: Type.Optional(Type.Unknown())
|
|
2549
|
-
});
|
|
2550
|
-
const ModelNotFoundErr = _Agent.ModelNotFoundErr = NamedError.create("ModelNotFoundErr", Type.Object({
|
|
2551
|
-
message: Type.String(),
|
|
2552
|
-
provider: Type.String(),
|
|
2553
|
-
model: Type.String()
|
|
2554
|
-
}));
|
|
2555
|
-
const ModelNotConfiguredErr = _Agent.ModelNotConfiguredErr = NamedError.create("ModelNotConfiguredErr", Type.Object({ message: Type.String() }));
|
|
2556
|
-
const AgentInStreamingErr = _Agent.AgentInStreamingErr = NamedError.create("AgentInStreamingErr", Type.Object({
|
|
2557
|
-
message: Type.String(),
|
|
2558
|
-
name: Type.String()
|
|
2559
|
-
}));
|
|
2560
|
-
class Instance {
|
|
2561
|
-
_state;
|
|
2562
|
-
listeners = /* @__PURE__ */ new Set();
|
|
2563
|
-
abortController;
|
|
2564
|
-
convertToLlm;
|
|
2565
|
-
transformContext;
|
|
2566
|
-
steeringQueue = [];
|
|
2567
|
-
followUpQueue = [];
|
|
2568
|
-
steeringMode;
|
|
2569
|
-
followUpMode;
|
|
2570
|
-
streamFn;
|
|
2571
|
-
_sessionId;
|
|
2572
|
-
getApiKey;
|
|
2573
|
-
_onPayload;
|
|
2574
|
-
runningPrompt;
|
|
2575
|
-
resolveRunningPrompt;
|
|
2576
|
-
_thinkingBudgets;
|
|
2577
|
-
_transport;
|
|
2578
|
-
_maxRetryDelayMs;
|
|
2579
|
-
_toolExecution;
|
|
2580
|
-
_beforeToolExecution;
|
|
2581
|
-
_afterToolExecution;
|
|
2582
|
-
constructor(name, model, opts = {}) {
|
|
2583
|
-
this._state = {
|
|
2584
|
-
systemPrompt: "",
|
|
2585
|
-
thinkingLevel: "off",
|
|
2586
|
-
tools: [],
|
|
2587
|
-
messages: [],
|
|
2588
|
-
isStreaming: false,
|
|
2589
|
-
streamMessage: null,
|
|
2590
|
-
pendingToolCalls: /* @__PURE__ */ new Set(),
|
|
2591
|
-
error: void 0,
|
|
2592
|
-
...opts.initialState,
|
|
2593
|
-
name,
|
|
2594
|
-
model
|
|
2595
|
-
};
|
|
2596
|
-
/**
|
|
2597
|
-
* Transformation logic to prepare messages for the LLM.
|
|
2598
|
-
* * @remarks
|
|
2599
|
-
* Currently just forwards messages as-is. Modify this logic when
|
|
2600
|
-
* specific formatting or filtering is required.
|
|
2601
|
-
* A good example is using user message parts with custom content
|
|
2602
|
-
* * @default
|
|
2603
|
-
* forwards messages as is.
|
|
2604
|
-
*/
|
|
2605
|
-
this.convertToLlm = opts.convertToLlm || ((messages) => messages);
|
|
2606
|
-
this.transformContext = opts.transformContext;
|
|
2607
|
-
this.steeringMode = opts.steeringMode || "one-at-a-time";
|
|
2608
|
-
this.followUpMode = opts.followUpMode || "one-at-a-time";
|
|
2609
|
-
this.streamFn = opts.streamFn || Stream.streamSimple;
|
|
2610
|
-
this._sessionId = opts.sessionId;
|
|
2611
|
-
this.getApiKey = opts.getApiKey;
|
|
2612
|
-
this._onPayload = opts.onPayload;
|
|
2613
|
-
this._thinkingBudgets = opts.thinkingBudgets;
|
|
2614
|
-
this._transport = opts.transport ?? "sse";
|
|
2615
|
-
this._maxRetryDelayMs = opts.maxRetryDelayMs;
|
|
2616
|
-
this._toolExecution = opts.toolExecution ?? "parallel";
|
|
2617
|
-
this._beforeToolExecution = opts.beforeToolExecution;
|
|
2618
|
-
this._afterToolExecution = opts.afterToolExecution;
|
|
2619
|
-
}
|
|
2620
|
-
/**
|
|
2621
|
-
* Get the current session ID used for provider caching.
|
|
2622
|
-
*/
|
|
2623
|
-
get sessionId() {
|
|
2624
|
-
return this._sessionId;
|
|
2625
|
-
}
|
|
2626
|
-
/**
|
|
2627
|
-
* Set the session ID for provider caching.
|
|
2628
|
-
* Call this when switching sessions (new session, branch, resume, etc).
|
|
2629
|
-
*/
|
|
2630
|
-
set sessionId(value) {
|
|
2631
|
-
this._sessionId = value;
|
|
2632
|
-
}
|
|
2633
|
-
/**
|
|
2634
|
-
* Get the current thinking budgets.
|
|
2635
|
-
*/
|
|
2636
|
-
get thinkingBudgets() {
|
|
2637
|
-
return this._thinkingBudgets;
|
|
2638
|
-
}
|
|
2639
|
-
/**
|
|
2640
|
-
* Set custom thinking budgets for token-based providers.
|
|
2641
|
-
*/
|
|
2642
|
-
set thinkingBudgets(value) {
|
|
2643
|
-
this._thinkingBudgets = value;
|
|
2644
|
-
}
|
|
2645
|
-
/**
|
|
2646
|
-
* Get the current preferred transport.
|
|
2647
|
-
*/
|
|
2648
|
-
get transport() {
|
|
2649
|
-
return this._transport;
|
|
2650
|
-
}
|
|
2651
|
-
/**
|
|
2652
|
-
* Set the preferred transport.
|
|
2653
|
-
*/
|
|
2654
|
-
setTransport(value) {
|
|
2655
|
-
this._transport = value;
|
|
2656
|
-
}
|
|
2657
|
-
/**
|
|
2658
|
-
* Get the current max retry delay in milliseconds.
|
|
2659
|
-
*/
|
|
2660
|
-
get maxRetryDelayMs() {
|
|
2661
|
-
return this._maxRetryDelayMs;
|
|
2662
|
-
}
|
|
2663
|
-
/**
|
|
2664
|
-
* Set the maximum delay to wait for server-requested retries.
|
|
2665
|
-
* Set to 0 to disable the cap.
|
|
2666
|
-
*/
|
|
2667
|
-
set maxRetryDelayMs(value) {
|
|
2668
|
-
this._maxRetryDelayMs = value;
|
|
2669
|
-
}
|
|
2670
|
-
get toolExecution() {
|
|
2671
|
-
return this._toolExecution;
|
|
2672
|
-
}
|
|
2673
|
-
setToolExecution(value) {
|
|
2674
|
-
this._toolExecution = value;
|
|
2675
|
-
}
|
|
2676
|
-
setBeforeToolExecution(value) {
|
|
2677
|
-
this._beforeToolExecution = value;
|
|
2678
|
-
}
|
|
2679
|
-
setAfterToolExecution(value) {
|
|
2680
|
-
this._afterToolExecution = value;
|
|
2681
|
-
}
|
|
2682
|
-
get state() {
|
|
2683
|
-
return this._state;
|
|
2684
|
-
}
|
|
2685
|
-
subscribe(fn) {
|
|
2686
|
-
this.listeners.add(fn);
|
|
2687
|
-
return () => this.listeners.delete(fn);
|
|
2688
|
-
}
|
|
2689
|
-
setSystemPrompt(v) {
|
|
2690
|
-
this._state.systemPrompt = v;
|
|
2691
|
-
}
|
|
2692
|
-
setModel(m) {
|
|
2693
|
-
this._state.model = m;
|
|
2694
|
-
}
|
|
2695
|
-
setThinkingLevel(l) {
|
|
2696
|
-
this._state.thinkingLevel = l;
|
|
2697
|
-
}
|
|
2698
|
-
setSteeringMode(mode) {
|
|
2699
|
-
this.steeringMode = mode;
|
|
2700
|
-
}
|
|
2701
|
-
getSteeringMode() {
|
|
2702
|
-
return this.steeringMode;
|
|
2703
|
-
}
|
|
2704
|
-
setFollowUpMode(mode) {
|
|
2705
|
-
this.followUpMode = mode;
|
|
2706
|
-
}
|
|
2707
|
-
getFollowUpMode() {
|
|
2708
|
-
return this.followUpMode;
|
|
2709
|
-
}
|
|
2710
|
-
setTools(t) {
|
|
2711
|
-
this._state.tools = t;
|
|
2712
|
-
}
|
|
2713
|
-
replaceMessages(ms) {
|
|
2714
|
-
this._state.messages = ms.slice();
|
|
2715
|
-
}
|
|
2716
|
-
appendMessage(m) {
|
|
2717
|
-
this._state.messages = [...this._state.messages, m];
|
|
2718
|
-
}
|
|
2719
|
-
findMessageIndexById(messageId) {
|
|
2720
|
-
return this._state.messages.findIndex((message) => message.messageId === messageId);
|
|
2721
|
-
}
|
|
2722
|
-
replaceMessageById(message) {
|
|
2723
|
-
const messageIndex = this.findMessageIndexById(message.messageId);
|
|
2724
|
-
if (messageIndex === -1) return false;
|
|
2725
|
-
const messages = this._state.messages.slice();
|
|
2726
|
-
messages[messageIndex] = message;
|
|
2727
|
-
this._state.messages = messages;
|
|
2728
|
-
return true;
|
|
2729
|
-
}
|
|
2730
|
-
upsertMessage(message) {
|
|
2731
|
-
if (this.replaceMessageById(message)) return;
|
|
2732
|
-
this.appendMessage(message);
|
|
2733
|
-
}
|
|
2734
|
-
patchStoredAssistantPart(messageId, partIndex, part) {
|
|
2735
|
-
const messageIndex = this.findMessageIndexById(messageId);
|
|
2736
|
-
if (messageIndex === -1) return false;
|
|
2737
|
-
const messages = this._state.messages.slice();
|
|
2738
|
-
const existing = messages[messageIndex];
|
|
2739
|
-
if (!existing || existing.role !== "assistant") return false;
|
|
2740
|
-
const nextParts = existing.parts.slice();
|
|
2741
|
-
nextParts[partIndex] = part;
|
|
2742
|
-
messages[messageIndex] = {
|
|
2743
|
-
...existing,
|
|
2744
|
-
parts: nextParts
|
|
2745
|
-
};
|
|
2746
|
-
this._state.messages = messages;
|
|
2747
|
-
return true;
|
|
2748
|
-
}
|
|
2749
|
-
/**
|
|
2750
|
-
* Queue a steering message while the agent is running.
|
|
2751
|
-
* Delivered after the current assistant turn finishes executing its tool calls,
|
|
2752
|
-
* before the next LLM call.
|
|
2753
|
-
*/
|
|
2754
|
-
steer(m) {
|
|
2755
|
-
this.steeringQueue.push(m);
|
|
2756
|
-
}
|
|
2757
|
-
/**
|
|
2758
|
-
* Queue a follow-up message to be processed after the agent finishes.
|
|
2759
|
-
* Delivered only when agent has no more tool calls or steering messages.
|
|
2760
|
-
*/
|
|
2761
|
-
followUp(m) {
|
|
2762
|
-
this.followUpQueue.push(m);
|
|
2763
|
-
}
|
|
2764
|
-
clearSteeringQueue() {
|
|
2765
|
-
this.steeringQueue = [];
|
|
2766
|
-
}
|
|
2767
|
-
clearFollowUpQueue() {
|
|
2768
|
-
this.followUpQueue = [];
|
|
2769
|
-
}
|
|
2770
|
-
clearAllQueues() {
|
|
2771
|
-
this.steeringQueue = [];
|
|
2772
|
-
this.followUpQueue = [];
|
|
2773
|
-
}
|
|
2774
|
-
hasQueuedMessages() {
|
|
2775
|
-
return this.steeringQueue.length > 0 || this.followUpQueue.length > 0;
|
|
2776
|
-
}
|
|
2777
|
-
dequeueSteeringMessages() {
|
|
2778
|
-
if (this.steeringMode === "one-at-a-time") {
|
|
2779
|
-
if (this.steeringQueue.length > 0) {
|
|
2780
|
-
const first = this.steeringQueue[0];
|
|
2781
|
-
this.steeringQueue = this.steeringQueue.slice(1);
|
|
2782
|
-
return [first];
|
|
2783
|
-
}
|
|
2784
|
-
return [];
|
|
2785
|
-
}
|
|
2786
|
-
const steering = this.steeringQueue.slice();
|
|
2787
|
-
this.steeringQueue = [];
|
|
2788
|
-
return steering;
|
|
2789
|
-
}
|
|
2790
|
-
dequeueFollowUpMessages() {
|
|
2791
|
-
if (this.followUpMode === "one-at-a-time") {
|
|
2792
|
-
if (this.followUpQueue.length > 0) {
|
|
2793
|
-
const first = this.followUpQueue[0];
|
|
2794
|
-
this.followUpQueue = this.followUpQueue.slice(1);
|
|
2795
|
-
return [first];
|
|
2796
|
-
}
|
|
2797
|
-
return [];
|
|
2798
|
-
}
|
|
2799
|
-
const followUp = this.followUpQueue.slice();
|
|
2800
|
-
this.followUpQueue = [];
|
|
2801
|
-
return followUp;
|
|
2802
|
-
}
|
|
2803
|
-
clearMessages() {
|
|
2804
|
-
this._state.messages = [];
|
|
2805
|
-
}
|
|
2806
|
-
abort() {
|
|
2807
|
-
this.abortController?.abort();
|
|
2808
|
-
}
|
|
2809
|
-
waitForIdle() {
|
|
2810
|
-
return this.runningPrompt ?? Promise.resolve();
|
|
2811
|
-
}
|
|
2812
|
-
reset() {
|
|
2813
|
-
this._state.messages = [];
|
|
2814
|
-
this._state.isStreaming = false;
|
|
2815
|
-
this._state.streamMessage = null;
|
|
2816
|
-
this._state.pendingToolCalls = /* @__PURE__ */ new Set();
|
|
2817
|
-
this._state.error = void 0;
|
|
2818
|
-
this.steeringQueue = [];
|
|
2819
|
-
this.followUpQueue = [];
|
|
2820
|
-
}
|
|
2821
|
-
getName() {
|
|
2822
|
-
return this._state.name;
|
|
2823
|
-
}
|
|
2824
|
-
ensureIdle() {
|
|
2825
|
-
if (this._state.isStreaming) throw new AgentInStreamingErr({
|
|
2826
|
-
message: "agent is already processing a prompt. Use steer() or followup() to queue messages, or wait for completion.",
|
|
2827
|
-
name: this._state.name
|
|
2828
|
-
});
|
|
2829
|
-
}
|
|
2830
|
-
async _runLoop(messages, opts) {
|
|
2831
|
-
const model = this._state.model;
|
|
2832
|
-
if (!model) throw new ModelNotConfiguredErr({ message: "no model configured yet" });
|
|
2833
|
-
this.runningPrompt = new Promise((resolve) => {
|
|
2834
|
-
this.resolveRunningPrompt = resolve;
|
|
2835
|
-
});
|
|
2836
|
-
this.abortController = new AbortController();
|
|
2837
|
-
this._state.isStreaming = true;
|
|
2838
|
-
this._state.streamMessage = null;
|
|
2839
|
-
this._state.error = void 0;
|
|
2840
|
-
const reasoning = this.state.thinkingLevel === "off" ? void 0 : this._state.thinkingLevel;
|
|
2841
|
-
const context = {
|
|
2842
|
-
systemPrompt: this._state.systemPrompt,
|
|
2843
|
-
messages: this._state.messages.slice(),
|
|
2844
|
-
tools: this._state.tools
|
|
2845
|
-
};
|
|
2846
|
-
let skipInitialSteeringPoll = opts?.skipInitialSteeringPoll === true;
|
|
2847
|
-
const config = {
|
|
2848
|
-
model,
|
|
2849
|
-
reasoning,
|
|
2850
|
-
sessionId: this._sessionId,
|
|
2851
|
-
onPayload: this._onPayload,
|
|
2852
|
-
transport: this._transport,
|
|
2853
|
-
thinkingBudgets: this._thinkingBudgets,
|
|
2854
|
-
maxRetryDelayMs: this._maxRetryDelayMs,
|
|
2855
|
-
toolExecution: this._toolExecution,
|
|
2856
|
-
beforeToolExecution: this._beforeToolExecution,
|
|
2857
|
-
afterToolExecution: this._afterToolExecution,
|
|
2858
|
-
convertToLlm: this.convertToLlm,
|
|
2859
|
-
transformContext: this.transformContext,
|
|
2860
|
-
getApiKey: this.getApiKey,
|
|
2861
|
-
getSteeringMessages: async () => {
|
|
2862
|
-
if (skipInitialSteeringPoll) {
|
|
2863
|
-
skipInitialSteeringPoll = false;
|
|
2864
|
-
return [];
|
|
2865
|
-
}
|
|
2866
|
-
return this.dequeueSteeringMessages();
|
|
2867
|
-
},
|
|
2868
|
-
getFollowUpMessages: async () => this.dequeueFollowUpMessages()
|
|
2869
|
-
};
|
|
2870
|
-
try {
|
|
2871
|
-
if (messages) await Loop.runAgentLoop(config, context, messages, async (e) => this._processLoopEvent(e), this.streamFn, this.abortController.signal);
|
|
2872
|
-
else await Loop.runAgentLoopContinue(config, context, async (e) => this._processLoopEvent(e), this.streamFn, this.abortController.signal);
|
|
2873
|
-
} catch (err) {
|
|
2874
|
-
const message = Message.createAssistantMessage({
|
|
2875
|
-
role: "assistant",
|
|
2876
|
-
protocol: model.protocol,
|
|
2877
|
-
provider: model.provider,
|
|
2878
|
-
model: model.id,
|
|
2879
|
-
usage: {
|
|
2880
|
-
input: 0,
|
|
2881
|
-
output: 0,
|
|
2882
|
-
cacheRead: 0,
|
|
2883
|
-
cacheWrite: 0,
|
|
2884
|
-
totalTokens: 0,
|
|
2885
|
-
cost: {
|
|
2886
|
-
input: 0,
|
|
2887
|
-
output: 0,
|
|
2888
|
-
cacheRead: 0,
|
|
2889
|
-
cacheWrite: 0,
|
|
2890
|
-
total: 0
|
|
2891
|
-
}
|
|
2892
|
-
},
|
|
2893
|
-
stopReason: this.abortController.signal.aborted ? "aborted" : "error",
|
|
2894
|
-
errorMessage: err?.message || String(err),
|
|
2895
|
-
time: {
|
|
2896
|
-
created: Date.now(),
|
|
2897
|
-
completed: Date.now()
|
|
2898
|
-
},
|
|
2899
|
-
parts: []
|
|
2900
|
-
});
|
|
2901
|
-
this.appendMessage(message);
|
|
2902
|
-
this._state.error = err?.message || String(err);
|
|
2903
|
-
this.emit({
|
|
2904
|
-
type: "agent.end",
|
|
2905
|
-
messages: [message]
|
|
2906
|
-
});
|
|
2907
|
-
} finally {
|
|
2908
|
-
this._state.isStreaming = false;
|
|
2909
|
-
this._state.streamMessage = null;
|
|
2910
|
-
this._state.pendingToolCalls = /* @__PURE__ */ new Set();
|
|
2911
|
-
this.abortController = void 0;
|
|
2912
|
-
this.resolveRunningPrompt?.();
|
|
2913
|
-
this.runningPrompt = void 0;
|
|
2914
|
-
this.resolveRunningPrompt = void 0;
|
|
2915
|
-
}
|
|
2916
|
-
}
|
|
2917
|
-
async loop(messages) {
|
|
2918
|
-
this.ensureIdle();
|
|
2919
|
-
await this._runLoop(messages);
|
|
2920
|
-
}
|
|
2921
|
-
async loopContinue() {
|
|
2922
|
-
this.ensureIdle();
|
|
2923
|
-
await this._runLoop();
|
|
2924
|
-
}
|
|
2925
|
-
async prompt(messages, images) {
|
|
2926
|
-
this.ensureIdle();
|
|
2927
|
-
if (!this._state.model) throw new ModelNotConfiguredErr({ message: "no model configured yet." });
|
|
2928
|
-
const message = Message.createUserMessage({
|
|
2929
|
-
role: "user",
|
|
2930
|
-
time: { created: Date.now() },
|
|
2931
|
-
parts: [...messages, ...images ?? []]
|
|
2932
|
-
});
|
|
2933
|
-
await this.loop([message]);
|
|
2934
|
-
}
|
|
2935
|
-
_processLoopEvent(event) {
|
|
2936
|
-
switch (event.type) {
|
|
2937
|
-
case "message.start":
|
|
2938
|
-
this._state.streamMessage = event.message;
|
|
2939
|
-
break;
|
|
2940
|
-
case "message.part.start":
|
|
2941
|
-
case "message.part.update":
|
|
2942
|
-
case "message.part.end":
|
|
2943
|
-
this._state.streamMessage = event.message;
|
|
2944
|
-
if (event.message.role === "assistant") this.patchStoredAssistantPart(event.message.messageId, event.partIndex, event.part);
|
|
2945
|
-
break;
|
|
2946
|
-
case "message.update":
|
|
2947
|
-
this._state.streamMessage = event.message;
|
|
2948
|
-
this.replaceMessageById(event.message);
|
|
2949
|
-
break;
|
|
2950
|
-
case "message.end":
|
|
2951
|
-
this._state.streamMessage = null;
|
|
2952
|
-
this.upsertMessage(event.message);
|
|
2953
|
-
break;
|
|
2954
|
-
case "tool.execution.start": {
|
|
2955
|
-
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
2956
|
-
pendingToolCalls.add(event.callID);
|
|
2957
|
-
this._state.pendingToolCalls = pendingToolCalls;
|
|
2958
|
-
break;
|
|
2959
|
-
}
|
|
2960
|
-
case "tool.execution.end": {
|
|
2961
|
-
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
2962
|
-
pendingToolCalls.delete(event.callID);
|
|
2963
|
-
this._state.pendingToolCalls = pendingToolCalls;
|
|
2964
|
-
break;
|
|
2965
|
-
}
|
|
2966
|
-
case "turn.end":
|
|
2967
|
-
if (event.message.role === "assistant" && event.message.parts.length > 0) this._state.error = event.message.errorMessage;
|
|
2968
|
-
break;
|
|
2969
|
-
case "agent.end":
|
|
2970
|
-
this._state.isStreaming = false;
|
|
2971
|
-
this._state.streamMessage = null;
|
|
2972
|
-
break;
|
|
2973
|
-
}
|
|
2974
|
-
this.emit(event);
|
|
2975
|
-
}
|
|
2976
|
-
emit(e) {
|
|
2977
|
-
for (const listener of this.listeners) listener(e);
|
|
2978
|
-
}
|
|
2979
|
-
}
|
|
2980
|
-
_Agent.Instance = Instance;
|
|
2981
|
-
async function create(options) {
|
|
2982
|
-
let resolvedModel;
|
|
2983
|
-
if ("provider" in options) {
|
|
2984
|
-
const result = await Model.getModel(options.provider, options.model);
|
|
2985
|
-
if (!result) throw new ModelNotFoundErr({
|
|
2986
|
-
message: "model not found or not configured yet",
|
|
2987
|
-
provider: options.provider,
|
|
2988
|
-
model: options.model
|
|
2989
|
-
});
|
|
2990
|
-
resolvedModel = result;
|
|
2991
|
-
} else resolvedModel = options.model;
|
|
2992
|
-
return new Instance(options.name ?? "main", resolvedModel, options);
|
|
2993
|
-
}
|
|
2994
|
-
_Agent.create = create;
|
|
2995
|
-
})(Agent || (Agent = {}));
|
|
2996
1404
|
//#endregion
|
|
2997
|
-
//#region src/
|
|
2998
|
-
|
|
2999
|
-
(function(_CodeMode) {
|
|
3000
|
-
const ToolDefinitionErr = _CodeMode.ToolDefinitionErr = NamedError.create("ToolDefinitionErr", Type.Object({ message: Type.String() }));
|
|
3001
|
-
const toolFnPrefix = process.env.CODEWORK_CODEMODE_FN_PREFIX ?? "external_";
|
|
3002
|
-
const SandboxExecutionInputSchema = _CodeMode.SandboxExecutionInputSchema = Type.Object({ typescriptCode: Type.String({ description: "TypeScript code to execute in the sandbox." }) });
|
|
3003
|
-
const SandboxExecutionOutputSchema = _CodeMode.SandboxExecutionOutputSchema = Type.Object({
|
|
3004
|
-
result: Type.Optional(Type.Unknown()),
|
|
3005
|
-
logs: Type.Optional(Type.Array(Type.String()))
|
|
3006
|
-
});
|
|
3007
|
-
const SandboxExecutionErrorSchema = _CodeMode.SandboxExecutionErrorSchema = Type.Object({
|
|
3008
|
-
message: Type.String(),
|
|
3009
|
-
name: Type.Optional(Type.String()),
|
|
3010
|
-
stack: Type.Optional(Type.String()),
|
|
3011
|
-
line: Type.Optional(Type.Number()),
|
|
3012
|
-
logs: Type.Optional(Type.Array(Type.String()))
|
|
3013
|
-
});
|
|
3014
|
-
function withMessageInStack(message, stack) {
|
|
3015
|
-
if (!stack) return void 0;
|
|
3016
|
-
return stack.includes(message) ? stack : `${message}\n${stack}`;
|
|
3017
|
-
}
|
|
3018
|
-
function normalizeExecutionError(error) {
|
|
3019
|
-
if (error instanceof Error) return {
|
|
3020
|
-
name: error.name,
|
|
3021
|
-
message: error.message,
|
|
3022
|
-
stack: withMessageInStack(error.message, error.stack),
|
|
3023
|
-
line: parseErrorLine(error.stack)
|
|
3024
|
-
};
|
|
3025
|
-
if (typeof error === "object" && error !== null) {
|
|
3026
|
-
const candidate = error;
|
|
3027
|
-
return {
|
|
3028
|
-
name: typeof candidate.name === "string" ? candidate.name : void 0,
|
|
3029
|
-
message: typeof candidate.message === "string" ? candidate.message : JSON.stringify(candidate) || "Unknown execution error",
|
|
3030
|
-
stack: typeof candidate.stack === "string" ? withMessageInStack(typeof candidate.message === "string" ? candidate.message : JSON.stringify(candidate) || "Unknown execution error", candidate.stack) : void 0,
|
|
3031
|
-
line: typeof candidate.line === "number" ? candidate.line : parseErrorLine(candidate.stack)
|
|
3032
|
-
};
|
|
3033
|
-
}
|
|
3034
|
-
return {
|
|
3035
|
-
name: "Error",
|
|
3036
|
-
message: String(error)
|
|
3037
|
-
};
|
|
3038
|
-
}
|
|
3039
|
-
function parseErrorLine(stack) {
|
|
3040
|
-
if (typeof stack !== "string") return void 0;
|
|
3041
|
-
const lineMatch = stack.match(/:(\d+)(?::\d+)?\)?$/m);
|
|
3042
|
-
return lineMatch ? Number(lineMatch[1]) : void 0;
|
|
3043
|
-
}
|
|
3044
|
-
function serializeForContent(value) {
|
|
3045
|
-
return JSON.stringify(value, (_key, currentValue) => typeof currentValue === "bigint" ? currentValue.toString() : currentValue, 2);
|
|
3046
|
-
}
|
|
3047
|
-
function toolContentToText(result) {
|
|
3048
|
-
return result.content.filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n").trim();
|
|
3049
|
-
}
|
|
3050
|
-
function unwrapToolResult(tool, result) {
|
|
3051
|
-
if (result.status === "completed") {
|
|
3052
|
-
if (tool.outputSchema) return validateSchema(tool.outputSchema, result.result.details, `Tool "${tool.name}" output`);
|
|
3053
|
-
return result.result.details;
|
|
3054
|
-
}
|
|
3055
|
-
if (tool.errorSchema && result.result.details !== void 0) validateSchema(tool.errorSchema, result.result.details, `Tool "${tool.name}" error`);
|
|
3056
|
-
const message = toolContentToText(result.result) || `Tool "${tool.name}" failed`;
|
|
3057
|
-
const error = new Error(message);
|
|
3058
|
-
if (result.result.details !== void 0) error.cause = result.result.details;
|
|
3059
|
-
throw error;
|
|
3060
|
-
}
|
|
3061
|
-
function toolToBinding(tool, prefix = "") {
|
|
3062
|
-
const inputSchema = TypeGuard.IsSchema(tool.parameters) ? tool.parameters : Type.Object({});
|
|
3063
|
-
const outputSchema = TypeGuard.IsSchema(tool.outputSchema) ? tool.outputSchema : void 0;
|
|
3064
|
-
const errorSchema = TypeGuard.IsSchema(tool.errorSchema) ? tool.errorSchema : void 0;
|
|
3065
|
-
if (!("execute" in tool) || typeof tool.execute !== "function") throw new ToolDefinitionErr({ message: `tool "${tool.name}" does not have an execute function. code mode requires tools with implementation` });
|
|
3066
|
-
return {
|
|
3067
|
-
name: `${prefix}${tool.name}`,
|
|
3068
|
-
description: tool.description,
|
|
3069
|
-
inputSchema,
|
|
3070
|
-
outputSchema,
|
|
3071
|
-
errorSchema,
|
|
3072
|
-
execute: async (callID, params, signal) => {
|
|
3073
|
-
const validatedParams = validateSchema(inputSchema, params, `Tool "${tool.name}" input`);
|
|
3074
|
-
return unwrapToolResult(tool, await tool.execute(callID, validatedParams, signal));
|
|
3075
|
-
}
|
|
3076
|
-
};
|
|
3077
|
-
}
|
|
3078
|
-
function toolsForBinding(tools, prefix) {
|
|
3079
|
-
const bindings = {};
|
|
3080
|
-
for (const tool of tools) {
|
|
3081
|
-
const name = `${prefix}${tool.name}`;
|
|
3082
|
-
bindings[name] = toolToBinding(tool, prefix);
|
|
3083
|
-
}
|
|
3084
|
-
return bindings;
|
|
3085
|
-
}
|
|
3086
|
-
function indent(value, depth = 1) {
|
|
3087
|
-
const prefix = " ".repeat(depth);
|
|
3088
|
-
return value.split("\n").map((line) => `${prefix}${line}`).join("\n");
|
|
3089
|
-
}
|
|
3090
|
-
function toPropertyKey(name) {
|
|
3091
|
-
return /^[$A-Z_a-z][$\w]*$/i.test(name) ? name : JSON.stringify(name);
|
|
3092
|
-
}
|
|
3093
|
-
function schemaToTypeScript(schema) {
|
|
3094
|
-
if (TypeGuard.IsAny(schema)) return "any";
|
|
3095
|
-
if (TypeGuard.IsUnknown(schema)) return "unknown";
|
|
3096
|
-
if (TypeGuard.IsString(schema)) return "string";
|
|
3097
|
-
if (TypeGuard.IsNumber(schema) || TypeGuard.IsInteger(schema)) return "number";
|
|
3098
|
-
if (TypeGuard.IsBoolean(schema)) return "boolean";
|
|
3099
|
-
if (TypeGuard.IsNull(schema)) return "null";
|
|
3100
|
-
if (TypeGuard.IsUndefined(schema) || TypeGuard.IsVoid(schema)) return "undefined";
|
|
3101
|
-
if (TypeGuard.IsLiteral(schema)) return JSON.stringify(schema.const);
|
|
3102
|
-
if (TypeGuard.IsArray(schema)) return `Array<${schemaToTypeScript(schema.items)}>`;
|
|
3103
|
-
if (TypeGuard.IsTuple(schema)) return `[${(schema.items ?? []).map((item) => schemaToTypeScript(item)).join(", ")}]`;
|
|
3104
|
-
if (TypeGuard.IsUnion(schema)) return schema.anyOf.map((item) => schemaToTypeScript(item)).join(" | ");
|
|
3105
|
-
if (TypeGuard.IsIntersect(schema)) return schema.allOf.map((item) => schemaToTypeScript(item)).join(" & ");
|
|
3106
|
-
if (TypeGuard.IsRecord(schema)) return `Record<string, ${schemaToTypeScript(Object.values(schema.patternProperties ?? {}).find(TypeGuard.IsSchema) ?? (schema.additionalProperties && TypeGuard.IsSchema(schema.additionalProperties) ? schema.additionalProperties : Type.Unknown()))}>`;
|
|
3107
|
-
if (TypeGuard.IsObject(schema)) {
|
|
3108
|
-
const required = new Set(schema.required ?? []);
|
|
3109
|
-
const properties = Object.entries(schema.properties ?? {}).map(([key, value]) => {
|
|
3110
|
-
const optional = required.has(key) ? "" : "?";
|
|
3111
|
-
return `${toPropertyKey(key)}${optional}: ${schemaToTypeScript(value)};`;
|
|
3112
|
-
});
|
|
3113
|
-
if (schema.additionalProperties === true) properties.push("[key: string]: unknown;");
|
|
3114
|
-
else if (schema.additionalProperties && TypeGuard.IsSchema(schema.additionalProperties)) properties.push(`[key: string]: ${schemaToTypeScript(schema.additionalProperties)};`);
|
|
3115
|
-
if (properties.length === 0) return "{}";
|
|
3116
|
-
return `{\n${indent(properties.join("\n"))}\n}`;
|
|
3117
|
-
}
|
|
3118
|
-
return "unknown";
|
|
3119
|
-
}
|
|
3120
|
-
function generateTypeStubs(bindings, options = {}) {
|
|
3121
|
-
const { includeDescriptions = true } = options;
|
|
3122
|
-
const declarations = [];
|
|
3123
|
-
for (const [name, binding] of Object.entries(bindings)) {
|
|
3124
|
-
const inputTypeName = `${capitalize(name)}Input`;
|
|
3125
|
-
const outputTypeName = `${capitalize(name)}Output`;
|
|
3126
|
-
declarations.push(`type ${inputTypeName} = ${schemaToTypeScript(binding.inputSchema)};`);
|
|
3127
|
-
let outputTypeRef = "unknown";
|
|
3128
|
-
if (binding.outputSchema !== void 0) {
|
|
3129
|
-
declarations.push(`type ${outputTypeName} = ${schemaToTypeScript(binding.outputSchema)};`);
|
|
3130
|
-
outputTypeRef = outputTypeName;
|
|
3131
|
-
}
|
|
3132
|
-
const description = includeDescriptions && binding.description ? `/** ${binding.description} */\n` : "";
|
|
3133
|
-
declarations.push(`${description}declare function ${name}(input: ${inputTypeName}): Promise<${outputTypeRef}>;`);
|
|
3134
|
-
}
|
|
3135
|
-
return declarations.join("\n\n");
|
|
3136
|
-
}
|
|
3137
|
-
_CodeMode.generateTypeStubs = generateTypeStubs;
|
|
3138
|
-
function buildExampleSnippet() {
|
|
3139
|
-
return [
|
|
3140
|
-
"```typescript",
|
|
3141
|
-
"const numbers = [12, 24, 36];",
|
|
3142
|
-
"const total = numbers.reduce((sum, value) => sum + value, 0);",
|
|
3143
|
-
"",
|
|
3144
|
-
"return {",
|
|
3145
|
-
" count: numbers.length,",
|
|
3146
|
-
" average: total / numbers.length,",
|
|
3147
|
-
"};",
|
|
3148
|
-
"```"
|
|
3149
|
-
];
|
|
3150
|
-
}
|
|
3151
|
-
function generateSystemPrompt(config) {
|
|
3152
|
-
const fnPrefix = config.fnPrefix ?? toolFnPrefix;
|
|
3153
|
-
const bindings = toolsForBinding(config.tools, fnPrefix);
|
|
3154
|
-
const typeStubs = generateTypeStubs(bindings);
|
|
3155
|
-
return [
|
|
3156
|
-
"## Code Execution Tool",
|
|
3157
|
-
"",
|
|
3158
|
-
"You have access to `sandbox_execute_typescript` which runs TypeScript code in a sandboxed environment.",
|
|
3159
|
-
"",
|
|
3160
|
-
"### When to Use",
|
|
3161
|
-
"",
|
|
3162
|
-
"Use `sandbox_execute_typescript` when you need to:",
|
|
3163
|
-
"- Process data with loops, conditionals, or complex logic",
|
|
3164
|
-
"- Make multiple tool calls in parallel with `Promise.all(...)`",
|
|
3165
|
-
"- Transform, filter, or aggregate data",
|
|
3166
|
-
"- Perform calculations or data analysis",
|
|
3167
|
-
"",
|
|
3168
|
-
"For simple operations, prefer calling tools directly.",
|
|
3169
|
-
"",
|
|
3170
|
-
"### Available External APIs",
|
|
3171
|
-
"",
|
|
3172
|
-
"Inside your TypeScript code, you can call these async functions:",
|
|
3173
|
-
"",
|
|
3174
|
-
Object.entries(bindings).map(([name, binding]) => `- \`${name}(input)\`: ${binding.description}`).join("\n") || "- No external APIs available for this run.",
|
|
3175
|
-
"",
|
|
3176
|
-
"### Type Definitions",
|
|
3177
|
-
"",
|
|
3178
|
-
"```typescript",
|
|
3179
|
-
typeStubs,
|
|
3180
|
-
"```",
|
|
3181
|
-
"",
|
|
3182
|
-
"### Example",
|
|
3183
|
-
"",
|
|
3184
|
-
...buildExampleSnippet(),
|
|
3185
|
-
"",
|
|
3186
|
-
"### Important Notes",
|
|
3187
|
-
"",
|
|
3188
|
-
`- All\`${fnPrefix}\`*calls are async, so always use \`await\``,
|
|
3189
|
-
"- Return a value to pass results back to you",
|
|
3190
|
-
"- Use `console.log()` for debugging (logs are captured)",
|
|
3191
|
-
"- The sandbox is isolated - no network access or file system",
|
|
3192
|
-
"- Each execution is isolated and does not share state with previous runs",
|
|
3193
|
-
""
|
|
3194
|
-
].join("\n");
|
|
3195
|
-
}
|
|
3196
|
-
_CodeMode.generateSystemPrompt = generateSystemPrompt;
|
|
3197
|
-
async function transpileTypeScript(typescriptCode) {
|
|
3198
|
-
return (await transform([
|
|
3199
|
-
"(async () => {",
|
|
3200
|
-
" const __codemodeNormalizeError = (error: unknown) => {",
|
|
3201
|
-
" if (error instanceof Error) return { name: error.name, message: error.message, stack: error.stack };",
|
|
3202
|
-
" if (typeof error === 'object' && error !== null) {",
|
|
3203
|
-
" const candidate = error as { name?: unknown; message?: unknown; stack?: unknown };",
|
|
3204
|
-
" return {",
|
|
3205
|
-
" name: typeof candidate.name === 'string' ? candidate.name : 'Error',",
|
|
3206
|
-
" message:",
|
|
3207
|
-
" typeof candidate.message === 'string'",
|
|
3208
|
-
" ? candidate.message",
|
|
3209
|
-
" : JSON.stringify(candidate) || 'Unknown execution error',",
|
|
3210
|
-
" stack: typeof candidate.stack === 'string' ? candidate.stack : undefined,",
|
|
3211
|
-
" };",
|
|
3212
|
-
" }",
|
|
3213
|
-
" return { name: 'Error', message: String(error) };",
|
|
3214
|
-
" };",
|
|
3215
|
-
" try {",
|
|
3216
|
-
typescriptCode,
|
|
3217
|
-
" } catch (error) {",
|
|
3218
|
-
" throw __codemodeNormalizeError(error);",
|
|
3219
|
-
" }",
|
|
3220
|
-
"})()"
|
|
3221
|
-
].join("\n"), {
|
|
3222
|
-
loader: "ts",
|
|
3223
|
-
target: "es2022",
|
|
3224
|
-
sourcefile: "script.ts",
|
|
3225
|
-
minify: false,
|
|
3226
|
-
keepNames: false
|
|
3227
|
-
})).code;
|
|
3228
|
-
}
|
|
3229
|
-
function buildToolDescription(tools, fnPrefix = toolFnPrefix) {
|
|
3230
|
-
return [
|
|
3231
|
-
"Execute TypeScript code in a secure sandbox environment. ",
|
|
3232
|
-
"The code can use these external API functions:",
|
|
3233
|
-
"<functions>",
|
|
3234
|
-
` ${tools.map((tool) => `${fnPrefix}${tool.name}`).join("\n")}`,
|
|
3235
|
-
"</functions>",
|
|
3236
|
-
`All ${fnPrefix}* calls are async and must be awaited. `,
|
|
3237
|
-
"Return a value to pass results back. Use console.log() for debugging."
|
|
3238
|
-
].join("\n");
|
|
3239
|
-
}
|
|
3240
|
-
function createCodeModeTool(config) {
|
|
3241
|
-
if (config.tools.length === 0) throw new ToolDefinitionErr({ message: "at least one tool must be provided to `createCodeModeTool`" });
|
|
3242
|
-
return Agent.defineTool({
|
|
3243
|
-
name: "sandbox_execute_typescript",
|
|
3244
|
-
label: "Sandbox TypeScript",
|
|
3245
|
-
description: buildToolDescription(config.tools, config.fnPrefix),
|
|
3246
|
-
parameters: SandboxExecutionInputSchema,
|
|
3247
|
-
outputSchema: SandboxExecutionOutputSchema,
|
|
3248
|
-
errorSchema: SandboxExecutionErrorSchema,
|
|
3249
|
-
async execute(_callID, params, signal, onUpdate) {
|
|
3250
|
-
const bindings = toolsForBinding(config.tools, config.fnPrefix ?? toolFnPrefix);
|
|
3251
|
-
let context;
|
|
3252
|
-
try {
|
|
3253
|
-
await onUpdate?.({
|
|
3254
|
-
status: "running",
|
|
3255
|
-
partial: { content: [{
|
|
3256
|
-
type: "text",
|
|
3257
|
-
text: "Transpiling TypeScript for sandbox execution"
|
|
3258
|
-
}] }
|
|
3259
|
-
});
|
|
3260
|
-
const javascriptCode = await transpileTypeScript(params.typescriptCode);
|
|
3261
|
-
await onUpdate?.({
|
|
3262
|
-
status: "running",
|
|
3263
|
-
partial: { content: [{
|
|
3264
|
-
type: "text",
|
|
3265
|
-
text: "Executing code in sandbox runtime"
|
|
3266
|
-
}] }
|
|
3267
|
-
});
|
|
3268
|
-
context = await config.driver.createContext({
|
|
3269
|
-
bindings,
|
|
3270
|
-
timeout: config.timeout,
|
|
3271
|
-
memoryLimit: config.memoryLimit,
|
|
3272
|
-
signal
|
|
3273
|
-
});
|
|
3274
|
-
const executionResult = await context.execute(javascriptCode);
|
|
3275
|
-
if (executionResult.success) {
|
|
3276
|
-
const details = {
|
|
3277
|
-
result: executionResult.value,
|
|
3278
|
-
...executionResult.logs && executionResult.logs.length > 0 ? { logs: executionResult.logs } : {}
|
|
3279
|
-
};
|
|
3280
|
-
return {
|
|
3281
|
-
status: "completed",
|
|
3282
|
-
result: {
|
|
3283
|
-
content: [{
|
|
3284
|
-
type: "text",
|
|
3285
|
-
text: serializeForContent(details)
|
|
3286
|
-
}],
|
|
3287
|
-
details,
|
|
3288
|
-
isError: false
|
|
3289
|
-
}
|
|
3290
|
-
};
|
|
3291
|
-
}
|
|
3292
|
-
const details = {
|
|
3293
|
-
message: executionResult.error?.message || "sandbox execution failed",
|
|
3294
|
-
...executionResult.error?.name ? { name: executionResult.error.name } : {},
|
|
3295
|
-
...executionResult.error?.stack ? { stack: executionResult.error.stack } : {},
|
|
3296
|
-
...executionResult.error?.line != null ? { line: executionResult.error.line } : {},
|
|
3297
|
-
...executionResult.logs && executionResult.logs.length > 0 ? { logs: executionResult.logs } : {}
|
|
3298
|
-
};
|
|
3299
|
-
return {
|
|
3300
|
-
status: "error",
|
|
3301
|
-
result: {
|
|
3302
|
-
content: [{
|
|
3303
|
-
type: "text",
|
|
3304
|
-
text: serializeForContent(details)
|
|
3305
|
-
}],
|
|
3306
|
-
details,
|
|
3307
|
-
isError: true
|
|
3308
|
-
}
|
|
3309
|
-
};
|
|
3310
|
-
} catch (error) {
|
|
3311
|
-
const normalizedError = normalizeExecutionError(error);
|
|
3312
|
-
const details = {
|
|
3313
|
-
message: normalizedError.message,
|
|
3314
|
-
...normalizedError.name ? { name: normalizedError.name } : {},
|
|
3315
|
-
...normalizedError.stack ? { stack: normalizedError.stack } : {},
|
|
3316
|
-
...normalizedError.line != null ? { line: normalizedError.line } : {}
|
|
3317
|
-
};
|
|
3318
|
-
return {
|
|
3319
|
-
status: "error",
|
|
3320
|
-
result: {
|
|
3321
|
-
content: [{
|
|
3322
|
-
type: "text",
|
|
3323
|
-
text: serializeForContent(details)
|
|
3324
|
-
}],
|
|
3325
|
-
details,
|
|
3326
|
-
isError: true
|
|
3327
|
-
}
|
|
3328
|
-
};
|
|
3329
|
-
} finally {
|
|
3330
|
-
await context?.dispose();
|
|
3331
|
-
}
|
|
3332
|
-
}
|
|
3333
|
-
});
|
|
3334
|
-
}
|
|
3335
|
-
_CodeMode.createCodeModeTool = createCodeModeTool;
|
|
3336
|
-
async function create(config) {
|
|
3337
|
-
return {
|
|
3338
|
-
tool: createCodeModeTool(config),
|
|
3339
|
-
systemPrompt: generateSystemPrompt(config)
|
|
3340
|
-
};
|
|
3341
|
-
}
|
|
3342
|
-
_CodeMode.create = create;
|
|
3343
|
-
})(CodeMode || (CodeMode = {}));
|
|
3344
|
-
//#endregion
|
|
3345
|
-
//#region src/llm.ts
|
|
3346
|
-
const llmImpl = async (provider, model, overrides) => Model.getModel(provider, model, overrides);
|
|
3347
|
-
const llm = Object.assign(llmImpl, {
|
|
3348
|
-
model: Model.getModel,
|
|
3349
|
-
models: Model.getModels,
|
|
3350
|
-
providers: Model.getProviders,
|
|
3351
|
-
registry: Model.registry,
|
|
3352
|
-
supportsXhigh: Model.supportsXhigh,
|
|
3353
|
-
modelsAreEqual: Model.modelsAreEqual
|
|
3354
|
-
});
|
|
1405
|
+
//#region src/llm/register.ts
|
|
1406
|
+
registerAISDKProtocols();
|
|
3355
1407
|
//#endregion
|
|
3356
1408
|
//#region src/stream.ts
|
|
3357
|
-
const streamImpl = (model, context, options) =>
|
|
1409
|
+
const streamImpl = (model, context, options) => Protocol.stream(model, context, options);
|
|
3358
1410
|
/**
|
|
3359
1411
|
* Start a streaming assistant response for a model/context pair.
|
|
3360
1412
|
*
|
|
@@ -3362,20 +1414,65 @@ const streamImpl = (model, context, options) => Stream.stream(model, context, op
|
|
|
3362
1414
|
* Attached helpers:
|
|
3363
1415
|
*
|
|
3364
1416
|
* - `stream.complete(...)` resolves the final assistant message without manually iterating events.
|
|
3365
|
-
* - `stream.simple(...)` uses `Stream.SimpleOptions` for higher-level reasoning controls.
|
|
3366
|
-
* - `stream.completeSimple(...)` is the non-streaming counterpart to `stream.simple(...)`.
|
|
3367
1417
|
* - `stream.resolveProtocolProvider(...)` exposes protocol resolution for advanced integrations.
|
|
3368
1418
|
*/
|
|
3369
1419
|
const stream = Object.assign(streamImpl, {
|
|
3370
|
-
complete:
|
|
3371
|
-
|
|
3372
|
-
completeSimple: Stream.completeSimple,
|
|
3373
|
-
resolveProtocolProvider: Stream.resolveProtocolProvider
|
|
1420
|
+
complete: Protocol.complete,
|
|
1421
|
+
resolveProtocolProvider: Protocol.resolveProtocolProvider
|
|
3374
1422
|
});
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
1423
|
+
Protocol.complete;
|
|
1424
|
+
//#endregion
|
|
1425
|
+
//#region src/utils/validation.ts
|
|
1426
|
+
const validators = /* @__PURE__ */ new WeakMap();
|
|
1427
|
+
function getValidator(schema) {
|
|
1428
|
+
const existing = validators.get(schema);
|
|
1429
|
+
if (existing) return existing;
|
|
1430
|
+
const validator = Schema.Compile(schema);
|
|
1431
|
+
validators.set(schema, validator);
|
|
1432
|
+
return validator;
|
|
1433
|
+
}
|
|
1434
|
+
function errorPath(error) {
|
|
1435
|
+
if (error.instancePath) return error.instancePath.substring(1);
|
|
1436
|
+
const requiredProperties = error.params?.requiredProperties;
|
|
1437
|
+
if (Array.isArray(requiredProperties)) return requiredProperties.join(", ");
|
|
1438
|
+
return "root";
|
|
1439
|
+
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Validates an arbitrary value against a TypeBox schema and returns the coerced value.
|
|
1442
|
+
*/
|
|
1443
|
+
function validateSchema(schema, value, label) {
|
|
1444
|
+
const validator = getValidator(schema);
|
|
1445
|
+
const input = Value.Convert(schema, structuredClone(value));
|
|
1446
|
+
try {
|
|
1447
|
+
return validator.Parse(input);
|
|
1448
|
+
} catch {
|
|
1449
|
+
const [_result, validationErrors] = validator.Errors(input);
|
|
1450
|
+
const errors = validationErrors.map((err) => {
|
|
1451
|
+
return ` - ${errorPath(err)}: ${err.message}`;
|
|
1452
|
+
}).join("\n") || "Unknown Validation Error";
|
|
1453
|
+
throw new Error([
|
|
1454
|
+
`Validation Failed For ${label}`,
|
|
1455
|
+
`${errors}\n`,
|
|
1456
|
+
"Received Value:",
|
|
1457
|
+
`${JSON.stringify(value, null, 2)}\n`
|
|
1458
|
+
].join("\n"));
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Finds a tool by name and validates the tool call arguments against its TypeBox schema
|
|
1463
|
+
*/
|
|
1464
|
+
function validateToolCall(tools, toolExecution) {
|
|
1465
|
+
const tool = tools.find((t) => t.name === toolExecution.name);
|
|
1466
|
+
if (!tool) throw new Error(`Tool "${toolExecution.name}" not found`);
|
|
1467
|
+
return validateToolArguments(tool, toolExecution);
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Validates tool call arguments against the tool's TypeBox schema
|
|
1471
|
+
*/
|
|
1472
|
+
function validateToolArguments(tool, toolExecution) {
|
|
1473
|
+
return validateSchema(tool.parameters, toolExecution.rawArgs, `Tool "${toolExecution.name}"`);
|
|
1474
|
+
}
|
|
3378
1475
|
//#endregion
|
|
3379
|
-
export {
|
|
1476
|
+
export { Event, EventStream, Message, Model, Protocol, ThinkingBudgets, Type, createAssistantMessageEventStream, llm, stream, validateSchema, validateToolArguments, validateToolCall };
|
|
3380
1477
|
|
|
3381
1478
|
//# sourceMappingURL=index.mjs.map
|