@swifty.js/swifty 0.0.30 → 0.0.32
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 +60 -3
- package/dist/agent-2DUTUJFX.js +4 -0
- package/dist/anthropic-KR5MXB5I.js +4 -0
- package/dist/checker-RKAWOOXC.js +4 -0
- package/dist/chunk-2EV72T5X.js +4 -0
- package/dist/chunk-4YVJP2CO.js +4 -0
- package/dist/chunk-BWWNI2FK.js +121 -0
- package/dist/{chunk-K5ZK27BX.js → chunk-JMF2DWGY.js} +1 -1
- package/dist/chunk-LTFPTWX4.js +612 -0
- package/dist/chunk-NERVCUWE.js +4 -0
- package/dist/chunk-S35E7OYL.js +5 -0
- package/dist/{chunk-QFSCPD63.js → chunk-TCQ4EB4G.js} +1 -1
- package/dist/{chunk-C3WGLVVZ.js → chunk-TKQ5T5VO.js} +1 -1
- package/dist/chunk-TW7RHCDS.js +150 -0
- package/dist/lib/agent-3OEC4SOB.js +10 -0
- package/dist/lib/{anthropic-CL5IK7KN.js → anthropic-B33M2AVN.js} +5 -6
- package/dist/lib/{checker-BS4MK3O6.js → checker-QNMXPZ7C.js} +3 -4
- package/dist/lib/{chunk-OQIQOU5S.js → chunk-3OFLDUAW.js} +121 -1
- package/dist/lib/{chunk-EY7HE52Q.js → chunk-3XCGUKGJ.js} +18 -24
- package/dist/lib/{chunk-7QPDFSQE.js → chunk-4BPKIIQD.js} +29 -10
- package/dist/lib/{chunk-KG4MJGKQ.js → chunk-BCBD34D2.js} +2 -5
- package/dist/lib/{chunk-IYPTOY3Y.js → chunk-FODSMOWP.js} +40 -31
- package/dist/lib/{chunk-RMB3J46W.js → chunk-SOOSTGHI.js} +198 -37
- package/dist/lib/{chunk-I7OPU4K2.js → chunk-TJLAJGG4.js} +194 -34
- package/dist/lib/{chunk-OOSNCCI7.js → chunk-UH5M7FDP.js} +151 -152
- package/dist/lib/{chunk-PIL7M52F.js → chunk-XT67KGWE.js} +16 -3
- package/dist/lib/index.d.ts +2103 -1344
- package/dist/lib/index.js +11869 -9629
- package/dist/lib/{openai-LH4E7ZQS.js → openai-C2PZFGJ2.js} +3 -3
- package/dist/lib/{tool-filter-CS6W2GMU.js → tool-filter-IMIU7CW2.js} +3 -2
- package/dist/main.js +186 -187
- package/dist/{node-4LTSRXL2.js → node-GXMM4JG3.js} +1 -1
- package/dist/openai-M7B2TITO.js +34 -0
- package/dist/seatbelt-3GM2YGXV.js +5 -0
- package/dist/{server-IVIRQTO7.js → server-QMMIYNXW.js} +16 -23
- package/dist/tool-filter-7LLVAHD5.js +4 -0
- package/package.json +9 -12
- package/dist/agent-TCNIRVHD.js +0 -4
- package/dist/anthropic-7RIVSEDF.js +0 -4
- package/dist/checker-3LHDOATB.js +0 -4
- package/dist/chunk-2IBMB3ZM.js +0 -150
- package/dist/chunk-AQ3A5CF4.js +0 -5
- package/dist/chunk-E55KH72M.js +0 -4
- package/dist/chunk-FA26MQ7K.js +0 -257
- package/dist/chunk-OTVZGPHD.js +0 -121
- package/dist/chunk-QCKJLO6X.js +0 -4
- package/dist/chunk-TKADLB2Q.js +0 -4
- package/dist/chunk-VA64DJNN.js +0 -4
- package/dist/lib/agent-IRY7KR5D.js +0 -11
- package/dist/lib/chunk-GHF2PSEW.js +0 -8
- package/dist/openai-RZLCY55V.js +0 -34
- package/dist/seatbelt-YXUQ5XR3.js +0 -5
- package/dist/tool-filter-CG3KGQQW.js +0 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createChildLogger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3XCGUKGJ.js";
|
|
4
4
|
|
|
5
5
|
// src/llm/errors.ts
|
|
6
6
|
var LLMError = class extends Error {
|
|
@@ -288,6 +288,10 @@ function loadSingleFile(path) {
|
|
|
288
288
|
const parsed2 = safeParse(z.array(MCPServerConfigSchema), raw.mcp_servers);
|
|
289
289
|
if (parsed2.success) {
|
|
290
290
|
mcpServers = parsed2.data;
|
|
291
|
+
} else {
|
|
292
|
+
throw new ConfigError(
|
|
293
|
+
`Invalid MCP server configuration in ${path}: ${getParseErrorMessage(parsed2.error)}`
|
|
294
|
+
);
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
297
|
if ("hooks" in raw) {
|
|
@@ -323,6 +327,7 @@ function validateProviders(config) {
|
|
|
323
327
|
throw new ConfigError("At least one provider MUST be configured.");
|
|
324
328
|
}
|
|
325
329
|
const requiredFields = ["name", "protocol", "base_url", "model"];
|
|
330
|
+
const baseUrls = /* @__PURE__ */ new Map();
|
|
326
331
|
for (let i = 0; i < config.providers.length; i++) {
|
|
327
332
|
const p = config.providers[i];
|
|
328
333
|
const values = {
|
|
@@ -340,11 +345,123 @@ function validateProviders(config) {
|
|
|
340
345
|
`Provider #${String(i + 1)}: invalid protocol '${p.protocol}', MUST be one of: ${Array.from(VALID_PROTOCOLS).join(", ")}`
|
|
341
346
|
);
|
|
342
347
|
}
|
|
348
|
+
const previous = baseUrls.get(p.base_url);
|
|
349
|
+
if (previous !== void 0) {
|
|
350
|
+
throw new ConfigError(
|
|
351
|
+
`Provider #${String(i + 1)}: duplicate base_url '${p.base_url}' (already used by provider #${String(previous + 1)}).`
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
baseUrls.set(p.base_url, i);
|
|
343
355
|
}
|
|
344
356
|
}
|
|
357
|
+
function validateMcpServers(config) {
|
|
358
|
+
const names = /* @__PURE__ */ new Map();
|
|
359
|
+
for (let i = 0; i < config.mcp_servers.length; i++) {
|
|
360
|
+
const server = config.mcp_servers[i];
|
|
361
|
+
const position = `MCP server #${String(i + 1)}`;
|
|
362
|
+
if (!server.name.trim()) {
|
|
363
|
+
throw new ConfigError(`${position}: name must not be empty.`);
|
|
364
|
+
}
|
|
365
|
+
const previous = names.get(server.name);
|
|
366
|
+
if (previous !== void 0) {
|
|
367
|
+
throw new ConfigError(
|
|
368
|
+
`${position}: duplicate name '${server.name}' (already used by MCP server #${String(previous + 1)}).`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
names.set(server.name, i);
|
|
372
|
+
const hasCommand = Boolean(server.command?.trim());
|
|
373
|
+
const hasUrl = Boolean(server.url?.trim());
|
|
374
|
+
if (hasCommand === hasUrl) {
|
|
375
|
+
throw new ConfigError(
|
|
376
|
+
`${position} '${server.name}': configure exactly one of command or url.`
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
if (hasCommand && server.transport && server.transport !== "stdio") {
|
|
380
|
+
throw new ConfigError(`${position} '${server.name}': command servers must use stdio.`);
|
|
381
|
+
}
|
|
382
|
+
if (hasUrl && server.transport && !["http", "sse"].includes(server.transport)) {
|
|
383
|
+
throw new ConfigError(`${position} '${server.name}': URL transport must be http or sse.`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
var PROJECT_MCP_FILENAME = ".mcp.json";
|
|
388
|
+
var McpJsonEntrySchema = z.looseObject({
|
|
389
|
+
command: z.string().optional(),
|
|
390
|
+
args: z.array(z.string()).optional(),
|
|
391
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
392
|
+
type: z.enum(["stdio", "sse", "http"]).optional(),
|
|
393
|
+
url: z.string().optional(),
|
|
394
|
+
headers: z.record(z.string(), z.string()).optional()
|
|
395
|
+
});
|
|
396
|
+
var McpJsonFileSchema = z.looseObject({
|
|
397
|
+
// Parse entries independently below so one bad server does not disable every
|
|
398
|
+
// valid server in the project file.
|
|
399
|
+
mcpServers: z.record(z.string(), z.unknown()).default({})
|
|
400
|
+
});
|
|
401
|
+
function mcpServerFromJsonEntry(name, entry) {
|
|
402
|
+
const transport = entry.type ?? (entry.command !== void 0 ? "stdio" : "http");
|
|
403
|
+
if (transport === "stdio") {
|
|
404
|
+
if (!entry.command || entry.url !== void 0) {
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
return { name, command: entry.command, args: entry.args, env: entry.env };
|
|
408
|
+
}
|
|
409
|
+
if (!entry.url || entry.command !== void 0) {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
return { name, url: entry.url, transport, headers: entry.headers };
|
|
413
|
+
}
|
|
414
|
+
function loadProjectMcpServers(workDir) {
|
|
415
|
+
const path = join(workDir, PROJECT_MCP_FILENAME);
|
|
416
|
+
if (!existsSync(path)) {
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
let raw;
|
|
420
|
+
try {
|
|
421
|
+
raw = JSON.parse(readFileSync(path, "utf-8"));
|
|
422
|
+
} catch (err) {
|
|
423
|
+
log.error({ err, path }, "invalid .mcp.json");
|
|
424
|
+
return [];
|
|
425
|
+
}
|
|
426
|
+
const parsed = safeParse(McpJsonFileSchema, raw);
|
|
427
|
+
if (!parsed.success) {
|
|
428
|
+
log.error({ error: parsed.error, path }, "invalid .mcp.json");
|
|
429
|
+
return [];
|
|
430
|
+
}
|
|
431
|
+
const servers = [];
|
|
432
|
+
for (const [name, rawEntry] of Object.entries(parsed.data.mcpServers)) {
|
|
433
|
+
const parsedEntry = safeParse(McpJsonEntrySchema, rawEntry);
|
|
434
|
+
if (!name.trim() || !parsedEntry.success) {
|
|
435
|
+
log.warn(
|
|
436
|
+
{ name, path, error: parsedEntry.success ? void 0 : parsedEntry.error },
|
|
437
|
+
"skipping invalid .mcp.json server entry"
|
|
438
|
+
);
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
const server = mcpServerFromJsonEntry(name, parsedEntry.data);
|
|
442
|
+
if (server) {
|
|
443
|
+
servers.push(server);
|
|
444
|
+
} else {
|
|
445
|
+
log.warn({ name, path }, "skipping invalid .mcp.json server entry");
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return servers;
|
|
449
|
+
}
|
|
450
|
+
function withProjectMcpServers(config, workDir) {
|
|
451
|
+
const projectServers = loadProjectMcpServers(workDir);
|
|
452
|
+
if (projectServers.length === 0) {
|
|
453
|
+
return config;
|
|
454
|
+
}
|
|
455
|
+
const known = new Set(config.mcp_servers.map((s) => s.name));
|
|
456
|
+
return {
|
|
457
|
+
...config,
|
|
458
|
+
mcp_servers: [...config.mcp_servers, ...projectServers.filter((s) => !known.has(s.name))]
|
|
459
|
+
};
|
|
460
|
+
}
|
|
345
461
|
function loadConfig(path, options = {}) {
|
|
346
462
|
if (path) {
|
|
347
463
|
const config2 = loadSingleFile(path);
|
|
464
|
+
validateMcpServers(config2);
|
|
348
465
|
if (!options.allowEmptyProviders || config2.providers.length > 0) {
|
|
349
466
|
validateProviders(config2);
|
|
350
467
|
}
|
|
@@ -358,6 +475,7 @@ function loadConfig(path, options = {}) {
|
|
|
358
475
|
throw new ConfigError(`No config file found, expected ${candidate}.`);
|
|
359
476
|
}
|
|
360
477
|
const config = loadSingleFile(candidate);
|
|
478
|
+
validateMcpServers(config);
|
|
361
479
|
if (!options.allowEmptyProviders || config.providers.length > 0) {
|
|
362
480
|
validateProviders(config);
|
|
363
481
|
}
|
|
@@ -444,6 +562,8 @@ export {
|
|
|
444
562
|
resolveAPIKey,
|
|
445
563
|
HookConfigSchema,
|
|
446
564
|
forkEnabled,
|
|
565
|
+
loadProjectMcpServers,
|
|
566
|
+
withProjectMcpServers,
|
|
447
567
|
loadConfig,
|
|
448
568
|
INTERRUPTED_TOOL_RESULT,
|
|
449
569
|
REJECTED_TOOL_RESULT,
|
|
@@ -228,7 +228,7 @@ function errSerializer(err) {
|
|
|
228
228
|
return { message: safeStringify(err), value: err };
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
// src/utils/
|
|
231
|
+
// src/utils/utils.ts
|
|
232
232
|
var log = createChildLogger({ module: "utils" });
|
|
233
233
|
function contentToText(content) {
|
|
234
234
|
if (typeof content === "string") {
|
|
@@ -336,29 +336,23 @@ function boolArg(args, key, fallback) {
|
|
|
336
336
|
}
|
|
337
337
|
return fallback ?? Boolean(v);
|
|
338
338
|
}
|
|
339
|
-
function
|
|
340
|
-
if (
|
|
341
|
-
return
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
const left = [];
|
|
349
|
-
const right = [];
|
|
350
|
-
const equal = [];
|
|
351
|
-
for (const item of arr) {
|
|
352
|
-
const result = compare(item, pivot);
|
|
353
|
-
if (result < 0) {
|
|
354
|
-
left.push(item);
|
|
355
|
-
} else if (result > 0) {
|
|
356
|
-
right.push(item);
|
|
357
|
-
} else {
|
|
358
|
-
equal.push(item);
|
|
359
|
-
}
|
|
339
|
+
function formatToolArgs(args) {
|
|
340
|
+
if (args.command) {
|
|
341
|
+
return truncate(strArg(args, "command"), 80);
|
|
342
|
+
}
|
|
343
|
+
if (args.file_path) {
|
|
344
|
+
return truncate(strArg(args, "file_path"), 80);
|
|
345
|
+
}
|
|
346
|
+
if (args.pattern) {
|
|
347
|
+
return truncate(strArg(args, "pattern"), 80);
|
|
360
348
|
}
|
|
361
|
-
|
|
349
|
+
if (args.description) {
|
|
350
|
+
return truncate(strArg(args, "description"), 80);
|
|
351
|
+
}
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
function truncate(value, max) {
|
|
355
|
+
return value.length > max ? `${value.slice(0, max)}\u2026` : value;
|
|
362
356
|
}
|
|
363
357
|
|
|
364
358
|
export {
|
|
@@ -380,5 +374,5 @@ export {
|
|
|
380
374
|
strList,
|
|
381
375
|
strArg,
|
|
382
376
|
boolArg,
|
|
383
|
-
|
|
377
|
+
formatToolArgs
|
|
384
378
|
};
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MCP_CALL_TOOL_NAME,
|
|
3
|
-
TOOL_SEARCH_TOOL_NAME
|
|
4
|
-
} from "./chunk-GHF2PSEW.js";
|
|
5
|
-
|
|
6
1
|
// src/tools/registry.ts
|
|
7
2
|
var ToolRegistry = class {
|
|
8
3
|
tools = /* @__PURE__ */ new Map();
|
|
@@ -26,26 +21,44 @@ var ToolRegistry = class {
|
|
|
26
21
|
register(tool) {
|
|
27
22
|
this.tools.set(tool.name, tool);
|
|
28
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Removes a tool and forgets its discovery state, so a re-registered tool
|
|
26
|
+
* with the same name starts deferred again. Used by /mcp reload to drop
|
|
27
|
+
* tools of servers that disappeared from the config.
|
|
28
|
+
*/
|
|
29
|
+
unregister(name) {
|
|
30
|
+
this.tools.delete(name);
|
|
31
|
+
this.discovered.delete(name);
|
|
32
|
+
}
|
|
29
33
|
get(name) {
|
|
30
34
|
return this.tools.get(name);
|
|
31
35
|
}
|
|
32
36
|
listTools() {
|
|
33
37
|
return [...this.tools.values()];
|
|
34
38
|
}
|
|
35
|
-
getAllSchemas(protocol
|
|
36
|
-
const
|
|
39
|
+
getAllSchemas(protocol, filter) {
|
|
40
|
+
const resolvedProtocol = protocol ?? "anthropic";
|
|
41
|
+
const isOpenAI = resolvedProtocol === "openai" || resolvedProtocol === "openai-compat";
|
|
37
42
|
const native = this.mcpLoadingMode === "native" && !isOpenAI;
|
|
38
43
|
const schemas = [];
|
|
39
44
|
for (const tool of this.tools.values()) {
|
|
40
|
-
if (
|
|
45
|
+
if (filter && !filter(tool.name)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (tool.name === "ToolSearch" && !this.exposeToolSearch || tool.name === "McpCall" && !this.exposeMcpCall) {
|
|
41
49
|
continue;
|
|
42
50
|
}
|
|
43
51
|
const deferred = Boolean(tool.deferred) && !this.discovered.has(tool.name);
|
|
44
52
|
if (deferred && !native) {
|
|
45
53
|
continue;
|
|
46
54
|
}
|
|
55
|
+
const providerSchema = protocol ? tool.providerSchema?.(resolvedProtocol) : void 0;
|
|
56
|
+
if (providerSchema) {
|
|
57
|
+
schemas.push(providerSchema);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
47
60
|
const s = tool.schema();
|
|
48
|
-
if (
|
|
61
|
+
if (resolvedProtocol === "openai") {
|
|
49
62
|
schemas.push({
|
|
50
63
|
strict: s.strict ?? false,
|
|
51
64
|
type: "function",
|
|
@@ -53,7 +66,7 @@ var ToolRegistry = class {
|
|
|
53
66
|
description: s.description,
|
|
54
67
|
parameters: s.input_schema
|
|
55
68
|
});
|
|
56
|
-
} else if (
|
|
69
|
+
} else if (resolvedProtocol === "openai-compat") {
|
|
57
70
|
schemas.push({
|
|
58
71
|
type: "function",
|
|
59
72
|
function: {
|
|
@@ -120,11 +133,13 @@ var ToolRegistry = class {
|
|
|
120
133
|
};
|
|
121
134
|
|
|
122
135
|
// src/subagent/tool-filter.ts
|
|
136
|
+
var MAIN_AGENT_ONLY_TOOLS = /* @__PURE__ */ new Set(["ComputerUse"]);
|
|
123
137
|
var SUBAGENT_DISALLOWED_TOOLS = /* @__PURE__ */ new Set([
|
|
124
138
|
"ExitPlanMode",
|
|
125
139
|
"Agent",
|
|
126
140
|
// Prevents recursive spawning of subagents
|
|
127
141
|
"AskUserQuestion",
|
|
142
|
+
...MAIN_AGENT_ONLY_TOOLS,
|
|
128
143
|
"TaskStop"
|
|
129
144
|
]);
|
|
130
145
|
var TEAMMATE_DISALLOWED_TOOLS = /* @__PURE__ */ new Set(["TeamCreate", "TeamDelete"]);
|
|
@@ -193,6 +208,9 @@ function cloneRegistryForFork(registry) {
|
|
|
193
208
|
const forked = new ToolRegistry();
|
|
194
209
|
forked.mcpLoadingMode = registry.mcpLoadingMode;
|
|
195
210
|
for (const tool of registry.listTools()) {
|
|
211
|
+
if (MAIN_AGENT_ONLY_TOOLS.has(tool.name)) {
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
196
214
|
if (tool.name === "Agent" && "querySource" in tool) {
|
|
197
215
|
const clone = Object.create(
|
|
198
216
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
@@ -210,6 +228,7 @@ function cloneRegistryForFork(registry) {
|
|
|
210
228
|
|
|
211
229
|
export {
|
|
212
230
|
ToolRegistry,
|
|
231
|
+
MAIN_AGENT_ONLY_TOOLS,
|
|
213
232
|
SUBAGENT_DISALLOWED_TOOLS,
|
|
214
233
|
TEAMMATE_DISALLOWED_TOOLS,
|
|
215
234
|
CUSTOM_AGENT_DISALLOWED_TOOLS,
|
|
@@ -3,10 +3,7 @@ import {
|
|
|
3
3
|
asRecord,
|
|
4
4
|
createChildLogger,
|
|
5
5
|
strArg
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
MCP_CALL_TOOL_NAME
|
|
9
|
-
} from "./chunk-GHF2PSEW.js";
|
|
6
|
+
} from "./chunk-3XCGUKGJ.js";
|
|
10
7
|
|
|
11
8
|
// src/mcp/tool-wrapper.ts
|
|
12
9
|
var log = createChildLogger({ module: "mcp" });
|
|
@@ -148,7 +145,7 @@ var McpCallTool = class {
|
|
|
148
145
|
this.registry = registry;
|
|
149
146
|
}
|
|
150
147
|
registry;
|
|
151
|
-
name =
|
|
148
|
+
name = "McpCall";
|
|
152
149
|
description = "Invoke a tool on a connected MCP server. Call ToolSearch first to load the tool's schema, then pass its arguments here exactly as that schema requires, using the same JSON types.";
|
|
153
150
|
category = "command";
|
|
154
151
|
// This tool must stay in tools[] itself, otherwise the model has no entry point
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normalizeToolResultContentBlock
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XT67KGWE.js";
|
|
4
|
+
import {
|
|
5
|
+
MCP_TOOL_PREFIX,
|
|
6
|
+
isMcpToolLike
|
|
7
|
+
} from "./chunk-BCBD34D2.js";
|
|
4
8
|
import {
|
|
5
9
|
AuthenticationError,
|
|
6
10
|
ContextTooLongError,
|
|
@@ -17,11 +21,7 @@ import {
|
|
|
17
21
|
thinkingBudgetForLevel,
|
|
18
22
|
toAnthropicThinkingEffort,
|
|
19
23
|
toReasoningEffort
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import {
|
|
22
|
-
MCP_TOOL_PREFIX,
|
|
23
|
-
isMcpToolLike
|
|
24
|
-
} from "./chunk-KG4MJGKQ.js";
|
|
24
|
+
} from "./chunk-3OFLDUAW.js";
|
|
25
25
|
import {
|
|
26
26
|
asErrorString,
|
|
27
27
|
asRecord,
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
createChildLogger,
|
|
31
31
|
isRecord,
|
|
32
32
|
strArg
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-3XCGUKGJ.js";
|
|
34
34
|
|
|
35
35
|
// src/llm/anthropic.ts
|
|
36
36
|
import Anthropic from "@anthropic-ai/sdk";
|
|
@@ -112,7 +112,23 @@ function markToolsForCache(tools) {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
function needsToolSearchBeta(toolSchemas) {
|
|
115
|
-
return toolSchemas.some((
|
|
115
|
+
return toolSchemas.some((schema) => "defer_loading" in schema && schema.defer_loading === true);
|
|
116
|
+
}
|
|
117
|
+
var COMPUTER_USE_BETA = "computer-use-2025-11-24";
|
|
118
|
+
function toAnthropicToolSchema(schema) {
|
|
119
|
+
if ("type" in schema && schema.type === "computer_20251124") {
|
|
120
|
+
return { ...schema };
|
|
121
|
+
}
|
|
122
|
+
if ("input_schema" in schema) {
|
|
123
|
+
const tool = schema;
|
|
124
|
+
const { cache_control: cacheControl, ...rest } = tool;
|
|
125
|
+
return {
|
|
126
|
+
...rest,
|
|
127
|
+
type: "custom",
|
|
128
|
+
...tool.defer_loading !== true && cacheControl ? { cache_control: cacheControl } : {}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
throw new Error("Anthropic received a tool schema serialized for another protocol.");
|
|
116
132
|
}
|
|
117
133
|
var log = createChildLogger({ module: "llm" });
|
|
118
134
|
var MODEL_FETCH_TIMEOUT_MS = 3e3;
|
|
@@ -196,7 +212,7 @@ function buildAnthropicMessages(messages) {
|
|
|
196
212
|
type: "tool_use",
|
|
197
213
|
// tool use **request**
|
|
198
214
|
id: tu.toolUseId,
|
|
199
|
-
name: tu.toolName,
|
|
215
|
+
name: tu.toolName === "ComputerUse" ? "computer" : tu.toolName,
|
|
200
216
|
input: tu.arguments
|
|
201
217
|
});
|
|
202
218
|
}
|
|
@@ -256,6 +272,7 @@ function buildAnthropicMessages(messages) {
|
|
|
256
272
|
return result;
|
|
257
273
|
}
|
|
258
274
|
var AnthropicClient = class {
|
|
275
|
+
protocol = "anthropic";
|
|
259
276
|
client;
|
|
260
277
|
model;
|
|
261
278
|
/** Effective logical level for budget or explicitly configured adaptive mode. */
|
|
@@ -301,23 +318,10 @@ var AnthropicClient = class {
|
|
|
301
318
|
async *stream(conversation, toolSchemas, abortSignal) {
|
|
302
319
|
const messages = buildAnthropicMessages(ensureToolPairing(conversation.getMessages()));
|
|
303
320
|
const sendToolSearchBeta = needsToolSearchBeta(toolSchemas);
|
|
304
|
-
const antToolSchemas = toolSchemas.map(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
// Preserve constraints and definitions, not just properties/required.
|
|
309
|
-
input_schema: s.input_schema
|
|
310
|
-
};
|
|
311
|
-
if (s.strict !== void 0) {
|
|
312
|
-
tool.strict = s.strict;
|
|
313
|
-
}
|
|
314
|
-
if (s.defer_loading === true) {
|
|
315
|
-
tool.defer_loading = true;
|
|
316
|
-
} else if (s.cache_control) {
|
|
317
|
-
tool.cache_control = s.cache_control;
|
|
318
|
-
}
|
|
319
|
-
return tool;
|
|
320
|
-
});
|
|
321
|
+
const antToolSchemas = toolSchemas.map(toAnthropicToolSchema);
|
|
322
|
+
const sendComputerUseBeta = antToolSchemas.some(
|
|
323
|
+
(schema) => "type" in schema && schema.type === "computer_20251124"
|
|
324
|
+
);
|
|
321
325
|
markToolsForCache(antToolSchemas);
|
|
322
326
|
markLastUserTailForCache(messages);
|
|
323
327
|
const params = {
|
|
@@ -335,7 +339,10 @@ var AnthropicClient = class {
|
|
|
335
339
|
}
|
|
336
340
|
],
|
|
337
341
|
messages,
|
|
338
|
-
...antToolSchemas.length > 0 ?
|
|
342
|
+
...antToolSchemas.length > 0 ? (
|
|
343
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
344
|
+
{ tools: antToolSchemas }
|
|
345
|
+
) : {}
|
|
339
346
|
};
|
|
340
347
|
const level = this.getThinkingLevel();
|
|
341
348
|
if (this.config.reasoning !== false) {
|
|
@@ -369,11 +376,13 @@ var AnthropicClient = class {
|
|
|
369
376
|
let thinkingSignature = "";
|
|
370
377
|
let inThinking = false;
|
|
371
378
|
try {
|
|
379
|
+
const betas = [
|
|
380
|
+
...sendToolSearchBeta ? [NATIVE_TOOL_USE_BETA] : [],
|
|
381
|
+
...sendComputerUseBeta ? [COMPUTER_USE_BETA] : []
|
|
382
|
+
];
|
|
372
383
|
const response = this.client.messages.stream(params, {
|
|
373
384
|
...abortSignal ? { signal: abortSignal } : {},
|
|
374
|
-
|
|
375
|
-
// Only the official endpoint reaches this code path (see mcp/strategy).
|
|
376
|
-
...sendToolSearchBeta ? { headers: { "anthropic-beta": NATIVE_TOOL_USE_BETA } } : {}
|
|
385
|
+
...betas.length > 0 ? { headers: { "anthropic-beta": betas.join(",") } } : {}
|
|
377
386
|
});
|
|
378
387
|
let currentToolName = "";
|
|
379
388
|
let currentToolId = "";
|
|
@@ -388,7 +397,7 @@ var AnthropicClient = class {
|
|
|
388
397
|
thinkingSignature = "";
|
|
389
398
|
} else if (block.type === "tool_use") {
|
|
390
399
|
currentToolId = block.id;
|
|
391
|
-
currentToolName = block.name;
|
|
400
|
+
currentToolName = block.name === "computer" ? "ComputerUse" : block.name;
|
|
392
401
|
jsonAccumulate = "";
|
|
393
402
|
yield {
|
|
394
403
|
type: "tool_call_start",
|