@swifty.js/swifty 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/{agent-ZCMBUWLZ.js → agent-RABW3Z3R.js} +1 -1
  2. package/dist/anthropic-V22T6E6E.js +4 -0
  3. package/dist/{checker-OJFS2MZY.js → checker-3RWAYF2U.js} +1 -1
  4. package/dist/{chunk-Y5WGBAGP.js → chunk-5KXBVL2A.js} +1 -1
  5. package/dist/{chunk-MUPVOATV.js → chunk-CV7OKXYC.js} +1 -1
  6. package/dist/chunk-MJR2C7S7.js +130 -0
  7. package/dist/{chunk-GUXBLUNR.js → chunk-NR62AA5K.js} +1 -1
  8. package/dist/{chunk-S6ZADC7C.js → chunk-OCQ6TYLT.js} +21 -20
  9. package/dist/chunk-QN27QEFS.js +4 -0
  10. package/dist/{chunk-LX2LK3TF.js → chunk-SIWLMWHH.js} +12 -11
  11. package/dist/chunk-Y43POSIW.js +389 -0
  12. package/dist/lib/agent-GHXYOARN.js +9 -0
  13. package/dist/lib/anthropic-7YEN2QTU.js +22 -0
  14. package/dist/lib/bwrap-QRGPUP4J.js +6 -0
  15. package/dist/lib/checker-6BW4222R.js +19 -0
  16. package/dist/lib/chunk-7IZEK7X5.js +545 -0
  17. package/dist/lib/chunk-BN4Q54G2.js +1096 -0
  18. package/dist/lib/chunk-BO76JDFZ.js +617 -0
  19. package/dist/lib/chunk-CYDNMEBC.js +339 -0
  20. package/dist/lib/chunk-EY7HE52Q.js +384 -0
  21. package/dist/lib/chunk-GHF2PSEW.js +8 -0
  22. package/dist/lib/chunk-GNI7YX6F.js +426 -0
  23. package/dist/lib/chunk-HK2Z6WP4.js +223 -0
  24. package/dist/lib/chunk-MF3YLQDS.js +1277 -0
  25. package/dist/lib/chunk-OO2CLOEE.js +88 -0
  26. package/dist/lib/chunk-ORSYNBMM.js +38 -0
  27. package/dist/lib/chunk-PZ42NAFA.js +242 -0
  28. package/dist/lib/chunk-VUD72RTY.js +39 -0
  29. package/dist/lib/glob.wasm +0 -0
  30. package/dist/lib/index.d.ts +5347 -0
  31. package/dist/lib/index.js +11990 -0
  32. package/dist/lib/openai-RDHZFJUT.js +15 -0
  33. package/dist/lib/seatbelt-FT5IY73W.js +6 -0
  34. package/dist/lib/tool-filter-VF7TZRE5.js +19 -0
  35. package/dist/main.js +204 -466
  36. package/dist/{openai-HXD52MZB.js → openai-6NWVJ5LI.js} +15 -15
  37. package/dist/{server-VMHWEO2Y.js → server-KQTLAXC6.js} +17 -17
  38. package/package.json +18 -6
  39. package/dist/anthropic-4ZVG7AMA.js +0 -4
  40. package/dist/chunk-6E6UA7MT.js +0 -126
  41. package/dist/chunk-DDBH5AEN.js +0 -386
  42. package/dist/chunk-ZZQE743W.js +0 -4
@@ -0,0 +1,339 @@
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-7YEN2QTU.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
+ };
@@ -0,0 +1,384 @@
1
+ // src/logger/logger.ts
2
+ import { openSync, closeSync, mkdirSync, writeFileSync } from "fs";
3
+ import { readdir, stat, unlink } from "fs/promises";
4
+ import { homedir } from "os";
5
+ import { join, dirname, basename } from "path";
6
+ import pino from "pino";
7
+ var currentLogger = null;
8
+ var currentDest = null;
9
+ var currentFd = null;
10
+ function resolveLogPath(opts) {
11
+ const dir = opts.logDir ?? join(opts.workDir ?? process.cwd(), ".swifty", "logs");
12
+ return join(dir, `${opts.sessionId}.jsonl`);
13
+ }
14
+ function ensureSwiftyGitignore(logPath) {
15
+ let dir = dirname(logPath);
16
+ while (basename(dir) !== ".swifty") {
17
+ const parent = dirname(dir);
18
+ if (parent === dir) {
19
+ return;
20
+ }
21
+ dir = parent;
22
+ }
23
+ try {
24
+ writeFileSync(join(dir, ".gitignore"), "*\n", { flag: "wx" });
25
+ } catch {
26
+ }
27
+ }
28
+ function sanitizeNameSegment(name) {
29
+ const cleaned = name.replace(/[^a-zA-Z0-9_-]/g, "_");
30
+ return cleaned || "unnamed";
31
+ }
32
+ function flushDestination(dest) {
33
+ if (typeof dest !== "object" || dest === null) {
34
+ return;
35
+ }
36
+ const fn = Reflect.get(dest, "flushSync");
37
+ if (typeof fn === "function") {
38
+ fn.call(dest);
39
+ }
40
+ }
41
+ var LOG_LEVEL = "warn";
42
+ function initLogger(opts) {
43
+ if (currentLogger) {
44
+ closeLogger();
45
+ }
46
+ const logPath = resolveLogPath(opts);
47
+ mkdirSync(dirname(logPath), { recursive: true });
48
+ ensureSwiftyGitignore(logPath);
49
+ const fd = openSync(logPath, "a");
50
+ currentFd = fd;
51
+ currentDest = pino.destination(fd);
52
+ const pinoOpts = {
53
+ level: LOG_LEVEL,
54
+ base: { sessionId: opts.sessionId, mode: opts.mode },
55
+ serializers: { err: errSerializer }
56
+ };
57
+ if (opts.stdout) {
58
+ currentLogger = pino(
59
+ pinoOpts,
60
+ pino.multistream([
61
+ { stream: currentDest, level: LOG_LEVEL },
62
+ { stream: process.stdout, level: LOG_LEVEL }
63
+ ])
64
+ );
65
+ } else {
66
+ currentLogger = pino(pinoOpts, currentDest);
67
+ }
68
+ if (!opts.skipCleanup) {
69
+ const workDir = opts.workDir ?? process.cwd();
70
+ void cleanExpiredLogs(workDir).catch(() => {
71
+ });
72
+ }
73
+ return currentLogger;
74
+ }
75
+ function getLogger() {
76
+ return currentLogger;
77
+ }
78
+ function closeLogger() {
79
+ if (currentLogger) {
80
+ try {
81
+ currentLogger.flush();
82
+ } catch {
83
+ }
84
+ currentLogger = null;
85
+ }
86
+ if (currentDest) {
87
+ flushDestination(currentDest);
88
+ currentDest = null;
89
+ }
90
+ if (currentFd !== null) {
91
+ try {
92
+ closeSync(currentFd);
93
+ } catch {
94
+ }
95
+ currentFd = null;
96
+ }
97
+ }
98
+ var silentFallback = pino({ level: "silent" });
99
+ var logger = new Proxy(silentFallback, {
100
+ get(_target, prop, receiver) {
101
+ const current = getLogger();
102
+ const target = current ?? _target;
103
+ const value = Reflect.get(target, prop, receiver);
104
+ if (typeof value === "function") {
105
+ return value.bind(target);
106
+ }
107
+ return value;
108
+ },
109
+ set(_target, prop, value) {
110
+ return Reflect.set(getLogger() ?? _target, prop, value);
111
+ }
112
+ });
113
+ function createChildLogger(bindings) {
114
+ let cachedChild = null;
115
+ let cachedLogger = null;
116
+ const resolveChild = () => {
117
+ const current = getLogger();
118
+ if (!current) {
119
+ return null;
120
+ }
121
+ if (cachedChild === null || cachedLogger !== current) {
122
+ cachedChild = current.child(bindings);
123
+ cachedLogger = current;
124
+ }
125
+ return cachedChild;
126
+ };
127
+ return new Proxy(silentFallback, {
128
+ get(_target, prop, receiver) {
129
+ const target = resolveChild() ?? _target;
130
+ const value = Reflect.get(target, prop, receiver);
131
+ if (typeof value === "function") {
132
+ return value.bind(target);
133
+ }
134
+ return value;
135
+ },
136
+ set(_target, prop, value) {
137
+ return Reflect.set(resolveChild() ?? _target, prop, value);
138
+ }
139
+ });
140
+ }
141
+ async function cleanDir(dir) {
142
+ let files;
143
+ try {
144
+ files = (await readdir(dir)).filter((f) => f.endsWith(".jsonl"));
145
+ } catch {
146
+ return 0;
147
+ }
148
+ const now = Date.now();
149
+ let removed = 0;
150
+ for (const file of files) {
151
+ const filePath = join(dir, file);
152
+ try {
153
+ const s = await stat(filePath);
154
+ if (now - s.mtimeMs > 30 * 24 * 60 * 60 * 1e3) {
155
+ await unlink(filePath);
156
+ removed++;
157
+ }
158
+ } catch {
159
+ }
160
+ }
161
+ return removed;
162
+ }
163
+ async function cleanExpiredLogs(workDir) {
164
+ let removed = 0;
165
+ removed += await cleanDir(join(workDir, ".swifty", "logs"));
166
+ const teamsDir = join(homedir(), ".swifty", "teams");
167
+ let teams;
168
+ try {
169
+ teams = await readdir(teamsDir);
170
+ } catch {
171
+ return removed;
172
+ }
173
+ for (const team of teams) {
174
+ removed += await cleanDir(join(teamsDir, team, "logs"));
175
+ }
176
+ return removed;
177
+ }
178
+ var CAUSE_MAX_DEPTH = 5;
179
+ var RESERVED_KEYS = /* @__PURE__ */ new Set(["name", "message", "stack", "cause"]);
180
+ function serializeErrorInstance(err, depth) {
181
+ const out = {
182
+ type: err.name,
183
+ message: err.message,
184
+ stack: err.stack
185
+ };
186
+ const causeDescriptor = Object.getOwnPropertyDescriptor(err, "cause");
187
+ if (causeDescriptor && depth < CAUSE_MAX_DEPTH) {
188
+ const cause = causeDescriptor.value;
189
+ if (cause instanceof Error) {
190
+ out.cause = serializeErrorInstance(cause, depth + 1);
191
+ } else if (cause !== void 0) {
192
+ out.cause = { message: safeStringify(cause) };
193
+ }
194
+ }
195
+ for (const key of Object.keys(err)) {
196
+ if (RESERVED_KEYS.has(key)) {
197
+ continue;
198
+ }
199
+ const descriptor = Object.getOwnPropertyDescriptor(err, key);
200
+ if (descriptor) {
201
+ const fieldValue = descriptor.value;
202
+ out[key] = fieldValue;
203
+ }
204
+ }
205
+ return out;
206
+ }
207
+ function safeStringify(value) {
208
+ if (typeof value === "string") {
209
+ return value;
210
+ }
211
+ try {
212
+ const json = JSON.stringify(value);
213
+ if (json !== void 0) {
214
+ return json;
215
+ }
216
+ } catch {
217
+ }
218
+ try {
219
+ return String(value);
220
+ } catch {
221
+ return Object.prototype.toString.call(value);
222
+ }
223
+ }
224
+ function errSerializer(err) {
225
+ if (err instanceof Error) {
226
+ return serializeErrorInstance(err, 0);
227
+ }
228
+ return { message: safeStringify(err), value: err };
229
+ }
230
+
231
+ // src/utils/index.ts
232
+ var log = createChildLogger({ module: "utils" });
233
+ function contentToText(content) {
234
+ if (typeof content === "string") {
235
+ return content;
236
+ }
237
+ const parts = [];
238
+ for (const block of content) {
239
+ if (block.type === "text" && typeof block.text === "string") {
240
+ parts.push(block.text);
241
+ } else if (block.type === "image" && isRecord(block.source)) {
242
+ const mediaType = block.source.type === "base64" && typeof block.source.media_type === "string" ? block.source.media_type : "image";
243
+ parts.push(`[Image: ${mediaType}]`);
244
+ } else if (block.type === "tool_reference" && typeof block.tool_name === "string") {
245
+ parts.push(`[Tool reference: ${block.tool_name}]`);
246
+ } else if (block.type === "search_result") {
247
+ const title = typeof block.title === "string" ? block.title : "search result";
248
+ const source = typeof block.source === "string" ? ` (${block.source})` : "";
249
+ const nested = Array.isArray(block.content) ? contentToText(block.content.filter(isRecord)) : "";
250
+ parts.push(`${title}${source}${nested ? `
251
+ ${nested}` : ""}`);
252
+ } else if (block.type === "document") {
253
+ const title = typeof block.title === "string" ? block.title : "document";
254
+ parts.push(`[Document: ${title}]`);
255
+ }
256
+ }
257
+ return parts.join("\n");
258
+ }
259
+ function isRecord(value) {
260
+ return typeof value === "object" && value !== null && !Array.isArray(value);
261
+ }
262
+ function asRecord(value) {
263
+ if (isRecord(value)) {
264
+ return value;
265
+ }
266
+ if (Array.isArray(value)) {
267
+ return Object.fromEntries(value.entries());
268
+ }
269
+ return {};
270
+ }
271
+ function asString(value) {
272
+ if (typeof value === "string") {
273
+ return value;
274
+ }
275
+ return String(value);
276
+ }
277
+ function asErrorString(value) {
278
+ if (value instanceof Error) {
279
+ return value.message;
280
+ }
281
+ return asString(value);
282
+ }
283
+ function isObject(value) {
284
+ return typeof value === "object" && value !== null;
285
+ }
286
+ function toTry(fn, ctx) {
287
+ if (typeof fn !== "function") {
288
+ return fn;
289
+ }
290
+ return function(...args) {
291
+ let ret;
292
+ try {
293
+ ret = ctx ? fn.call(ctx, ...args) : fn.call(this, ...args);
294
+ } catch (err) {
295
+ log.error({ err }, "utils operation failed");
296
+ return void 0;
297
+ }
298
+ return ret;
299
+ };
300
+ }
301
+ var safeJSONParse = toTry(JSON.parse, JSON);
302
+ function asError(err) {
303
+ if (err instanceof Error) {
304
+ return err;
305
+ }
306
+ return new Error(String(err));
307
+ }
308
+ function intArg(args, key, fallback) {
309
+ const v = args[key];
310
+ if (typeof v === "number") {
311
+ return Math.floor(v);
312
+ }
313
+ if (typeof v === "string") {
314
+ const n = Number.parseInt(v, 10);
315
+ return Number.isNaN(n) ? fallback : n;
316
+ }
317
+ return fallback;
318
+ }
319
+ function strList(raw) {
320
+ if (Array.isArray(raw)) {
321
+ return raw.filter((v) => typeof v === "string");
322
+ }
323
+ return [];
324
+ }
325
+ function strArg(args, key, fallback) {
326
+ const v = args[key];
327
+ if (typeof v === "string") {
328
+ return v;
329
+ }
330
+ return fallback ?? "";
331
+ }
332
+ function boolArg(args, key, fallback) {
333
+ const v = args[key];
334
+ if (typeof v === "boolean") {
335
+ return v;
336
+ }
337
+ return fallback ?? Boolean(v);
338
+ }
339
+ function quickSort(arr, compare) {
340
+ if (arr.length <= 1) {
341
+ return [...arr];
342
+ }
343
+ const pivotIndex = Math.floor(arr.length / 2);
344
+ const pivot = arr[pivotIndex];
345
+ if (pivot === void 0) {
346
+ return [...arr];
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
+ }
360
+ }
361
+ return [...quickSort(left, compare), ...equal, ...quickSort(right, compare)];
362
+ }
363
+
364
+ export {
365
+ sanitizeNameSegment,
366
+ initLogger,
367
+ closeLogger,
368
+ logger,
369
+ createChildLogger,
370
+ contentToText,
371
+ isRecord,
372
+ asRecord,
373
+ asString,
374
+ asErrorString,
375
+ isObject,
376
+ toTry,
377
+ safeJSONParse,
378
+ asError,
379
+ intArg,
380
+ strList,
381
+ strArg,
382
+ boolArg,
383
+ quickSort
384
+ };