@swifty.js/swifty 0.0.27 → 0.0.29
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 +47 -37
- package/dist/agent-YR6YK26C.js +4 -0
- package/dist/anthropic-5GRR5JCT.js +4 -0
- package/dist/checker-N5TIJEN5.js +4 -0
- package/dist/chunk-D34FUVGU.js +4 -0
- package/dist/{chunk-UGJVMFGH.js → chunk-K5ZK27BX.js} +1 -1
- package/dist/chunk-LIMEBKCY.js +408 -0
- package/dist/chunk-OTVZGPHD.js +121 -0
- package/dist/chunk-POHIQUFP.js +301 -0
- package/dist/chunk-QCKJLO6X.js +4 -0
- package/dist/chunk-QFSCPD63.js +4 -0
- package/dist/chunk-TMEX7RFA.js +4 -0
- package/dist/chunk-Y6SQB5FG.js +4 -0
- package/dist/lib/agent-5WEKVRTD.js +11 -0
- package/dist/lib/{anthropic-RYPJDHQM.js → anthropic-KWO3KLNV.js} +4 -5
- package/dist/lib/{checker-6BW4222R.js → checker-AXHPKVBY.js} +2 -2
- package/dist/lib/{chunk-HK2Z6WP4.js → chunk-2IVEVG5N.js} +5 -1
- package/dist/lib/{chunk-XFSN4LMA.js → chunk-3FBS5NB7.js} +71 -18
- package/dist/lib/{chunk-GNI7YX6F.js → chunk-DJ6AILPN.js} +70 -24
- package/dist/lib/chunk-GCY44T7S.js +2346 -0
- package/dist/lib/{chunk-PZ42NAFA.js → chunk-KG4MJGKQ.js} +19 -21
- package/dist/lib/{chunk-2AUSNVIB.js → chunk-KZSBR4FO.js} +44 -37
- package/dist/lib/chunk-PIL7M52F.js +127 -0
- package/dist/lib/chunk-Z4CYHTII.js +392 -0
- package/dist/lib/index.d.ts +227 -132
- package/dist/lib/index.js +2195 -1602
- package/dist/lib/{openai-VX5VBXZ4.js → openai-PBF7EWNJ.js} +2 -3
- package/dist/lib/{tool-filter-VF7TZRE5.js → tool-filter-R6HDDJHE.js} +1 -1
- package/dist/main.js +203 -194
- package/dist/{openai-5FDSLJNM.js → openai-QQ2K7GPF.js} +14 -14
- package/dist/{server-F666APPN.js → server-G23HCFLI.js} +21 -21
- package/dist/{tool-filter-NO7I3HFD.js → tool-filter-VBP6WOGO.js} +1 -1
- package/package.json +2 -2
- package/dist/agent-OMC6YIMW.js +0 -4
- package/dist/anthropic-T5K4BQPB.js +0 -4
- package/dist/checker-TOQVEG3P.js +0 -4
- package/dist/chunk-5I2WXSGV.js +0 -90
- package/dist/chunk-A2VR3BC4.js +0 -4
- package/dist/chunk-A57FEYSN.js +0 -4
- package/dist/chunk-BRC5L644.js +0 -130
- package/dist/chunk-FZPTNGTU.js +0 -4
- package/dist/chunk-G6YIQW3Z.js +0 -238
- package/dist/chunk-I2XG2PXV.js +0 -4
- package/dist/chunk-LVSHXIBK.js +0 -389
- package/dist/chunk-SULWNDNC.js +0 -4
- package/dist/chunk-WO6DL7OB.js +0 -35
- package/dist/lib/agent-U7MIUCKT.js +0 -9
- package/dist/lib/chunk-2QILP24G.js +0 -1120
- package/dist/lib/chunk-3LU4APFB.js +0 -339
- package/dist/lib/chunk-OO2CLOEE.js +0 -88
- package/dist/lib/chunk-RKJYTYQM.js +0 -1285
|
@@ -1,339 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createChildLogger
|
|
3
|
-
} from "./chunk-EY7HE52Q.js";
|
|
4
|
-
|
|
5
|
-
// src/config/config.ts
|
|
6
|
-
import { existsSync, readFileSync } from "fs";
|
|
7
|
-
import { homedir } from "os";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
import { safeParse } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
10
|
-
import yaml from "js-yaml";
|
|
11
|
-
import { z } from "zod";
|
|
12
|
-
var log = createChildLogger({ module: "config" });
|
|
13
|
-
var ENV_KEY_MAP = {
|
|
14
|
-
anthropic: "ANTHROPIC_API_KEY",
|
|
15
|
-
openai: "OPENAI_API_KEY",
|
|
16
|
-
"openai-compat": "OPENAI_API_KEY"
|
|
17
|
-
};
|
|
18
|
-
function isKeyofTypeofEnvKeyMap(k) {
|
|
19
|
-
return VALID_PROTOCOLS.has(k);
|
|
20
|
-
}
|
|
21
|
-
var VALID_PROTOCOLS = new Set(Object.keys(ENV_KEY_MAP));
|
|
22
|
-
var ConfigError = class extends Error {
|
|
23
|
-
constructor(message) {
|
|
24
|
-
super(message);
|
|
25
|
-
this.name = "ConfigError";
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
var ProviderConfigSchema = z.object({
|
|
29
|
-
name: z.string(),
|
|
30
|
-
/**
|
|
31
|
-
* enum: ["anthropic", "openai", "openai-compat"]
|
|
32
|
-
*/
|
|
33
|
-
protocol: z.enum(["anthropic", "openai", "openai-compat"]),
|
|
34
|
-
base_url: z.string(),
|
|
35
|
-
model: z.string(),
|
|
36
|
-
api_key: z.string().optional(),
|
|
37
|
-
thinking: z.boolean().optional(),
|
|
38
|
-
context_window: z.coerce.number().optional(),
|
|
39
|
-
max_output_tokens: z.coerce.number().optional()
|
|
40
|
-
});
|
|
41
|
-
var MODEL_CONTEXT_WINDOWS = [
|
|
42
|
-
// 1M-token variants (e.g. "...-1m") come first so they win over the base family.
|
|
43
|
-
["1m", 1e6],
|
|
44
|
-
["gpt-4.1", 1e6],
|
|
45
|
-
["gpt-4o", 128e3],
|
|
46
|
-
["gpt-4-turbo", 128e3],
|
|
47
|
-
["o1", 2e5],
|
|
48
|
-
["o3", 2e5],
|
|
49
|
-
["o4", 2e5],
|
|
50
|
-
["gpt-3.5", 16385],
|
|
51
|
-
["claude", 2e5]
|
|
52
|
-
];
|
|
53
|
-
function lookupModelContextWindow(model) {
|
|
54
|
-
const model_ = model.toLowerCase();
|
|
55
|
-
for (const [m, window] of MODEL_CONTEXT_WINDOWS) {
|
|
56
|
-
if (model_.includes(m)) {
|
|
57
|
-
return window;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return model_.includes("claude") ? 2e5 : 128e3;
|
|
61
|
-
}
|
|
62
|
-
function getContextWindow(p) {
|
|
63
|
-
if (p.context_window && p.context_window > 0) {
|
|
64
|
-
return p.context_window;
|
|
65
|
-
}
|
|
66
|
-
return lookupModelContextWindow(p.model);
|
|
67
|
-
}
|
|
68
|
-
var fetchedWindowCache = /* @__PURE__ */ new Map();
|
|
69
|
-
async function getContextWindowAsync(p, fetcher) {
|
|
70
|
-
if (p.context_window && p.context_window > 0) {
|
|
71
|
-
return p.context_window;
|
|
72
|
-
}
|
|
73
|
-
if (p.protocol === "anthropic") {
|
|
74
|
-
const key = `${p.name}-${p.model}`;
|
|
75
|
-
let fetched = fetchedWindowCache.get(key);
|
|
76
|
-
if (fetched === void 0) {
|
|
77
|
-
try {
|
|
78
|
-
const fn = fetcher ?? (await import("./anthropic-RYPJDHQM.js")).fetchModelContextWindow;
|
|
79
|
-
fetched = await fn(p);
|
|
80
|
-
} catch (err) {
|
|
81
|
-
log.error({ err }, "config operation failed");
|
|
82
|
-
fetched = 0;
|
|
83
|
-
}
|
|
84
|
-
fetchedWindowCache.set(key, fetched);
|
|
85
|
-
}
|
|
86
|
-
if (fetched && fetched > 0) {
|
|
87
|
-
return fetched;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return lookupModelContextWindow(p.model);
|
|
91
|
-
}
|
|
92
|
-
function _resetContextWindowCache() {
|
|
93
|
-
fetchedWindowCache.clear();
|
|
94
|
-
}
|
|
95
|
-
function getMaxOutputTokens(p) {
|
|
96
|
-
if (p.max_output_tokens && p.max_output_tokens > 0) {
|
|
97
|
-
return p.max_output_tokens;
|
|
98
|
-
}
|
|
99
|
-
if (p.thinking) {
|
|
100
|
-
return 64e3;
|
|
101
|
-
}
|
|
102
|
-
return 8192;
|
|
103
|
-
}
|
|
104
|
-
function resolveAPIKey(p) {
|
|
105
|
-
if (p.api_key) {
|
|
106
|
-
return p.api_key;
|
|
107
|
-
}
|
|
108
|
-
const envVar = isKeyofTypeofEnvKeyMap(p.protocol) ? ENV_KEY_MAP[p.protocol] : "";
|
|
109
|
-
if (!envVar) {
|
|
110
|
-
return "";
|
|
111
|
-
}
|
|
112
|
-
return process.env[envVar] ?? "";
|
|
113
|
-
}
|
|
114
|
-
var MCPServerConfigSchema = z.object({
|
|
115
|
-
name: z.string(),
|
|
116
|
-
command: z.string().optional(),
|
|
117
|
-
args: z.array(z.string()).optional(),
|
|
118
|
-
url: z.string().optional(),
|
|
119
|
-
transport: z.string().optional(),
|
|
120
|
-
headers: z.record(z.string(), z.string()).optional(),
|
|
121
|
-
env: z.record(z.string(), z.string()).optional()
|
|
122
|
-
});
|
|
123
|
-
var HookConfigSchema = z.object({
|
|
124
|
-
id: z.string().optional(),
|
|
125
|
-
event: z.string(),
|
|
126
|
-
condition: z.string().optional(),
|
|
127
|
-
action: z.object({
|
|
128
|
-
type: z.string(),
|
|
129
|
-
command: z.string().optional(),
|
|
130
|
-
url: z.string().optional(),
|
|
131
|
-
method: z.string().optional(),
|
|
132
|
-
prompt: z.string().optional()
|
|
133
|
-
}),
|
|
134
|
-
reject: z.boolean().optional(),
|
|
135
|
-
once: z.boolean().optional(),
|
|
136
|
-
async: z.boolean().optional(),
|
|
137
|
-
on_error: z.string().optional()
|
|
138
|
-
});
|
|
139
|
-
var SandboxYamlConfigSchema = z.object({
|
|
140
|
-
enabled: z.boolean().optional(),
|
|
141
|
-
auto_allow: z.boolean().optional(),
|
|
142
|
-
network_enabled: z.boolean().optional()
|
|
143
|
-
});
|
|
144
|
-
var AppConfigSchema = z.looseObject({
|
|
145
|
-
providers: z.array(ProviderConfigSchema),
|
|
146
|
-
permission_mode: z.string().optional(),
|
|
147
|
-
mcp_servers: z.array(MCPServerConfigSchema).default([]),
|
|
148
|
-
hooks: z.array(HookConfigSchema).default([]),
|
|
149
|
-
sandbox: SandboxYamlConfigSchema.optional(),
|
|
150
|
-
enable_coordinator_mode: z.boolean().optional(),
|
|
151
|
-
/**
|
|
152
|
-
* Whether to fork when subagent_type is omitted. Enabled by default, so this
|
|
153
|
-
* field is left as undefined to represent "not specified in config". Using a
|
|
154
|
-
* concrete boolean would make it impossible to distinguish "not set" from
|
|
155
|
-
* "explicitly false", and the latter could never be turned back off.
|
|
156
|
-
*/
|
|
157
|
-
enable_fork: z.boolean().optional()
|
|
158
|
-
});
|
|
159
|
-
function forkEnabled(cfg) {
|
|
160
|
-
return cfg.enable_fork !== false;
|
|
161
|
-
}
|
|
162
|
-
function isRecord(value) {
|
|
163
|
-
return typeof value === "object" && value !== null;
|
|
164
|
-
}
|
|
165
|
-
function loadSingleFile(path) {
|
|
166
|
-
const data = readFileSync(path, "utf-8");
|
|
167
|
-
const raw = yaml.load(data);
|
|
168
|
-
if (!isRecord(raw)) {
|
|
169
|
-
log.error({ path }, "invalid yaml");
|
|
170
|
-
return { providers: [], mcp_servers: [], hooks: [] };
|
|
171
|
-
}
|
|
172
|
-
const parsed = safeParse(AppConfigSchema, raw);
|
|
173
|
-
if (parsed.success) {
|
|
174
|
-
const data2 = parsed.data;
|
|
175
|
-
return {
|
|
176
|
-
providers: data2.providers,
|
|
177
|
-
permission_mode: data2.permission_mode,
|
|
178
|
-
mcp_servers: data2.mcp_servers,
|
|
179
|
-
hooks: data2.hooks
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
log.error({ error: parsed.error }, "config error");
|
|
183
|
-
let providers = [];
|
|
184
|
-
let permissionMode;
|
|
185
|
-
let mcpServers = [];
|
|
186
|
-
let hooks = [];
|
|
187
|
-
let sandbox = void 0;
|
|
188
|
-
let enableCoordinatorMode = false;
|
|
189
|
-
let enableFork = true;
|
|
190
|
-
if ("providers" in raw) {
|
|
191
|
-
const parsed2 = safeParse(z.array(ProviderConfigSchema), raw.providers);
|
|
192
|
-
if (parsed2.success) {
|
|
193
|
-
providers = parsed2.data;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if ("permission_mode" in raw && typeof raw.permission_mode === "string") {
|
|
197
|
-
permissionMode = raw.permission_mode;
|
|
198
|
-
}
|
|
199
|
-
if ("mcp_servers" in raw) {
|
|
200
|
-
const parsed2 = safeParse(z.array(MCPServerConfigSchema), raw.mcp_servers);
|
|
201
|
-
if (parsed2.success) {
|
|
202
|
-
mcpServers = parsed2.data;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if ("hooks" in raw) {
|
|
206
|
-
const parsed2 = safeParse(z.array(HookConfigSchema), raw.hooks);
|
|
207
|
-
if (parsed2.success) {
|
|
208
|
-
hooks = parsed2.data;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if ("sandbox" in raw) {
|
|
212
|
-
const parsed2 = safeParse(SandboxYamlConfigSchema, raw.sandbox);
|
|
213
|
-
if (parsed2.success) {
|
|
214
|
-
sandbox = parsed2.data;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if ("enable_coordinator_mode" in raw) {
|
|
218
|
-
enableCoordinatorMode = Boolean(raw.enable_coordinator_mode);
|
|
219
|
-
}
|
|
220
|
-
if ("enable_fork" in raw) {
|
|
221
|
-
enableFork = Boolean(raw.enable_fork);
|
|
222
|
-
}
|
|
223
|
-
return {
|
|
224
|
-
providers,
|
|
225
|
-
permission_mode: permissionMode,
|
|
226
|
-
mcp_servers: mcpServers,
|
|
227
|
-
hooks,
|
|
228
|
-
sandbox,
|
|
229
|
-
enable_coordinator_mode: enableCoordinatorMode,
|
|
230
|
-
enable_fork: enableFork
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
function mergeConfig(base, override) {
|
|
234
|
-
if (override.providers.length > 0) {
|
|
235
|
-
base.providers = override.providers;
|
|
236
|
-
}
|
|
237
|
-
if (override.permission_mode) {
|
|
238
|
-
base.permission_mode = override.permission_mode;
|
|
239
|
-
}
|
|
240
|
-
if (override.mcp_servers.length > 0) {
|
|
241
|
-
const mcpToIdx = /* @__PURE__ */ new Map();
|
|
242
|
-
for (let i = 0; i < base.mcp_servers.length; i++) {
|
|
243
|
-
const mcp = base.mcp_servers[i];
|
|
244
|
-
mcpToIdx.set(mcp.name, i);
|
|
245
|
-
}
|
|
246
|
-
for (const s of override.mcp_servers) {
|
|
247
|
-
const idx = mcpToIdx.get(s.name);
|
|
248
|
-
if (idx !== void 0) {
|
|
249
|
-
base.mcp_servers[idx] = s;
|
|
250
|
-
} else {
|
|
251
|
-
base.mcp_servers.push(s);
|
|
252
|
-
mcpToIdx.set(s.name, base.mcp_servers.length - 1);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
base.hooks = [...base.hooks, ...override.hooks];
|
|
257
|
-
if (override.sandbox) {
|
|
258
|
-
base.sandbox = { ...base.sandbox, ...override.sandbox };
|
|
259
|
-
}
|
|
260
|
-
if (override.enable_coordinator_mode) {
|
|
261
|
-
base.enable_coordinator_mode = true;
|
|
262
|
-
}
|
|
263
|
-
if (override.enable_fork !== void 0) {
|
|
264
|
-
base.enable_fork = override.enable_fork;
|
|
265
|
-
}
|
|
266
|
-
return base;
|
|
267
|
-
}
|
|
268
|
-
function validateProviders(config) {
|
|
269
|
-
if (config.providers.length === 0) {
|
|
270
|
-
throw new ConfigError("At least one provider MUST be configured.");
|
|
271
|
-
}
|
|
272
|
-
const requiredFields = ["name", "protocol", "base_url", "model"];
|
|
273
|
-
for (let i = 0; i < config.providers.length; i++) {
|
|
274
|
-
const p = config.providers[i];
|
|
275
|
-
const values = {
|
|
276
|
-
name: p.name,
|
|
277
|
-
protocol: p.protocol,
|
|
278
|
-
base_url: p.base_url,
|
|
279
|
-
model: p.model
|
|
280
|
-
};
|
|
281
|
-
const missing = requiredFields.filter((field) => !(field in values));
|
|
282
|
-
if (missing.length > 0) {
|
|
283
|
-
throw new ConfigError(`Provider #${String(i + 1)}: missing fields: ${missing.join(", ")}`);
|
|
284
|
-
}
|
|
285
|
-
if (!VALID_PROTOCOLS.has(p.protocol)) {
|
|
286
|
-
throw new ConfigError(
|
|
287
|
-
`Provider #${String(i + 1)}: invalid protocol '${p.protocol}', MUST be one of: ${Array.from(VALID_PROTOCOLS).join(", ")}`
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
function loadConfig(path) {
|
|
293
|
-
if (path) {
|
|
294
|
-
const config = loadSingleFile(path);
|
|
295
|
-
validateProviders(config);
|
|
296
|
-
return config;
|
|
297
|
-
}
|
|
298
|
-
const wd = process.cwd();
|
|
299
|
-
const home = homedir();
|
|
300
|
-
const candidates = [
|
|
301
|
-
join(home, ".swifty", "config.yaml"),
|
|
302
|
-
join(wd, ".swifty", "config.yaml"),
|
|
303
|
-
join(wd, ".swifty", "config.local.yaml")
|
|
304
|
-
];
|
|
305
|
-
let merged = null;
|
|
306
|
-
for (const candidate of candidates) {
|
|
307
|
-
if (!existsSync(candidate)) {
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
const layer = loadSingleFile(candidate);
|
|
311
|
-
if (!merged) {
|
|
312
|
-
merged = layer;
|
|
313
|
-
} else {
|
|
314
|
-
merged = mergeConfig(merged, layer);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
if (!merged) {
|
|
318
|
-
throw new ConfigError(
|
|
319
|
-
"No config file found, expected .swifty/config.y(a)ml under project or $HOME/.swifty/config.y(a)ml."
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
validateProviders(merged);
|
|
323
|
-
return merged;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export {
|
|
327
|
-
ConfigError,
|
|
328
|
-
ProviderConfigSchema,
|
|
329
|
-
lookupModelContextWindow,
|
|
330
|
-
getContextWindow,
|
|
331
|
-
getContextWindowAsync,
|
|
332
|
-
_resetContextWindowCache,
|
|
333
|
-
getMaxOutputTokens,
|
|
334
|
-
resolveAPIKey,
|
|
335
|
-
HookConfigSchema,
|
|
336
|
-
forkEnabled,
|
|
337
|
-
mergeConfig,
|
|
338
|
-
loadConfig
|
|
339
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
// src/llm/errors.ts
|
|
2
|
-
var LLMError = class extends Error {
|
|
3
|
-
constructor(message) {
|
|
4
|
-
super(message);
|
|
5
|
-
this.name = "LLMError";
|
|
6
|
-
}
|
|
7
|
-
};
|
|
8
|
-
var AuthenticationError = class extends LLMError {
|
|
9
|
-
constructor(message) {
|
|
10
|
-
super(message);
|
|
11
|
-
this.name = "AuthenticationError";
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
var RateLimitError = class extends LLMError {
|
|
15
|
-
retryAfter;
|
|
16
|
-
constructor(message, retryAfter) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.name = "RateLimitError";
|
|
19
|
-
this.retryAfter = retryAfter;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
var NetworkError = class extends LLMError {
|
|
23
|
-
constructor(message) {
|
|
24
|
-
super(message);
|
|
25
|
-
this.name = "NetworkError";
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
var ContextTooLongError = class extends LLMError {
|
|
29
|
-
constructor(message) {
|
|
30
|
-
super(message);
|
|
31
|
-
this.name = "ContextTooLongError";
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// src/conversation/pairing.ts
|
|
36
|
-
var INTERRUPTED_TOOL_RESULT = "Tool execution was interrupted. The tool may or may not have completed; verify before relying on its effects.";
|
|
37
|
-
var REJECTED_TOOL_RESULT = "The user rejected this tool use. Nothing was changed (for file edits, the new content was NOT written).";
|
|
38
|
-
function ensureToolPairing(messages) {
|
|
39
|
-
const resolved = /* @__PURE__ */ new Set();
|
|
40
|
-
const issued = /* @__PURE__ */ new Set();
|
|
41
|
-
for (const m of messages) {
|
|
42
|
-
for (const tr of m.toolResults ?? []) {
|
|
43
|
-
resolved.add(tr.toolUseId);
|
|
44
|
-
}
|
|
45
|
-
for (const tu of m.toolUses ?? []) {
|
|
46
|
-
issued.add(tu.toolUseId);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const out = [];
|
|
50
|
-
for (const m of messages) {
|
|
51
|
-
let current = m;
|
|
52
|
-
if ((m.toolResults?.length ?? 0) > 0) {
|
|
53
|
-
const kept = (m.toolResults ?? []).filter((tr) => issued.has(tr.toolUseId));
|
|
54
|
-
if (kept.length === 0 && !m.content && !(m.toolUses?.length ?? 0)) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
current = { ...m, toolResults: kept };
|
|
58
|
-
}
|
|
59
|
-
out.push(current);
|
|
60
|
-
const missing = [];
|
|
61
|
-
for (const tu of m.toolUses ?? []) {
|
|
62
|
-
if (resolved.has(tu.toolUseId)) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
missing.push({
|
|
66
|
-
toolUseId: tu.toolUseId,
|
|
67
|
-
content: INTERRUPTED_TOOL_RESULT,
|
|
68
|
-
isError: true
|
|
69
|
-
});
|
|
70
|
-
resolved.add(tu.toolUseId);
|
|
71
|
-
}
|
|
72
|
-
if (missing.length > 0) {
|
|
73
|
-
out.push({ role: "user", content: "", toolResults: missing });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return out;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export {
|
|
80
|
-
LLMError,
|
|
81
|
-
AuthenticationError,
|
|
82
|
-
RateLimitError,
|
|
83
|
-
NetworkError,
|
|
84
|
-
ContextTooLongError,
|
|
85
|
-
INTERRUPTED_TOOL_RESULT,
|
|
86
|
-
REJECTED_TOOL_RESULT,
|
|
87
|
-
ensureToolPairing
|
|
88
|
-
};
|