stitchkit 0.55.0 → 0.56.0

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 (69) hide show
  1. package/dist/browser/socket-io.d.ts +14 -6
  2. package/dist/browser/socket-io.d.ts.map +1 -1
  3. package/dist/cli.js +4 -4
  4. package/dist/contract/errors.d.ts +7 -0
  5. package/dist/contract/errors.d.ts.map +1 -1
  6. package/dist/contract/index.js +1 -1
  7. package/dist/files/boundary.d.ts +8 -5
  8. package/dist/files/boundary.d.ts.map +1 -1
  9. package/dist/files.js +1 -1
  10. package/dist/{index-rgd18hx3.js → index-28cqssm3.js} +7 -0
  11. package/dist/index-557by2db.js +34 -0
  12. package/dist/index-5r13htq1.js +283 -0
  13. package/dist/index-6y759j86.js +1031 -0
  14. package/dist/{index-1k16zv57.js → index-bfcpjw20.js} +125 -31
  15. package/dist/{index-0gv7k0ra.js → index-escqg10p.js} +73 -666
  16. package/dist/{index-v4bbq3p4.js → index-j3dem06f.js} +1 -1
  17. package/dist/{index-qx84bqzk.js → index-jcc611vh.js} +1 -1
  18. package/dist/{index-npye5kt7.js → index-n4nfa7gh.js} +3 -3
  19. package/dist/{index-pzc32v75.js → index-sm2tjx06.js} +41 -4
  20. package/dist/{index-js7yexng.js → index-xy8fmh6w.js} +83 -4
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +27 -6
  24. package/dist/node.js +5 -4
  25. package/dist/observability/index.js +3 -3
  26. package/dist/remote.js +1 -1
  27. package/dist/server/context-contribution.d.ts +8 -0
  28. package/dist/server/context-contribution.d.ts.map +1 -1
  29. package/dist/server/index.d.ts +1 -1
  30. package/dist/server/index.d.ts.map +1 -1
  31. package/dist/server/index.js +8 -5
  32. package/dist/server/middleware/auth.d.ts +29 -2
  33. package/dist/server/middleware/auth.d.ts.map +1 -1
  34. package/dist/testing/surface-conformance.d.ts +143 -10
  35. package/dist/testing/surface-conformance.d.ts.map +1 -1
  36. package/dist/testing/surface-manifest.d.ts +132 -33
  37. package/dist/testing/surface-manifest.d.ts.map +1 -1
  38. package/dist/testing.d.ts +2 -2
  39. package/dist/testing.d.ts.map +1 -1
  40. package/dist/testing.js +470 -122
  41. package/dist/tools/async-operation.d.ts +210 -18
  42. package/dist/tools/async-operation.d.ts.map +1 -1
  43. package/dist/tools/define-download-tool.d.ts.map +1 -1
  44. package/dist/tools/define-upload-tool.d.ts.map +1 -1
  45. package/dist/tools/internal/surface-projector.d.ts +101 -0
  46. package/dist/tools/internal/surface-projector.d.ts.map +1 -0
  47. package/dist/tools/managed-file-error.d.ts +6 -0
  48. package/dist/tools/managed-file-error.d.ts.map +1 -0
  49. package/dist/tools/mcp-prepare.d.ts +3 -21
  50. package/dist/tools/mcp-prepare.d.ts.map +1 -1
  51. package/dist/tools/mcp-round-policy.d.ts +9 -0
  52. package/dist/tools/mcp-round-policy.d.ts.map +1 -0
  53. package/dist/tools/mcp-round.d.ts +0 -4
  54. package/dist/tools/mcp-round.d.ts.map +1 -1
  55. package/dist/tools/mount-download.d.ts.map +1 -1
  56. package/dist/tools/mount-upload.d.ts.map +1 -1
  57. package/dist/tools/mount.d.ts +5 -9
  58. package/dist/tools/mount.d.ts.map +1 -1
  59. package/dist/tools/runtime-tool.d.ts.map +1 -1
  60. package/dist/tools/surface.d.ts +7 -0
  61. package/dist/tools/surface.d.ts.map +1 -1
  62. package/dist/tools/view-file.d.ts.map +1 -1
  63. package/dist/tools.d.ts +1 -1
  64. package/dist/tools.d.ts.map +1 -1
  65. package/dist/tools.js +348 -383
  66. package/llms-full.txt +361 -58
  67. package/package.json +1 -1
  68. package/dist/index-h60df7rj.js +0 -110
  69. package/dist/index-k4dftwf7.js +0 -66
@@ -2,14 +2,17 @@ import {
2
2
  isWithinDir
3
3
  } from "./index-sbdmyz75.js";
4
4
  import {
5
- assertToolName,
5
+ assertToolExtensionCompatible,
6
6
  assertUniqueToolName,
7
- hasUsableChars,
8
- toToolName
9
- } from "./index-k4dftwf7.js";
7
+ buildToolPresentationSchema,
8
+ mergeSchemas,
9
+ objectShapeKeys,
10
+ projectRuntimeTool,
11
+ projectToolSurface,
12
+ rebuildObject
13
+ } from "./index-6y759j86.js";
10
14
  import {
11
- jsonSchemaFields,
12
- toJsonSchema
15
+ jsonSchemaFields
13
16
  } from "./index-cby4ar3v.js";
14
17
  import {
15
18
  formatZodError,
@@ -17,14 +20,14 @@ import {
17
20
  normalizeError,
18
21
  runWithRequestContext,
19
22
  validateDeclaredOutput
20
- } from "./index-v4bbq3p4.js";
23
+ } from "./index-j3dem06f.js";
21
24
  import {
22
25
  AppError,
23
26
  STITCH_ERROR_STATUS,
24
27
  isStitchErrorCode,
25
28
  isUnsafeKey,
26
29
  safeJsonParse
27
- } from "./index-h60df7rj.js";
30
+ } from "./index-5r13htq1.js";
28
31
  import {
29
32
  isRecord
30
33
  } from "./index-7eq9va6e.js";
@@ -110,454 +113,8 @@ function coerceJsonArgs(args, schema) {
110
113
  return isRecord(coerced) ? coerced : args;
111
114
  }
112
115
 
113
- // src/tools/flatten-join.ts
114
- var ANNOTATION_KEYS = new Set(["$schema", "default", "description", "examples", "title"]);
115
- var TYPE_KEYWORDS = {
116
- array: [
117
- "contains",
118
- "items",
119
- "maxContains",
120
- "maxItems",
121
- "minContains",
122
- "minItems",
123
- "prefixItems",
124
- "uniqueItems"
125
- ],
126
- integer: ["exclusiveMaximum", "exclusiveMinimum", "maximum", "minimum", "multipleOf"],
127
- number: ["exclusiveMaximum", "exclusiveMinimum", "maximum", "minimum", "multipleOf"],
128
- object: [
129
- "additionalProperties",
130
- "dependentRequired",
131
- "dependentSchemas",
132
- "maxProperties",
133
- "minProperties",
134
- "patternProperties",
135
- "properties",
136
- "propertyNames",
137
- "required"
138
- ],
139
- string: [
140
- "contentEncoding",
141
- "contentMediaType",
142
- "format",
143
- "maxLength",
144
- "minLength",
145
- "pattern"
146
- ]
147
- };
148
- function nullableProjection(schema) {
149
- if (!Array.isArray(schema.anyOf) || schema.anyOf.length !== 2)
150
- return schema;
151
- const branches = schema.anyOf.filter(isRecord);
152
- if (branches.length !== 2)
153
- return schema;
154
- const nullBranch = branches.find((branch) => branch.type === "null");
155
- const value = branches.find((branch) => typeof branch.type === "string" && branch.type !== "null");
156
- if (!nullBranch || !value || Object.keys(nullBranch).some((key) => key !== "type")) {
157
- return schema;
158
- }
159
- const type = value.type;
160
- if (typeof type !== "string")
161
- return schema;
162
- const projected = { type: [type, "null"] };
163
- for (const key of [...ANNOTATION_KEYS, ...TYPE_KEYWORDS[type] ?? []]) {
164
- if (value[key] !== undefined)
165
- projected[key] = value[key];
166
- else if (schema[key] !== undefined)
167
- projected[key] = schema[key];
168
- }
169
- if (value.const !== undefined)
170
- projected.enum = [value.const, null];
171
- else if (Array.isArray(value.enum))
172
- projected.enum = [...value.enum, null];
173
- return projected;
174
- }
175
- function withoutAnnotations(schema) {
176
- const result = {};
177
- for (const [key, value] of Object.entries(schema)) {
178
- if (!ANNOTATION_KEYS.has(key))
179
- result[key] = value;
180
- }
181
- return result;
182
- }
183
- function stableJson(value) {
184
- if (Array.isArray(value))
185
- return `[${value.map(stableJson).join(",")}]`;
186
- if (!isRecord(value))
187
- return JSON.stringify(value) ?? "undefined";
188
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableJson(value[key])}`).join(",")}}`;
189
- }
190
- function stringValues(schema) {
191
- if (typeof schema.const === "string")
192
- return [schema.const];
193
- if (!Array.isArray(schema.enum))
194
- return null;
195
- const values = schema.enum.filter((value) => typeof value === "string");
196
- return values.length === schema.enum.length ? values : null;
197
- }
198
- var JSON_SCHEMA_TYPE_ORDER = [
199
- "string",
200
- "number",
201
- "integer",
202
- "boolean",
203
- "object",
204
- "array",
205
- "null"
206
- ];
207
- function jsonSchemaType(value) {
208
- switch (value) {
209
- case "array":
210
- case "boolean":
211
- case "integer":
212
- case "null":
213
- case "number":
214
- case "object":
215
- case "string":
216
- return value;
217
- default:
218
- return null;
219
- }
220
- }
221
- function valueType(value) {
222
- if (value === null)
223
- return "null";
224
- if (Array.isArray(value))
225
- return "array";
226
- if (isRecord(value))
227
- return "object";
228
- if (typeof value === "string")
229
- return "string";
230
- if (typeof value === "number")
231
- return "number";
232
- if (typeof value === "boolean")
233
- return "boolean";
234
- return null;
235
- }
236
- function normalizeTypes(types) {
237
- const normalized = new Set(types);
238
- if (normalized.has("number"))
239
- normalized.delete("integer");
240
- return JSON_SCHEMA_TYPE_ORDER.filter((type) => normalized.has(type));
241
- }
242
- function combinedBranchTypes(schema) {
243
- for (const keyword of ["oneOf", "anyOf"]) {
244
- const value = schema[keyword];
245
- if (!Array.isArray(value) || value.length === 0)
246
- continue;
247
- const collected = [];
248
- for (const branch of value) {
249
- if (!isRecord(branch))
250
- return null;
251
- const types = typeNames(branch);
252
- if (!types)
253
- return null;
254
- collected.push(...types);
255
- }
256
- return normalizeTypes(collected);
257
- }
258
- return null;
259
- }
260
- function typeNames(schema) {
261
- const direct = jsonSchemaType(schema.type);
262
- if (direct)
263
- return [direct];
264
- if (Array.isArray(schema.type)) {
265
- const values = [];
266
- for (const value of schema.type) {
267
- const type = jsonSchemaType(value);
268
- if (!type)
269
- return null;
270
- values.push(type);
271
- }
272
- return values.length > 0 ? normalizeTypes(values) : null;
273
- }
274
- if (schema.const !== undefined) {
275
- const type = valueType(schema.const);
276
- return type ? [type] : null;
277
- }
278
- if (Array.isArray(schema.enum) && schema.enum.length > 0) {
279
- const values = [];
280
- for (const value of schema.enum) {
281
- const type = valueType(value);
282
- if (!type)
283
- return null;
284
- values.push(type);
285
- }
286
- return normalizeTypes(values);
287
- }
288
- return combinedBranchTypes(schema);
289
- }
290
- function typeSchema(type, nullable) {
291
- const schema = { type: nullable ? [type, "null"] : type };
292
- if (type === "array")
293
- schema.items = {};
294
- if (type === "object")
295
- schema.additionalProperties = {};
296
- return schema;
297
- }
298
- function commonBaseType(schemas) {
299
- const names = schemas.map(typeNames);
300
- if (names.some((value) => value === null))
301
- return {};
302
- let nullable = false;
303
- const bases = new Set;
304
- for (const branch of names) {
305
- if (!branch)
306
- return {};
307
- for (const name of branch) {
308
- if (name === "null")
309
- nullable = true;
310
- else
311
- bases.add(name);
312
- }
313
- }
314
- if (bases.size === 0)
315
- return nullable ? { type: "null" } : {};
316
- if (bases.size === 1) {
317
- const [only] = bases;
318
- return only ? typeSchema(only, nullable) : {};
319
- }
320
- if ([...bases].every((name) => name === "integer" || name === "number")) {
321
- return typeSchema("number", nullable);
322
- }
323
- const types = normalizeTypes(nullable ? [...bases, "null"] : bases);
324
- return types.length > 0 ? { type: types } : {};
325
- }
326
- function mergePropertySchemas(properties) {
327
- const schemas = properties.map((property) => nullableProjection(property.schema));
328
- const structural = schemas.map(withoutAnnotations);
329
- const [first] = structural;
330
- let merged;
331
- if (first && structural.every((schema) => stableJson(schema) === stableJson(first))) {
332
- merged = structuredClone(first);
333
- } else {
334
- const values = schemas.map(stringValues);
335
- const allStrings = values.every((value) => value !== null);
336
- merged = allStrings ? { type: "string", enum: [...new Set(values.flatMap((value) => value ?? []))] } : commonBaseType(schemas);
337
- }
338
- const descriptions = [
339
- ...new Set(schemas.map((schema) => schema.description).filter((value) => typeof value === "string"))
340
- ];
341
- if (descriptions.length === 1)
342
- merged.description = descriptions[0];
343
- return merged;
344
- }
345
-
346
- // src/tools/flatten.ts
347
- function rebuild(value) {
348
- if (Array.isArray(value))
349
- return value.map(rebuild);
350
- if (!isRecord(value))
351
- return value;
352
- const node = {};
353
- for (const [key, child] of Object.entries(value))
354
- node[key] = rebuild(child);
355
- return flattenNode(node);
356
- }
357
- function stringValues2(schema) {
358
- if (typeof schema.const === "string")
359
- return [schema.const];
360
- if (!Array.isArray(schema.enum))
361
- return null;
362
- const values = schema.enum.filter((value) => typeof value === "string");
363
- return values.length === schema.enum.length ? values : null;
364
- }
365
- function objectVariants(node) {
366
- if (!Array.isArray(node.oneOf) || node.oneOf.length < 2)
367
- return null;
368
- const variants = node.oneOf.filter(isRecord);
369
- if (variants.length !== node.oneOf.length)
370
- return null;
371
- if (variants.some((variant) => variant.type !== "object" || !isRecord(variant.properties))) {
372
- return null;
373
- }
374
- return variants;
375
- }
376
- function findDiscriminator(variants) {
377
- const [first] = variants;
378
- if (!first || !isRecord(first.properties))
379
- return null;
380
- for (const key of Object.keys(first.properties).sort()) {
381
- const values = [];
382
- const seen = new Set;
383
- let valid = true;
384
- for (const variant of variants) {
385
- if (!requiredKeys(variant).has(key)) {
386
- valid = false;
387
- break;
388
- }
389
- const properties = variant.properties;
390
- const field = isRecord(properties) ? properties[key] : undefined;
391
- const branchValues = isRecord(field) ? stringValues2(field) : null;
392
- if (!branchValues || branchValues.length === 0) {
393
- valid = false;
394
- break;
395
- }
396
- for (const value of branchValues) {
397
- if (seen.has(value)) {
398
- valid = false;
399
- break;
400
- }
401
- seen.add(value);
402
- }
403
- if (!valid)
404
- break;
405
- values.push(branchValues);
406
- }
407
- if (valid)
408
- return { key, values };
409
- }
410
- return null;
411
- }
412
- function requiredKeys(variant) {
413
- if (!Array.isArray(variant.required))
414
- return new Set;
415
- return new Set(variant.required.filter((key) => typeof key === "string"));
416
- }
417
- function appendHint(schema, hint) {
418
- const description = typeof schema.description === "string" ? schema.description : undefined;
419
- return { ...schema, description: description ? `${description} ${hint}` : hint };
420
- }
421
- function flattenNode(node) {
422
- const variants = objectVariants(node);
423
- if (!variants)
424
- return node;
425
- const discriminator = findDiscriminator(variants);
426
- if (!discriminator)
427
- return node;
428
- const perKey = new Map;
429
- for (let index = 0;index < variants.length; index++) {
430
- const variant = variants[index];
431
- if (!variant)
432
- continue;
433
- const labels = discriminator.values[index] ?? [];
434
- const required2 = requiredKeys(variant);
435
- if (!isRecord(variant.properties))
436
- continue;
437
- for (const [key, rawSchema] of Object.entries(variant.properties)) {
438
- if (key === discriminator.key || !isRecord(rawSchema))
439
- continue;
440
- const entries = perKey.get(key) ?? [];
441
- entries.push({ schema: rawSchema, labels, required: required2.has(key) });
442
- perKey.set(key, entries);
443
- }
444
- }
445
- const discriminatorProperties = [];
446
- for (let index = 0;index < variants.length; index++) {
447
- const variant = variants[index];
448
- if (!variant || !isRecord(variant.properties))
449
- continue;
450
- const schema = variant.properties[discriminator.key];
451
- if (!isRecord(schema))
452
- continue;
453
- discriminatorProperties.push({
454
- schema,
455
- labels: discriminator.values[index] ?? [],
456
- required: true
457
- });
458
- }
459
- const properties = {
460
- [discriminator.key]: mergePropertySchemas(discriminatorProperties)
461
- };
462
- const required = [discriminator.key];
463
- for (const [key, entries] of perKey) {
464
- let merged = mergePropertySchemas(entries);
465
- const requiredEverywhere = entries.length === variants.length && entries.every((entry) => entry.required);
466
- if (requiredEverywhere) {
467
- required.push(key);
468
- } else {
469
- const requiredLabels = entries.filter((entry) => entry.required).flatMap((entry) => entry.labels);
470
- const presentLabels = entries.flatMap((entry) => entry.labels);
471
- const labels = requiredLabels.length > 0 ? requiredLabels : presentLabels;
472
- const verb = requiredLabels.length > 0 ? "Required" : "Available";
473
- merged = appendHint(merged, `${verb} if ${discriminator.key} = ${[...new Set(labels)].join(" | ")}`);
474
- }
475
- properties[key] = merged;
476
- }
477
- const result = {};
478
- for (const [key, value] of Object.entries(node)) {
479
- if (key !== "oneOf" && key !== "anyOf" && key !== "properties" && key !== "required") {
480
- result[key] = value;
481
- }
482
- }
483
- result.type = "object";
484
- result.properties = properties;
485
- result.required = required;
486
- result.additionalProperties = variants.every((variant) => variant.additionalProperties === false) ? false : {};
487
- return result;
488
- }
489
- function flattenToolJsonSchema(schema) {
490
- const result = rebuild(schema);
491
- return isRecord(result) ? result : {};
492
- }
493
- function freezeToolJsonSchema(schema) {
494
- for (const value of Object.values(schema))
495
- freezeJsonValue(value);
496
- return Object.freeze(schema);
497
- }
498
- function freezeJsonValue(value) {
499
- if (Array.isArray(value)) {
500
- for (const item of value)
501
- freezeJsonValue(item);
502
- Object.freeze(value);
503
- } else if (isRecord(value)) {
504
- freezeToolJsonSchema(value);
505
- }
506
- }
507
-
508
116
  // src/tools/mount.ts
509
- import { z as z4 } from "zod";
510
-
511
- // src/tools/schema.ts
512
117
  import { z as z2 } from "zod";
513
- function objectShapeKeys(schema) {
514
- return schema instanceof z2.ZodObject ? Object.keys(schema.shape) : [];
515
- }
516
- function keyPolicyOf(schema) {
517
- return schema.def.catchall;
518
- }
519
- function rebuildObject(source, shape) {
520
- return withKeyPolicy(z2.object(shape), keyPolicyOf(source));
521
- }
522
- function withKeyPolicy(object, policy) {
523
- if (policy === undefined)
524
- return object;
525
- return object.catchall(representable(policy));
526
- }
527
- function representable(policy) {
528
- if (policy instanceof z2.ZodNever || policy instanceof z2.ZodUnknown)
529
- return policy;
530
- if (!(policy instanceof z2.ZodType))
531
- return z2.unknown();
532
- try {
533
- toJsonSchema(policy, "input");
534
- return policy;
535
- } catch {
536
- return z2.unknown();
537
- }
538
- }
539
- function mergeSchemas(paramsSchema, inputSchema) {
540
- if (paramsSchema && !(paramsSchema instanceof z2.ZodObject)) {
541
- throw new Error("Tool params schema must be a z.object()");
542
- }
543
- const paramsObject = paramsSchema instanceof z2.ZodObject ? paramsSchema : undefined;
544
- if (!inputSchema) {
545
- return paramsObject ?? z2.object({});
546
- }
547
- if (inputSchema instanceof z2.ZodObject) {
548
- if (paramsObject) {
549
- const conflicts = Object.keys(paramsObject.shape).filter((key) => (key in inputSchema.shape));
550
- if (conflicts.length > 0) {
551
- throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
552
- }
553
- }
554
- return rebuildObject(inputSchema, {
555
- ...paramsObject?.shape ?? {},
556
- ...inputSchema.shape
557
- });
558
- }
559
- return paramsObject ? z2.intersection(paramsObject, inputSchema) : inputSchema;
560
- }
561
118
 
562
119
  // src/tools/execute.ts
563
120
  var normalizedToolErrors = new WeakMap;
@@ -779,174 +336,44 @@ async function runToolMethod(method, toolName, rawArgs, context, hooks, lifecycl
779
336
  }
780
337
  }
781
338
 
782
- // src/tools/presentation.ts
783
- import { z as z3 } from "zod";
784
- function withoutDialect(schema) {
785
- const result = {};
786
- for (const [key, value] of Object.entries(schema)) {
787
- if (key !== "$schema")
788
- result[key] = value;
789
- }
790
- return result;
791
- }
792
- function hasLocalReference(value) {
793
- if (Array.isArray(value))
794
- return value.some(hasLocalReference);
795
- if (!isRecord(value))
796
- return false;
797
- if (typeof value.$ref === "string" && value.$ref.startsWith("#"))
798
- return true;
799
- return Object.values(value).some(hasLocalReference);
800
- }
801
- function rewriteLocalReferences(value, namespace) {
802
- if (Array.isArray(value)) {
803
- return value.map((child) => rewriteLocalReferences(child, namespace));
804
- }
805
- if (!isRecord(value))
806
- return value;
807
- const rewritten = {};
808
- for (const [key, child] of Object.entries(value)) {
809
- rewritten[key] = key === "$ref" && typeof child === "string" && child.startsWith("#") ? `#/definitions/${namespace}${child.slice(1)}` : rewriteLocalReferences(child, namespace);
810
- }
811
- return rewritten;
812
- }
813
- function namespaceLocalReferences(schema, namespace) {
814
- if (!schema || !hasLocalReference(schema))
815
- return schema;
816
- const rewritten = rewriteLocalReferences(schema, namespace);
817
- if (!isRecord(rewritten))
818
- return schema;
819
- return { ...rewritten, definitions: { [namespace]: rewritten } };
820
- }
821
- function objectProperties(schema) {
822
- return schema.type === "object" && isRecord(schema.properties) ? schema.properties : null;
823
- }
824
- function requiredKeys2(schema) {
825
- return Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : [];
826
- }
827
- function mergeObjectSchemas(left, right, rightOwnsUnknownKeys) {
828
- const leftProperties = objectProperties(left);
829
- const rightProperties = objectProperties(right);
830
- if (!leftProperties || !rightProperties)
831
- return { allOf: [left, right] };
832
- const conflicts = Object.keys(leftProperties).filter((key) => (key in rightProperties));
833
- if (conflicts.length > 0) {
834
- throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
835
- }
836
- const merged = {
837
- type: "object",
838
- properties: { ...leftProperties, ...rightProperties },
839
- required: [...new Set([...requiredKeys2(left), ...requiredKeys2(right)])]
840
- };
841
- const leftDefinitions = isRecord(left.definitions) ? left.definitions : {};
842
- const rightDefinitions = isRecord(right.definitions) ? right.definitions : {};
843
- const definitions = { ...leftDefinitions, ...rightDefinitions };
844
- if (Object.keys(definitions).length > 0)
845
- merged.definitions = definitions;
846
- const unknownKeys = rightOwnsUnknownKeys ? right.additionalProperties : left.additionalProperties;
847
- if (unknownKeys !== undefined)
848
- merged.additionalProperties = unknownKeys;
849
- return merged;
850
- }
851
- function schemaFromZod(schema, unrepresentable, flatten) {
852
- if (!schema)
853
- return;
854
- const json = toJsonSchema(schema, "input", unrepresentable, "draft-07");
855
- return flatten ? flattenToolJsonSchema(json) : json;
856
- }
857
- function buildToolPresentationSchema(config) {
858
- const unrepresentable = config.unrepresentable ?? "any";
859
- const flatten = config.flattenUnionInput ?? false;
860
- const params = namespaceLocalReferences(schemaFromZod(config.paramsSchema, unrepresentable, flatten), "params");
861
- const input = namespaceLocalReferences(schemaFromZod(config.inputSchema, unrepresentable, flatten), "input");
862
- let presentation;
863
- if (params && input) {
864
- presentation = mergeObjectSchemas(withoutDialect(params), withoutDialect(input), true);
865
- } else if (input) {
866
- presentation = input;
867
- } else if (params) {
868
- presentation = params;
869
- } else {
870
- presentation = {
871
- $schema: "http://json-schema.org/draft-07/schema#",
872
- type: "object",
873
- properties: {}
874
- };
875
- }
876
- if (config.extendSchema) {
877
- const extra = namespaceLocalReferences(schemaFromZod(z3.object(config.extendSchema), unrepresentable, flatten), "extend");
878
- if (extra) {
879
- presentation = mergeObjectSchemas(withoutDialect(extra), withoutDialect(presentation), true);
880
- }
881
- }
882
- if (presentation.$schema === undefined) {
883
- presentation = {
884
- $schema: "http://json-schema.org/draft-07/schema#",
885
- ...presentation
886
- };
887
- }
888
- return freezeToolJsonSchema(presentation);
889
- }
890
- function isObjectPresentationSchema(schema) {
891
- return schema.type === "object" && isRecord(schema.properties);
892
- }
893
- function presentationMetadata(schema) {
894
- return withoutDialect(schema);
895
- }
896
-
897
339
  // src/tools/mount.ts
898
340
  function applyExtend(base, extra) {
899
- if (base instanceof z4.ZodObject) {
900
- const conflicts = Object.keys(extra).filter((key) => (key in base.shape));
901
- if (conflicts.length > 0) {
902
- throw new Error(`Tool extend conflict: ${conflicts.join(", ")} already declared by the contract`);
903
- }
341
+ if (base instanceof z2.ZodObject) {
342
+ assertToolExtensionCompatible(base, extra);
904
343
  return rebuildObject(base, { ...extra, ...base.shape });
905
344
  }
906
- return z4.intersection(z4.object(extra), base);
345
+ return z2.intersection(z2.object(extra), base);
346
+ }
347
+ function contractToolMountable(projected, extend) {
348
+ const method = projected.source;
349
+ const baseArgumentSchema = mergeSchemas(method.paramsSchema, method.inputSchema);
350
+ const argumentSchema = projected.shouldExtend && extend ? applyExtend(baseArgumentSchema, extend.schema) : baseArgumentSchema;
351
+ return {
352
+ method,
353
+ name: projected.name,
354
+ argumentSchema,
355
+ presentationSchema: projected.presentationSchema,
356
+ shouldExtend: projected.shouldExtend
357
+ };
907
358
  }
908
359
  function collectTools(service, transport, config = {}) {
909
360
  const { extend, flattenUnionInput = false, assertNames = true } = config;
910
361
  const tools = [];
911
- for (const [methodName, method] of Object.entries(service.methods)) {
912
- if (transport === "CLI") {
913
- if (!method.expose?.includes("CLI"))
914
- continue;
915
- } else if (method.expose && !method.expose.includes(transport)) {
916
- continue;
917
- }
918
- if (method.multipart)
919
- continue;
920
- if (method.rawBody)
921
- continue;
922
- if (method.responseMeta)
923
- continue;
924
- if (method.rawResponse)
362
+ for (const projected of projectToolSurface({ services: [service] }, transport === "HTTP" ? "AGENT" : transport, {
363
+ extend,
364
+ flattenUnionInput,
365
+ assertNames,
366
+ assertUniqueNames: false
367
+ })) {
368
+ if (projected.kind !== "contract")
925
369
  continue;
926
- const name = method.toolName ?? toToolName(service.name, methodName);
927
- if (assertNames && transport !== "CLI") {
928
- if (!method.toolName && !hasUsableChars(service.name)) {
929
- throw new Error(`Service prefix "${service.name}" (method "${methodName}") has no characters usable in a tool name — set an explicit \`toolName\` or rename the prefix`);
930
- }
931
- assertToolName(name, service.name, methodName);
932
- }
933
- const shouldExtend = !!extend && (!extend.filter || extend.filter(service, method));
934
- const baseArgumentSchema = mergeSchemas(method.paramsSchema, method.inputSchema);
935
- const argumentSchema = shouldExtend && extend ? applyExtend(baseArgumentSchema, extend.schema) : baseArgumentSchema;
936
- const presentationSchema = buildToolPresentationSchema({
937
- paramsSchema: method.paramsSchema,
938
- inputSchema: method.inputSchema,
939
- extendSchema: shouldExtend ? extend?.schema : undefined,
940
- flattenUnionInput,
941
- unrepresentable: "any"
942
- });
943
- tools.push({ method, name, argumentSchema, presentationSchema, shouldExtend });
370
+ tools.push(contractToolMountable(projected, extend));
944
371
  }
945
372
  return tools;
946
373
  }
947
374
  function createToolRunner(config) {
948
375
  const extension = config.extend ? {
949
- schema: z4.object(config.extend.schema),
376
+ schema: z2.object(config.extend.schema),
950
377
  resolve: config.extend.resolve
951
378
  } : undefined;
952
379
  return async function runOneToolCall(tool, rawArgs, context) {
@@ -1020,14 +447,6 @@ function createRuntimeToolFactory(config) {
1020
447
  }
1021
448
  return { define };
1022
449
  }
1023
- function runtimeToolSupports(definition, transport) {
1024
- if (definition.transports?.length === 0) {
1025
- throw new Error(`Runtime tool "${definition.name}" must expose at least one transport`);
1026
- }
1027
- if (!definition.transports)
1028
- return transport !== "CLI";
1029
- return definition.transports.includes(transport);
1030
- }
1031
450
  function runtimeToolIdentity(definition) {
1032
451
  return {
1033
452
  method: definition.identity.method,
@@ -1043,9 +462,7 @@ function runtimeToolIdentity(definition) {
1043
462
  };
1044
463
  }
1045
464
  function runtimeToolMountable(definition, assertName = true) {
1046
- if (assertName) {
1047
- assertToolName(definition.name, definition.identity.serviceName, definition.identity.action);
1048
- }
465
+ const projected = projectRuntimeTool(definition, assertName);
1049
466
  const method = {
1050
467
  ...runtimeToolIdentity(definition),
1051
468
  inputSchema: definition.input,
@@ -1054,18 +471,15 @@ function runtimeToolMountable(definition, assertName = true) {
1054
471
  };
1055
472
  return {
1056
473
  method,
1057
- name: definition.name,
474
+ name: projected.name,
1058
475
  argumentSchema: definition.input,
1059
- presentationSchema: buildToolPresentationSchema({
1060
- inputSchema: definition.input,
1061
- unrepresentable: "any"
1062
- }),
476
+ presentationSchema: projected.presentationSchema,
1063
477
  shouldExtend: false
1064
478
  };
1065
479
  }
1066
480
 
1067
481
  // src/tools/cli-args.ts
1068
- import { z as z5 } from "zod";
482
+ import { z as z3 } from "zod";
1069
483
  var NUMERIC_VALUE = /^-(\d+\.?\d*|\.\d+)$/;
1070
484
  var BOOL_OPTIONS = new Set(["json", "wait", "quiet", "dry-run", "help"]);
1071
485
  var VALUE_OPTIONS = new Set(["wait-timeout", "output-dir"]);
@@ -1075,27 +489,27 @@ class CliArgumentError extends Error {
1075
489
  name = "CliArgumentError";
1076
490
  }
1077
491
  function unwrap(field) {
1078
- if (field instanceof z5.ZodOptional || field instanceof z5.ZodNullable || field instanceof z5.ZodDefault) {
492
+ if (field instanceof z3.ZodOptional || field instanceof z3.ZodNullable || field instanceof z3.ZodDefault) {
1079
493
  return unwrap(field.unwrap());
1080
494
  }
1081
495
  return field;
1082
496
  }
1083
497
  function classify(field) {
1084
- if (field instanceof z5.ZodBoolean)
498
+ if (field instanceof z3.ZodBoolean)
1085
499
  return "boolean";
1086
- if (field instanceof z5.ZodNumber)
500
+ if (field instanceof z3.ZodNumber)
1087
501
  return "number";
1088
- if (field instanceof z5.ZodBigInt)
502
+ if (field instanceof z3.ZodBigInt)
1089
503
  return "bigint";
1090
- if (field instanceof z5.ZodDate)
504
+ if (field instanceof z3.ZodDate)
1091
505
  return "date";
1092
- if (field instanceof z5.ZodEnum)
506
+ if (field instanceof z3.ZodEnum)
1093
507
  return "enum";
1094
- if (field instanceof z5.ZodArray)
508
+ if (field instanceof z3.ZodArray)
1095
509
  return "array";
1096
- if (field instanceof z5.ZodObject)
510
+ if (field instanceof z3.ZodObject)
1097
511
  return "object";
1098
- if (field instanceof z5.ZodString || field instanceof z5.ZodLiteral)
512
+ if (field instanceof z3.ZodString || field instanceof z3.ZodLiteral)
1099
513
  return "string";
1100
514
  return "other";
1101
515
  }
@@ -1115,11 +529,11 @@ function mergeField(fields, name, info) {
1115
529
  }
1116
530
  function collectSchemaFields(schema, fields) {
1117
531
  const base = unwrap(schema);
1118
- if (base instanceof z5.ZodObject) {
532
+ if (base instanceof z3.ZodObject) {
1119
533
  for (const [name, raw] of Object.entries(base.shape)) {
1120
534
  const fieldBase = unwrap(raw);
1121
535
  const kind = classify(fieldBase);
1122
- if (kind === "array" && fieldBase instanceof z5.ZodArray) {
536
+ if (kind === "array" && fieldBase instanceof z3.ZodArray) {
1123
537
  mergeField(fields, name, { kind, elementKind: classify(unwrap(fieldBase.element)) });
1124
538
  } else {
1125
539
  mergeField(fields, name, { kind });
@@ -1127,12 +541,12 @@ function collectSchemaFields(schema, fields) {
1127
541
  }
1128
542
  return;
1129
543
  }
1130
- if (base instanceof z5.ZodUnion) {
544
+ if (base instanceof z3.ZodUnion) {
1131
545
  for (const option of base.def.options)
1132
546
  collectSchemaFields(option, fields);
1133
547
  return;
1134
548
  }
1135
- if (base instanceof z5.ZodIntersection) {
549
+ if (base instanceof z3.ZodIntersection) {
1136
550
  collectSchemaFields(base.def.left, fields);
1137
551
  collectSchemaFields(base.def.right, fields);
1138
552
  return;
@@ -1921,13 +1335,6 @@ async function writeDownload(root, target, data) {
1921
1335
  }
1922
1336
 
1923
1337
  // src/tools/surface.ts
1924
- function duplicateLabel(transport) {
1925
- if (transport === "MCP")
1926
- return "MCP tool name";
1927
- if (transport === "AGENT")
1928
- return "agent tool name";
1929
- return "CLI command";
1930
- }
1931
1338
  function collectToolSurface({
1932
1339
  surface,
1933
1340
  transport,
@@ -1935,35 +1342,35 @@ function collectToolSurface({
1935
1342
  ...collectConfig
1936
1343
  }) {
1937
1344
  const entries = [];
1938
- const names = new Set;
1939
1345
  const append = (entry) => {
1940
- if (assertUniqueNames) {
1941
- assertUniqueToolName(entry.mountable.name, names.has(entry.mountable.name), duplicateLabel(transport));
1942
- }
1943
- names.add(entry.mountable.name);
1944
1346
  entries.push(entry);
1945
1347
  };
1946
- for (const service of surface.services ?? []) {
1947
- for (const mountable of collectTools(service, transport, collectConfig)) {
1348
+ for (const projected of projectToolSurface(surface, transport, {
1349
+ extend: collectConfig.extend,
1350
+ flattenUnionInput: collectConfig.flattenUnionInput,
1351
+ assertNames: collectConfig.assertNames,
1352
+ assertUniqueNames
1353
+ })) {
1354
+ if (projected.kind === "contract") {
1355
+ const mountable = contractToolMountable(projected, collectConfig.extend);
1948
1356
  append({
1949
1357
  kind: "contract",
1950
- service: service.name,
1358
+ service: projected.serviceName,
1951
1359
  action: mountable.method.key,
1952
- mountable
1360
+ mountable,
1361
+ projection: projected
1362
+ });
1363
+ } else {
1364
+ append({
1365
+ kind: "runtime",
1366
+ service: projected.serviceName,
1367
+ action: projected.action,
1368
+ mountable: runtimeToolMountable(projected.source, false),
1369
+ definition: projected.source,
1370
+ projection: projected
1953
1371
  });
1954
1372
  }
1955
1373
  }
1956
- for (const definition of surface.runtimeTools ?? []) {
1957
- if (!runtimeToolSupports(definition, transport))
1958
- continue;
1959
- append({
1960
- kind: "runtime",
1961
- service: definition.identity.serviceName,
1962
- action: definition.identity.action,
1963
- mountable: runtimeToolMountable(definition, collectConfig.assertNames),
1964
- definition
1965
- });
1966
- }
1967
1374
  return entries;
1968
1375
  }
1969
1376
 
@@ -2383,4 +1790,4 @@ async function createCli(config) {
2383
1790
  return exit(downloadsOk ? exitCode : 1);
2384
1791
  }
2385
1792
 
2386
- export { coerceJsonArgs, toolResultFromError, toolErrorFromResult, executeToolMethod, flattenToolJsonSchema, buildToolPresentationSchema, isObjectPresentationSchema, presentationMetadata, collectTools, createToolRunner, formatToolError, defineRuntimeTool, createRuntimeToolFactory, collectToolSurface, WaitTimeoutError, runWaitOperation, fetchGuarded, fetchPinnedDocument, readCapped, parseCliArgs, defineCliCommand, DEFAULT_EXIT_CODES, emitResult, pollUntilDone, createCli };
1793
+ export { coerceJsonArgs, toolResultFromError, toolErrorFromResult, executeToolMethod, collectTools, createToolRunner, formatToolError, defineRuntimeTool, createRuntimeToolFactory, collectToolSurface, WaitTimeoutError, runWaitOperation, fetchGuarded, fetchPinnedDocument, readCapped, parseCliArgs, defineCliCommand, DEFAULT_EXIT_CODES, emitResult, pollUntilDone, createCli };