stitchkit 0.90.3 → 0.90.5

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 (61) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/dist/agent-runtime-coding-tools.js +4 -4
  3. package/dist/agent-runtime-harness.js +6 -6
  4. package/dist/agent-runtime-sandbox.js +4 -4
  5. package/dist/agent-runtime.js +9 -9
  6. package/dist/cli.d.ts +14 -1
  7. package/dist/cli.d.ts.map +1 -1
  8. package/dist/cli.js +402 -11
  9. package/dist/{index-2hrfpw2c.js → index-1bnkzq95.js} +2 -2
  10. package/dist/{index-j7q0xj6d.js → index-3yqgj323.js} +3 -3
  11. package/dist/{index-gbqjt8jz.js → index-83fafqw8.js} +3 -3
  12. package/dist/{index-44ht2790.js → index-8pjqv3zh.js} +6 -6
  13. package/dist/{index-kc6h6hg0.js → index-8z9we758.js} +1 -1
  14. package/dist/{index-r159gjwy.js → index-fenaekmk.js} +94 -8
  15. package/dist/{index-1923shw9.js → index-fqg5mfk7.js} +339 -19
  16. package/dist/{index-f475yj00.js → index-s208wab5.js} +1 -1
  17. package/dist/{index-79hb1wyh.js → index-tgh3ksfh.js} +5 -5
  18. package/dist/{index-wb15909q.js → index-zsdgd1tz.js} +3 -3
  19. package/dist/index.js +7 -7
  20. package/dist/node.js +2 -2
  21. package/dist/observability/index.js +1 -1
  22. package/dist/remote.js +1 -1
  23. package/dist/server/index.js +6 -6
  24. package/dist/testing.js +3 -3
  25. package/dist/tool-invoker.js +6 -6
  26. package/dist/tools/cli-args.d.ts +30 -6
  27. package/dist/tools/cli-args.d.ts.map +1 -1
  28. package/dist/tools/cli-installer.d.ts +34 -0
  29. package/dist/tools/cli-installer.d.ts.map +1 -0
  30. package/dist/tools/cli-manifest.d.ts +83 -0
  31. package/dist/tools/cli-manifest.d.ts.map +1 -0
  32. package/dist/tools/cli-profile.d.ts +40 -0
  33. package/dist/tools/cli-profile.d.ts.map +1 -0
  34. package/dist/tools/cli-update.d.ts +64 -0
  35. package/dist/tools/cli-update.d.ts.map +1 -0
  36. package/dist/tools/cli-view.d.ts +12 -0
  37. package/dist/tools/cli-view.d.ts.map +1 -0
  38. package/dist/tools/cli.d.ts.map +1 -1
  39. package/dist/tools/connections/index.d.ts +2 -1
  40. package/dist/tools/connections/index.d.ts.map +1 -1
  41. package/dist/tools/connections/index.js +74 -14
  42. package/dist/tools/connections/mcp-envelope.d.ts +44 -0
  43. package/dist/tools/connections/mcp-envelope.d.ts.map +1 -0
  44. package/dist/tools/connections/mcp.d.ts +2 -1
  45. package/dist/tools/connections/mcp.d.ts.map +1 -1
  46. package/dist/tools/connections/mount.d.ts.map +1 -1
  47. package/dist/tools/connections/openapi.d.ts +2 -1
  48. package/dist/tools/connections/openapi.d.ts.map +1 -1
  49. package/dist/tools/connections/runtime.d.ts +17 -0
  50. package/dist/tools/connections/runtime.d.ts.map +1 -1
  51. package/dist/tools/connections/types.d.ts +18 -1
  52. package/dist/tools/connections/types.d.ts.map +1 -1
  53. package/dist/tools/json-schema-dialect.d.ts +17 -0
  54. package/dist/tools/json-schema-dialect.d.ts.map +1 -0
  55. package/dist/tools/presentation.d.ts +8 -1
  56. package/dist/tools/presentation.d.ts.map +1 -1
  57. package/dist/tools.js +13 -13
  58. package/dist/tracking.js +1 -1
  59. package/llms-full.txt +273 -3
  60. package/package.json +1 -1
  61. package/dist/{index-db51n3xr.js → index-ra6txecz.js} +3 -3
package/dist/cli.js CHANGED
@@ -1,33 +1,424 @@
1
1
  import {
2
+ CliArgumentError,
2
3
  DEFAULT_EXIT_CODES,
3
4
  createCli,
4
5
  defineCliCommand,
5
6
  emitResult,
7
+ extractCliGlobalOptions,
8
+ fetchGuarded,
6
9
  parseCliArgs,
7
- pollUntilDone
8
- } from "./index-1923shw9.js";
10
+ pollUntilDone,
11
+ readCapped,
12
+ renderCliView,
13
+ routeCliArgv
14
+ } from "./index-fqg5mfk7.js";
9
15
  import"./index-sbdmyz75.js";
10
- import"./index-wb15909q.js";
11
- import"./index-2hrfpw2c.js";
12
- import"./index-44ht2790.js";
16
+ import"./index-zsdgd1tz.js";
17
+ import"./index-1bnkzq95.js";
18
+ import"./index-8pjqv3zh.js";
13
19
  import"./index-vsbzgd7b.js";
14
20
  import"./index-f9mb610r.js";
15
21
  import"./index-2hryh65w.js";
16
22
  import"./index-kazec06k.js";
17
23
  import"./index-6k1937bx.js";
18
- import"./index-scs3f1eg.js";
19
24
  import"./index-zcgf3gqf.js";
20
- import"./index-7zbps32p.js";
21
- import"./index-kzfs85xp.js";
22
- import"./index-kc6h6hg0.js";
23
- import"./index-r159gjwy.js";
25
+ import {
26
+ coerceJsonArgs
27
+ } from "./index-7zbps32p.js";
28
+ import"./index-8z9we758.js";
29
+ import"./index-fenaekmk.js";
24
30
  import"./index-cby4ar3v.js";
31
+ import {
32
+ AppError
33
+ } from "./index-scs3f1eg.js";
34
+ import {
35
+ safeJsonParse
36
+ } from "./index-kzfs85xp.js";
25
37
  import"./index-77fekveh.js";
38
+ // src/tools/cli-installer.ts
39
+ function shellQuote(value) {
40
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
41
+ }
42
+ function renderCliInstaller(config) {
43
+ const binary = config.binaryName ?? config.manifest.name;
44
+ const installDir = config.installDir ?? "$HOME/.local/bin";
45
+ const assets = config.asset ? [config.asset] : config.manifest.assets;
46
+ if (assets.length === 0) {
47
+ throw new Error("[stitchkit] a build manifest with no assets installs nothing");
48
+ }
49
+ const selection = assets.length === 1 && assets[0] !== undefined ? singleTarget(assets[0]) : unameDispatch(assets);
50
+ return `#!/bin/sh
51
+ # ${binary} ${config.manifest.version} (${config.manifest.commit})
52
+ # Generated from the build manifest — it parses no JSON and needs no jq.
53
+ set -eu
54
+
55
+ binary=${shellQuote(binary)}
56
+ dir="\${INSTALL_DIR:-${installDir}}"
57
+
58
+ ${selection}
59
+
60
+ fetch() {
61
+ if command -v curl >/dev/null 2>&1; then
62
+ curl -fsSL "$1" -o "$2"
63
+ elif command -v wget >/dev/null 2>&1; then
64
+ wget -q "$1" -O "$2"
65
+ else
66
+ echo "need curl or wget" >&2
67
+ exit 1
68
+ fi
69
+ }
70
+
71
+ digest() {
72
+ if command -v sha256sum >/dev/null 2>&1; then
73
+ sha256sum "$1" | cut -d' ' -f1
74
+ elif command -v shasum >/dev/null 2>&1; then
75
+ shasum -a 256 "$1" | cut -d' ' -f1
76
+ elif command -v openssl >/dev/null 2>&1; then
77
+ openssl dgst -sha256 "$1" | awk '{print $NF}'
78
+ else
79
+ echo "need sha256sum, shasum or openssl" >&2
80
+ exit 1
81
+ fi
82
+ }
83
+
84
+ tmp="$(mktemp -d)"
85
+ trap 'rm -rf "$tmp"' EXIT
86
+
87
+ fetch "$url" "$tmp/download"
88
+ if [ "$compression" = "gzip" ]; then
89
+ gzip -dc "$tmp/download" > "$tmp/binary"
90
+ else
91
+ mv "$tmp/download" "$tmp/binary"
92
+ fi
93
+
94
+ actual="$(digest "$tmp/binary")"
95
+ if [ "$actual" != "$sha256" ]; then
96
+ echo "checksum mismatch: expected $sha256, got $actual" >&2
97
+ exit 1
98
+ fi
99
+
100
+ actual_size="$(wc -c < "$tmp/binary" | tr -d ' ')"
101
+ if [ "$actual_size" != "$size" ]; then
102
+ echo "size mismatch: expected $size bytes, got $actual_size" >&2
103
+ exit 1
104
+ fi
105
+
106
+ mkdir -p "$dir"
107
+ chmod 755 "$tmp/binary"
108
+ # A rename, never a write over the file in place: anything else can leave a
109
+ # half-written executable where a working one used to be.
110
+ mv "$tmp/binary" "$dir/$binary"
111
+
112
+ echo "installed $binary ${config.manifest.version} to $dir/$binary"
113
+ case ":$PATH:" in
114
+ *":$dir:"*) ;;
115
+ *) echo "note: $dir is not on your PATH" >&2 ;;
116
+ esac
117
+ `;
118
+ }
119
+ function singleTarget(asset) {
120
+ return [
121
+ `url=${shellQuote(asset.url)}`,
122
+ `sha256=${shellQuote(asset.sha256)}`,
123
+ `size=${shellQuote(String(asset.size))}`,
124
+ `compression=${shellQuote(asset.compression)}`
125
+ ].join(`
126
+ `);
127
+ }
128
+ function unameDispatch(assets) {
129
+ const cases = assets.map((asset) => ` ${asset.platform}/${asset.arch})
130
+ url=${shellQuote(asset.url)}
131
+ sha256=${shellQuote(asset.sha256)}
132
+ size=${shellQuote(String(asset.size))}
133
+ compression=${shellQuote(asset.compression)}
134
+ ;;`).join(`
135
+ `);
136
+ const published = assets.map((asset) => `${asset.platform}/${asset.arch}`).join(", ");
137
+ return `case "$(uname -s)" in
138
+ Darwin) platform=darwin ;;
139
+ Linux) platform=linux ;;
140
+ *) platform="$(uname -s)" ;;
141
+ esac
142
+ case "$(uname -m)" in
143
+ x86_64|amd64) arch=x64 ;;
144
+ aarch64|arm64) arch=arm64 ;;
145
+ *) arch="$(uname -m)" ;;
146
+ esac
147
+
148
+ case "$platform/$arch" in
149
+ ${cases}
150
+ *)
151
+ echo "no published build for $platform/$arch — published: ${published}" >&2
152
+ exit 1
153
+ ;;
154
+ esac`;
155
+ }
156
+ // src/tools/cli-manifest.ts
157
+ import { z } from "zod";
158
+ var CliBuildTargetSchema = z.object({
159
+ platform: z.string().min(1),
160
+ arch: z.string().min(1)
161
+ });
162
+ var CliBuildAssetSchema = CliBuildTargetSchema.extend({
163
+ url: z.url(),
164
+ compression: z.enum(["gzip", "none"]).default("none"),
165
+ size: z.int().positive(),
166
+ sha256: z.string().regex(/^[0-9a-f]{64}$/, "sha256 must be 64 lowercase hex characters")
167
+ });
168
+ var CliBuildManifestSchema = z.object({
169
+ name: z.string().min(1),
170
+ version: z.string().min(1),
171
+ commit: z.string().min(1),
172
+ builtAt: z.iso.datetime(),
173
+ assets: z.array(CliBuildAssetSchema)
174
+ });
175
+ var CliBuildStampSchema = z.object({
176
+ version: z.string().min(1),
177
+ commit: z.string().min(1),
178
+ builtAt: z.iso.datetime()
179
+ });
180
+ function formatCliBuildStamp(stamp, name) {
181
+ const prefix = name ? `${name} ` : "";
182
+ return `${prefix}${stamp.version} (${stamp.commit.slice(0, 12)}, built ${stamp.builtAt})`;
183
+ }
184
+ function currentCliBuildTarget() {
185
+ return { platform: process.platform, arch: process.arch };
186
+ }
187
+ function selectCliBuildAsset(manifest, target = currentCliBuildTarget()) {
188
+ return manifest.assets.find((asset) => asset.platform === target.platform && asset.arch === target.arch);
189
+ }
190
+ function assertCliPublishable(previous, next) {
191
+ if (!previous)
192
+ return;
193
+ if (previous.version !== next.version)
194
+ return;
195
+ if (previous.commit === next.commit)
196
+ return;
197
+ throw new Error(`[stitchkit] ${next.name} ${next.version} was already published from commit ${previous.commit}; ` + `refusing to republish it from ${next.commit} — bump the version instead`);
198
+ }
199
+ // src/tools/cli-profile.ts
200
+ import {
201
+ chmodSync,
202
+ existsSync,
203
+ mkdirSync,
204
+ readdirSync,
205
+ readFileSync,
206
+ statSync,
207
+ writeFileSync
208
+ } from "node:fs";
209
+ import { join } from "node:path";
210
+ var PROFILE_SUFFIX = ".json";
211
+ var FILE_MODE = 384;
212
+ var DIRECTORY_MODE = 448;
213
+
214
+ class CliProfileError extends AppError {
215
+ constructor(message, code = "NOT_FOUND") {
216
+ super(code, message, code === "NOT_FOUND" ? 404 : code === "FORBIDDEN" ? 403 : 400);
217
+ this.name = "CliProfileError";
218
+ }
219
+ }
220
+ function assertProfileName(name) {
221
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(name)) {
222
+ throw new CliProfileError(`"${name}" is not a usable profile name — letters, digits, dot, dash and underscore`, "BAD_REQUEST");
223
+ }
224
+ }
225
+ function createCliProfileStore(config) {
226
+ const announce = config.announce ?? ((line) => process.stderr.write(`${line}
227
+ `));
228
+ const pathFor = (name) => {
229
+ assertProfileName(name);
230
+ return join(config.directory, `${name}${PROFILE_SUFFIX}`);
231
+ };
232
+ const list = () => {
233
+ if (!existsSync(config.directory))
234
+ return [];
235
+ return readdirSync(config.directory).filter((entry) => entry.endsWith(PROFILE_SUFFIX)).map((entry) => entry.slice(0, -PROFILE_SUFFIX.length)).sort();
236
+ };
237
+ const read = (name) => {
238
+ const path = pathFor(name);
239
+ if (!existsSync(path)) {
240
+ throw new CliProfileError(missingMessage(name, path, config));
241
+ }
242
+ const mode = statSync(path).mode & 63;
243
+ if (mode !== 0) {
244
+ throw new CliProfileError(`profile "${name}" is readable by other users — run: chmod 600 ${path}`, "FORBIDDEN");
245
+ }
246
+ const parsed = safeJsonParse(readFileSync(path, "utf8"));
247
+ const result = config.schema.safeParse(parsed);
248
+ if (!result.success) {
249
+ const issue = result.error.issues[0];
250
+ const field = issue?.path.join(".");
251
+ throw new CliProfileError(`profile "${name}" (${path}) is not usable: ${field ? `${field}: ` : ""}${issue?.message ?? "invalid"}`, "BAD_REQUEST");
252
+ }
253
+ return result.data;
254
+ };
255
+ return {
256
+ directory: config.directory,
257
+ pathFor,
258
+ list,
259
+ read,
260
+ write(name, value) {
261
+ const path = pathFor(name);
262
+ mkdirSync(config.directory, { recursive: true, mode: DIRECTORY_MODE });
263
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
264
+ `, { mode: FILE_MODE });
265
+ chmodSync(path, FILE_MODE);
266
+ return path;
267
+ },
268
+ resolve(name) {
269
+ if (name !== undefined) {
270
+ const path = pathFor(name);
271
+ return { name, path, value: read(name), substituted: false };
272
+ }
273
+ const configured = list();
274
+ const only = configured[0];
275
+ if (configured.length === 1 && only !== undefined) {
276
+ const path = pathFor(only);
277
+ announce(`[${only}] using the only configured profile (${path})`);
278
+ return { name: only, path, value: read(only), substituted: true };
279
+ }
280
+ if (configured.length === 0) {
281
+ const example = join(config.directory, `<name>${PROFILE_SUFFIX}`);
282
+ throw new CliProfileError(`no profile is configured in ${config.directory}${config.createHint ? ` — ${config.createHint("<name>", example)}` : ""}`);
283
+ }
284
+ throw new CliProfileError(`several profiles are configured (${configured.join(", ")}) — name one`, "BAD_REQUEST");
285
+ }
286
+ };
287
+ }
288
+ function missingMessage(name, path, config) {
289
+ const hint = config.createHint ? ` — ${config.createHint(name, path)}` : "";
290
+ return `profile "${name}" is not configured; expected ${path}${hint}`;
291
+ }
292
+ // src/tools/cli-update.ts
293
+ import { createHash } from "node:crypto";
294
+ import { chmodSync as chmodSync2, renameSync, writeFileSync as writeFileSync2 } from "node:fs";
295
+ import { basename, dirname, join as join2 } from "node:path";
296
+ import { gunzipSync } from "node:zlib";
297
+ var DEFAULT_CHECK_TIMEOUT_MS = 2000;
298
+ var DEFAULT_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
299
+ var DEFAULT_DOWNLOAD_TIMEOUT_MS = 120000;
300
+ var MANIFEST_MAX_BYTES = 256 * 1024;
301
+ var DEFAULT_MAX_ASSET_BYTES = 256 * 1024 * 1024;
302
+ function parseVersion(value) {
303
+ const match = /^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(value.trim());
304
+ if (!match)
305
+ return;
306
+ const numbers = [match[1], match[2], match[3]].map((part) => Number(part));
307
+ if (numbers.some((part) => !Number.isFinite(part)))
308
+ return;
309
+ return { numbers, prerelease: match[4] };
310
+ }
311
+ function compareCliVersions(left, right) {
312
+ const a = parseVersion(left);
313
+ const b = parseVersion(right);
314
+ if (!a || !b)
315
+ return;
316
+ for (let index = 0;index < 3; index++) {
317
+ const difference = (a.numbers[index] ?? 0) - (b.numbers[index] ?? 0);
318
+ if (difference !== 0)
319
+ return difference < 0 ? -1 : 1;
320
+ }
321
+ if (a.prerelease === b.prerelease)
322
+ return 0;
323
+ if (a.prerelease === undefined)
324
+ return 1;
325
+ if (b.prerelease === undefined)
326
+ return -1;
327
+ return a.prerelease < b.prerelease ? -1 : 1;
328
+ }
329
+ async function checkCliUpdate(config) {
330
+ const now = config.now ?? Date.now();
331
+ const interval = config.intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
332
+ if (config.lastCheckedAt !== undefined && now - config.lastCheckedAt < interval) {
333
+ return { status: "skipped", nextCheckAt: config.lastCheckedAt + interval };
334
+ }
335
+ try {
336
+ const response = await fetchGuarded(new URL(config.manifestUrl), config.allowPrivateHosts ?? false, {
337
+ timeoutMs: config.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS,
338
+ bodyTimeoutMs: config.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS
339
+ });
340
+ if (!response.ok)
341
+ return { status: "unknown", reason: `manifest responded ${response.status}` };
342
+ const body = await readCapped(response, MANIFEST_MAX_BYTES);
343
+ if (!body)
344
+ return { status: "unknown", reason: "manifest is larger than expected" };
345
+ const parsed = CliBuildManifestSchema.safeParse(JSON.parse(body.toString("utf8")));
346
+ if (!parsed.success)
347
+ return { status: "unknown", reason: "manifest did not validate" };
348
+ const manifest = parsed.data;
349
+ const order = compareCliVersions(config.currentVersion, manifest.version);
350
+ if (order === undefined) {
351
+ return {
352
+ status: "unknown",
353
+ reason: `cannot compare ${config.currentVersion} with ${manifest.version}`
354
+ };
355
+ }
356
+ if (order >= 0)
357
+ return { status: "current", version: manifest.version };
358
+ const asset = selectCliBuildAsset(manifest, config.target ?? currentCliBuildTarget());
359
+ return {
360
+ status: "outdated",
361
+ version: manifest.version,
362
+ manifest,
363
+ ...asset && { asset }
364
+ };
365
+ } catch (error) {
366
+ return {
367
+ status: "unknown",
368
+ reason: error instanceof Error ? error.message : String(error)
369
+ };
370
+ }
371
+ }
372
+ async function applyCliUpdate(config) {
373
+ const target = config.targetPath ?? process.execPath;
374
+ const response = await fetchGuarded(new URL(config.asset.url), config.allowPrivateHosts ?? false, {
375
+ timeoutMs: config.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS,
376
+ bodyTimeoutMs: config.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS
377
+ });
378
+ if (!response.ok) {
379
+ throw new Error(`[stitchkit] update download responded ${response.status}`);
380
+ }
381
+ const transferred = await readCapped(response, config.maxBytes ?? DEFAULT_MAX_ASSET_BYTES);
382
+ if (!transferred)
383
+ throw new Error("[stitchkit] update download exceeded the size ceiling");
384
+ const bytes = config.asset.compression === "gzip" ? gunzipSync(transferred) : transferred;
385
+ if (bytes.length !== config.asset.size) {
386
+ throw new Error(`[stitchkit] update is ${bytes.length} bytes, manifest says ${config.asset.size} — refusing to install it`);
387
+ }
388
+ const sha256 = createHash("sha256").update(bytes).digest("hex");
389
+ if (sha256 !== config.asset.sha256) {
390
+ throw new Error(`[stitchkit] update digest ${sha256} does not match the manifest — refusing to install it`);
391
+ }
392
+ const staged = join2(dirname(target), `.${basename(target)}.${process.pid}.${Date.now()}`);
393
+ writeFileSync2(staged, bytes, { mode: 493 });
394
+ chmodSync2(staged, 493);
395
+ renameSync(staged, target);
396
+ return { path: target, bytes: bytes.length, sha256 };
397
+ }
26
398
  export {
399
+ selectCliBuildAsset,
400
+ routeCliArgv,
401
+ renderCliView,
402
+ renderCliInstaller,
27
403
  pollUntilDone,
28
404
  parseCliArgs,
405
+ formatCliBuildStamp,
406
+ extractCliGlobalOptions,
29
407
  emitResult,
30
408
  defineCliCommand,
409
+ currentCliBuildTarget,
410
+ createCliProfileStore,
31
411
  createCli,
32
- DEFAULT_EXIT_CODES
412
+ compareCliVersions,
413
+ coerceJsonArgs,
414
+ checkCliUpdate,
415
+ assertCliPublishable,
416
+ applyCliUpdate,
417
+ DEFAULT_EXIT_CODES,
418
+ CliProfileError,
419
+ CliBuildTargetSchema,
420
+ CliBuildStampSchema,
421
+ CliBuildManifestSchema,
422
+ CliBuildAssetSchema,
423
+ CliArgumentError
33
424
  };
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  executeToolMethod
3
- } from "./index-44ht2790.js";
3
+ } from "./index-8pjqv3zh.js";
4
4
  import {
5
5
  assertToolExtensionCompatible,
6
6
  mergeSchemas,
7
7
  projectToolSurface,
8
8
  rebuildObject
9
- } from "./index-r159gjwy.js";
9
+ } from "./index-fenaekmk.js";
10
10
 
11
11
  // src/tools/mount.ts
12
12
  import { z } from "zod";
@@ -18,13 +18,13 @@ import {
18
18
  probeAgentProcessSandbox,
19
19
  refuseMissingCodingPath
20
20
  } from "./index-gte38nbm.js";
21
+ import {
22
+ defineRuntimeTool
23
+ } from "./index-8z9we758.js";
21
24
  import {
22
25
  conflict,
23
26
  forbidden
24
27
  } from "./index-scs3f1eg.js";
25
- import {
26
- defineRuntimeTool
27
- } from "./index-kc6h6hg0.js";
28
28
 
29
29
  // src/agent-runtime/coding-tool-contract.ts
30
30
  import { z } from "zod";
@@ -4,16 +4,16 @@ import {
4
4
  } from "./index-7rkhw9ec.js";
5
5
  import {
6
6
  collectToolSurface
7
- } from "./index-wb15909q.js";
7
+ } from "./index-zsdgd1tz.js";
8
8
  import {
9
9
  createToolRunner,
10
10
  formatToolError
11
- } from "./index-2hrfpw2c.js";
11
+ } from "./index-1bnkzq95.js";
12
12
  import {
13
13
  isToolExecutionControlError,
14
14
  toolCauseFromResult,
15
15
  toolResultFromError
16
- } from "./index-44ht2790.js";
16
+ } from "./index-8pjqv3zh.js";
17
17
  import {
18
18
  isRecord
19
19
  } from "./index-77fekveh.js";
@@ -7,20 +7,20 @@ import {
7
7
  normalizeError,
8
8
  validateDeclaredOutput
9
9
  } from "./index-2hryh65w.js";
10
+ import {
11
+ coerceJsonArgs
12
+ } from "./index-7zbps32p.js";
13
+ import {
14
+ objectShapeKeys
15
+ } from "./index-fenaekmk.js";
10
16
  import {
11
17
  AppError,
12
18
  STITCH_ERROR_STATUS,
13
19
  isStitchErrorCode
14
20
  } from "./index-scs3f1eg.js";
15
- import {
16
- coerceJsonArgs
17
- } from "./index-7zbps32p.js";
18
21
  import {
19
22
  isUnsafeKey
20
23
  } from "./index-kzfs85xp.js";
21
- import {
22
- objectShapeKeys
23
- } from "./index-r159gjwy.js";
24
24
  import {
25
25
  isRecord
26
26
  } from "./index-77fekveh.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  projectRuntimeTool
3
- } from "./index-r159gjwy.js";
3
+ } from "./index-fenaekmk.js";
4
4
 
5
5
  // src/tools/runtime-tool.ts
6
6
  function defineRuntimeTool(definition) {
@@ -667,6 +667,40 @@ function assertUniqueToolName(name, taken, surface) {
667
667
 
668
668
  // src/tools/presentation.ts
669
669
  import { z as z2 } from "zod";
670
+
671
+ // src/tools/json-schema-dialect.ts
672
+ var DRAFT_07_MARKER = "draft-07";
673
+ var DRAFT_07_KEYWORD = "definitions";
674
+ var DEFS_KEYWORD = "$defs";
675
+ function declaresDraft07(dialect) {
676
+ return typeof dialect === "string" && dialect.includes(DRAFT_07_MARKER);
677
+ }
678
+ function rewriteDefinitionPointers(value) {
679
+ if (Array.isArray(value))
680
+ return value.map(rewriteDefinitionPointers);
681
+ if (!isRecord(value))
682
+ return value;
683
+ const rewritten = {};
684
+ for (const [key, child] of Object.entries(value)) {
685
+ rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith(`#/${DRAFT_07_KEYWORD}/`) ? `#/${DEFS_KEYWORD}/${child.slice(`#/${DRAFT_07_KEYWORD}/`.length)}` : rewriteDefinitionPointers(child);
686
+ }
687
+ return rewritten;
688
+ }
689
+ function withDefsDialect(schema) {
690
+ const definitions = schema[DRAFT_07_KEYWORD];
691
+ if (!isRecord(definitions) || DEFS_KEYWORD in schema)
692
+ return schema;
693
+ const rewritten = {};
694
+ for (const [key, value] of Object.entries(schema)) {
695
+ if (key === DRAFT_07_KEYWORD)
696
+ continue;
697
+ rewritten[key] = rewriteDefinitionPointers(value);
698
+ }
699
+ rewritten[DEFS_KEYWORD] = rewriteDefinitionPointers(definitions);
700
+ return rewritten;
701
+ }
702
+
703
+ // src/tools/presentation.ts
670
704
  function withoutDialect(schema) {
671
705
  const result = {};
672
706
  for (const [key, value] of Object.entries(schema)) {
@@ -684,25 +718,59 @@ function hasLocalReference(value) {
684
718
  return true;
685
719
  return Object.values(value).some(hasLocalReference);
686
720
  }
687
- function rewriteLocalReferences(value, namespace) {
721
+ var NAMESPACE_SEPARATOR = "__";
722
+ var DEFINITION_KEYWORDS = ["definitions", "$defs"];
723
+ function rewriteReference(reference, namespace, targets) {
724
+ if (reference === "#" || reference === "#/") {
725
+ targets.rootReferenced = true;
726
+ return `#/definitions/${namespace}`;
727
+ }
728
+ const segments = reference.slice(2).split("/");
729
+ const [keyword, name, ...rest] = segments;
730
+ if (keyword !== undefined && name !== undefined && DEFINITION_KEYWORDS.includes(keyword)) {
731
+ const renamed = `${namespace}${NAMESPACE_SEPARATOR}${name}`;
732
+ return ["#", "definitions", renamed, ...rest].join("/");
733
+ }
734
+ targets.rootReferenced = true;
735
+ return `#/definitions/${namespace}/${segments.join("/")}`;
736
+ }
737
+ function rewriteLocalReferences(value, namespace, targets) {
688
738
  if (Array.isArray(value)) {
689
- return value.map((child) => rewriteLocalReferences(child, namespace));
739
+ return value.map((child) => rewriteLocalReferences(child, namespace, targets));
690
740
  }
691
741
  if (!isRecord(value))
692
742
  return value;
693
743
  const rewritten = {};
694
744
  for (const [key, child] of Object.entries(value)) {
695
- rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith("#") ? `#/definitions/${namespace}${child.slice(1)}` : rewriteLocalReferences(child, namespace);
745
+ rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith("#") ? rewriteReference(child, namespace, targets) : rewriteLocalReferences(child, namespace, targets);
696
746
  }
697
747
  return rewritten;
698
748
  }
699
749
  function namespaceLocalReferences(schema, namespace) {
700
750
  if (!schema || !hasLocalReference(schema))
701
751
  return schema;
702
- const rewritten = rewriteLocalReferences(schema, namespace);
752
+ const targets = { rootReferenced: false };
753
+ const rewritten = rewriteLocalReferences(schema, namespace, targets);
703
754
  if (!isRecord(rewritten))
704
755
  return schema;
705
- return { ...rewritten, definitions: { [namespace]: rewritten } };
756
+ const definitions = {};
757
+ const body = {};
758
+ for (const [key, value] of Object.entries(rewritten)) {
759
+ if (DEFINITION_KEYWORDS.includes(key)) {
760
+ if (isRecord(value)) {
761
+ for (const [name, definition] of Object.entries(value)) {
762
+ definitions[`${namespace}${NAMESPACE_SEPARATOR}${name}`] = definition;
763
+ }
764
+ }
765
+ continue;
766
+ }
767
+ body[key] = value;
768
+ }
769
+ if (targets.rootReferenced)
770
+ definitions[namespace] = withoutDialect(body);
771
+ if (Object.keys(definitions).length === 0)
772
+ return body;
773
+ return { ...body, definitions };
706
774
  }
707
775
  function objectProperties(schema) {
708
776
  return schema.type === "object" && isRecord(schema.properties) ? schema.properties : null;
@@ -710,11 +778,29 @@ function objectProperties(schema) {
710
778
  function requiredKeys2(schema) {
711
779
  return Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : [];
712
780
  }
781
+ function hoistDefinitions(schema) {
782
+ const branches = Array.isArray(schema.allOf) ? schema.allOf : [];
783
+ const definitions = {};
784
+ const lifted = branches.map((branch) => {
785
+ if (!isRecord(branch) || !isRecord(branch.definitions))
786
+ return branch;
787
+ Object.assign(definitions, branch.definitions);
788
+ const rest = {};
789
+ for (const [key, value] of Object.entries(branch)) {
790
+ if (key !== "definitions")
791
+ rest[key] = value;
792
+ }
793
+ return rest;
794
+ });
795
+ if (Object.keys(definitions).length === 0)
796
+ return schema;
797
+ return { ...schema, allOf: lifted, definitions };
798
+ }
713
799
  function mergeObjectSchemas(left, right, rightOwnsUnknownKeys) {
714
800
  const leftProperties = objectProperties(left);
715
801
  const rightProperties = objectProperties(right);
716
802
  if (!leftProperties || !rightProperties)
717
- return { allOf: [left, right] };
803
+ return hoistDefinitions({ allOf: [left, right] });
718
804
  const conflicts = Object.keys(leftProperties).filter((key) => (key in rightProperties));
719
805
  if (conflicts.length > 0) {
720
806
  throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
@@ -777,7 +863,7 @@ function isObjectPresentationSchema(schema) {
777
863
  return schema.type === "object" && isRecord(schema.properties);
778
864
  }
779
865
  function presentationMetadata(schema) {
780
- return withoutDialect(schema);
866
+ return withDefsDialect(withoutDialect(schema));
781
867
  }
782
868
 
783
869
  // src/tools/internal/surface-projector.ts
@@ -1027,4 +1113,4 @@ function prepareProjectedMcpTools(tools, config = {}) {
1027
1113
  return prepared;
1028
1114
  }
1029
1115
 
1030
- export { objectShapeKeys, rebuildObject, mergeSchemas, validateMcpRoundPolicy, assertToolName, assertUniqueToolName, PORTABLE_JSON_SCHEMA_FORMATS, findNonPortableFormats, flattenToolJsonSchema, buildToolPresentationSchema, presentationMetadata, findUntypedProperties, assertToolExtensionCompatible, projectRuntimeTool, projectToolSurface, mcpProjectionCandidate, prepareProjectedMcpTools };
1116
+ export { objectShapeKeys, rebuildObject, mergeSchemas, validateMcpRoundPolicy, assertToolName, assertUniqueToolName, PORTABLE_JSON_SCHEMA_FORMATS, findNonPortableFormats, flattenToolJsonSchema, declaresDraft07, withDefsDialect, buildToolPresentationSchema, presentationMetadata, findUntypedProperties, assertToolExtensionCompatible, projectRuntimeTool, projectToolSurface, mcpProjectionCandidate, prepareProjectedMcpTools };