stitchkit 0.33.0 → 0.35.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.
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  emitResult,
5
5
  parseCliArgs,
6
6
  pollUntilDone
7
- } from "./index-jr8vf7g8.js";
7
+ } from "./index-bfabej0h.js";
8
8
  import"./index-0ed3bx43.js";
9
9
  import"./index-x3fcszf8.js";
10
10
  import"./index-enc7t99e.js";
@@ -229,30 +229,97 @@ function stripAnnotations(node) {
229
229
  stripAnnotations(value);
230
230
  }
231
231
  }
232
- function hasChecks(schema) {
232
+ function hasInvisibleConstraint(schema) {
233
233
  if (!(schema instanceof z3.ZodType))
234
234
  return false;
235
235
  const def = schema.def;
236
- if (isRecord(def) && Array.isArray(def.checks) && def.checks.length > 0)
236
+ if (isRecord(def) && def.type !== "unknown" && def.type !== "any") {
237
+ if (normalizedJson(schema) === "{}")
238
+ return true;
239
+ }
240
+ if (schema instanceof z3.ZodCatch)
241
+ return true;
242
+ if (isRecord(def) && def.coerce === true)
237
243
  return true;
244
+ if (isRecord(def) && Array.isArray(def.checks)) {
245
+ for (const check of def.checks) {
246
+ if (isInvisibleCheck(check))
247
+ return true;
248
+ }
249
+ }
238
250
  if (schema instanceof z3.ZodOptional || schema instanceof z3.ZodNullable || schema instanceof z3.ZodDefault) {
239
- return hasChecks(schema.unwrap());
251
+ return hasInvisibleConstraint(schema.unwrap());
240
252
  }
241
253
  if (schema instanceof z3.ZodPipe)
242
- return hasChecks(schema.def.in) || hasChecks(schema.def.out);
243
- if (schema instanceof z3.ZodObject)
244
- return Object.values(schema.shape).some(hasChecks);
254
+ return true;
255
+ if (schema instanceof z3.ZodObject) {
256
+ return Object.values(schema.shape).some(hasInvisibleConstraint);
257
+ }
245
258
  if (schema instanceof z3.ZodArray)
246
- return hasChecks(schema.element);
259
+ return hasInvisibleConstraint(schema.element);
247
260
  if (schema instanceof z3.ZodUnion)
248
- return schema.def.options.some(hasChecks);
261
+ return schema.def.options.some(hasInvisibleConstraint);
249
262
  if (schema instanceof z3.ZodRecord)
250
- return hasChecks(schema.valueType);
263
+ return hasInvisibleConstraint(schema.valueType);
251
264
  if (schema instanceof z3.ZodIntersection) {
252
- return hasChecks(schema.def.left) || hasChecks(schema.def.right);
265
+ return hasInvisibleConstraint(schema.def.left) || hasInvisibleConstraint(schema.def.right);
253
266
  }
254
267
  return false;
255
268
  }
269
+ var INVISIBLE_CHECK_KINDS = new Set(["custom", "overwrite"]);
270
+ function acceptsMoreThanItsType(schema) {
271
+ if (!(schema instanceof z3.ZodType))
272
+ return false;
273
+ if (schema instanceof z3.ZodCatch)
274
+ return true;
275
+ if (isRecord(schema.def) && schema.def.coerce === true)
276
+ return true;
277
+ if (schema instanceof z3.ZodOptional || schema instanceof z3.ZodNullable || schema instanceof z3.ZodDefault) {
278
+ return acceptsMoreThanItsType(schema.unwrap());
279
+ }
280
+ if (schema instanceof z3.ZodPipe)
281
+ return acceptsMoreThanItsType(schema.def.in);
282
+ return false;
283
+ }
284
+ function isInvisibleCheck(check) {
285
+ if (!isRecord(check))
286
+ return false;
287
+ const inner = check._zod;
288
+ const def = isRecord(inner) ? inner.def : undefined;
289
+ const kind = isRecord(def) ? def.check : undefined;
290
+ return typeof kind === "string" && INVISIBLE_CHECK_KINDS.has(kind);
291
+ }
292
+ function projectToBaseType(schema) {
293
+ if (!(schema instanceof z3.ZodType))
294
+ return z3.unknown();
295
+ if (schema instanceof z3.ZodNullable) {
296
+ return z3.nullable(projectToBaseType(schema.unwrap()));
297
+ }
298
+ if (schema instanceof z3.ZodOptional || schema instanceof z3.ZodDefault) {
299
+ return projectToBaseType(schema.unwrap());
300
+ }
301
+ if (schema instanceof z3.ZodPipe)
302
+ return projectToBaseType(schema.def.in);
303
+ if (schema instanceof z3.ZodCatch)
304
+ return z3.unknown();
305
+ const coerces = isRecord(schema.def) && schema.def.coerce === true;
306
+ if (schema instanceof z3.ZodNumber)
307
+ return coerces ? z3.coerce.number() : z3.number();
308
+ if (schema instanceof z3.ZodString)
309
+ return coerces ? z3.coerce.string() : z3.string();
310
+ if (schema instanceof z3.ZodBoolean && coerces)
311
+ return z3.coerce.boolean();
312
+ if (schema instanceof z3.ZodEnum || schema instanceof z3.ZodLiteral) {
313
+ return stringLiteralOrEnumValues(schema) === null ? z3.unknown() : z3.string();
314
+ }
315
+ if (schema instanceof z3.ZodBoolean)
316
+ return z3.boolean();
317
+ if (schema instanceof z3.ZodArray)
318
+ return z3.array(z3.unknown());
319
+ if (schema instanceof z3.ZodObject)
320
+ return z3.looseObject({});
321
+ return z3.unknown();
322
+ }
256
323
  function normalizedJson(schema) {
257
324
  if (!(schema instanceof z3.ZodType))
258
325
  return "{}";
@@ -272,7 +339,17 @@ function mergeCollidingFields(schemas) {
272
339
  if (values.length <= 1) {
273
340
  if (only === undefined)
274
341
  return z3.unknown();
275
- return schemas.length > 1 && hasChecks(only) ? z3.unknown() : only;
342
+ if (schemas.length <= 1)
343
+ return only;
344
+ const hazards2 = schemas.map(acceptsMoreThanItsType);
345
+ if (hazards2.some(Boolean) && !hazards2.every(Boolean))
346
+ return z3.unknown();
347
+ if (schemas.some(hasInvisibleConstraint)) {
348
+ if (normalizedJson(only) === "{}")
349
+ return only;
350
+ return projectToBaseType(only);
351
+ }
352
+ return only;
276
353
  }
277
354
  const merged = [];
278
355
  let allEnum = true;
@@ -286,9 +363,19 @@ function mergeCollidingFields(schemas) {
286
363
  }
287
364
  if (allEnum) {
288
365
  const uniq = [...new Set(merged)];
289
- const [first, ...rest] = uniq;
290
- if (first !== undefined)
291
- return z3.enum([first, ...rest]);
366
+ const [first2, ...rest] = uniq;
367
+ if (first2 !== undefined)
368
+ return z3.enum([first2, ...rest]);
369
+ }
370
+ const hazards = schemas.map(acceptsMoreThanItsType);
371
+ if (hazards.some(Boolean) && !hazards.every(Boolean))
372
+ return z3.unknown();
373
+ const projected = values.map(projectToBaseType);
374
+ const first = projected[0];
375
+ if (first !== undefined) {
376
+ const shape = normalizedJson(first);
377
+ if (shape !== "{}" && projected.every((p) => normalizedJson(p) === shape))
378
+ return first;
292
379
  }
293
380
  return z3.unknown();
294
381
  }
@@ -7,7 +7,7 @@
7
7
  * function — nothing else.
8
8
  */
9
9
  export { type AuditConfig, type AuditHook, createAuditHook } from './audit';
10
- export { getRequestContext, getTraceId, getUserId, type RequestContext, runWithRequestContext, setRequestDimensions, setRequestEndpoint, setRequestError, setRequestUser, wrapInRequestContext, } from './context';
10
+ export { getRequestContext, getTraceId, getUserId, type RequestContext, runWithRequestContext, setRequestDimensions, setRequestEndpoint, setRequestError, setRequestUser, type WrapRequestContextOptions, wrapInRequestContext, } from './context';
11
11
  export type { RequestEvent } from './event';
12
12
  export { type JsonValue, measureSize, redact, type SanitizeOptions, type SizeMeasure, sanitizePayload, truncatePreview, } from './sanitize';
13
13
  export { childSpan, createTraceContext, formatTraceparent, parseTraceparent, resolveTraceContext, type TraceContext, } from './trace';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,cAAc,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EACL,KAAK,SAAS,EACd,WAAW,EACX,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,KAAK,cAAc,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,KAAK,yBAAyB,EAC9B,oBAAoB,GACrB,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EACL,KAAK,SAAS,EACd,WAAW,EACX,MAAM,EACN,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
@@ -1,4 +1,4 @@
1
- type EventHandler<T = unknown> = (data: T) => void | Promise<void>;
1
+ export type EventHandler<T = unknown> = (data: T) => void | Promise<void>;
2
2
  /** Default event map — untyped string-keyed events (ad-hoc buses). */
3
3
  export type DefaultEventMap = Record<string, unknown>;
4
4
  /**
@@ -29,5 +29,4 @@ export interface EventBusOptions {
29
29
  onListenerError?: (error: unknown, event: string) => void;
30
30
  }
31
31
  export declare function createEventBus<M extends Record<string, unknown> = DefaultEventMap>(options?: EventBusOptions): EventBus<M>;
32
- export {};
33
32
  //# sourceMappingURL=event-bus.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/server/event-bus.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnE,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe;IAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAClF,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IACpF,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,KAAK,IAAI,IAAI,CAAC;CACf;AAYD,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAChF,OAAO,GAAE,eAAoB,GAC5B,QAAQ,CAAC,CAAC,CAAC,CA0Db"}
1
+ {"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/server/event-bus.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1E,sEAAsE;AACtE,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe;IAC3E,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7D,EAAE,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IAClF,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC;IACpF,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC7E,KAAK,IAAI,IAAI,CAAC;CACf;AAYD,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3D;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAChF,OAAO,GAAE,eAAoB,GAC5B,QAAQ,CAAC,CAAC,CAAC,CA0Db"}
@@ -4,15 +4,15 @@ export { isWithinDir } from '../internal/within-dir';
4
4
  export { cacheHeaders, createCache } from './cache';
5
5
  export { createHandler, createServer } from './create';
6
6
  export { createErrorHook, type ErrorHookConfig, type ResolvedError, } from './error-hook';
7
- export { createEventBus, type EventBus } from './event-bus';
7
+ export { createEventBus, type DefaultEventMap, type EventBus, type EventBusOptions, type EventHandler, } from './event-bus';
8
8
  export { type ByteRange, parseByteRange, type ServeFileOptions, serveFile, weakETag, } from './file';
9
9
  export { createImplement, implement } from './implement';
10
10
  export type { LogFormat } from './logger';
11
- export { type AuthHook, type AuthHookConfig, type AuthRule, type BearerResolverConfig, createAuthHook, createBearerResolver, extractToken, type JwtPayload, type SignJwtOptions, signJwt, verifyJwt, } from './middleware/auth';
11
+ export { type AuthHook, type AuthHookConfig, type AuthRule, type BearerResolverConfig, createAuthHook, createBearerResolver, extractToken, type JwtPayload, type SignJwtOptions, signJwt, type VerifyJwtOptions, verifyJwt, } from './middleware/auth';
12
12
  export { type CookieDef, type CookieOptions, defineCookie, parseCookies, serializeCookie, } from './middleware/cookies';
13
13
  export { type CorsConfig, corsHeaders, corsPreflightResponse, DEFAULT_CORS_ALLOW_HEADERS, DEFAULT_CORS_EXPOSE_HEADERS, } from './middleware/cors';
14
14
  export { deriveCodeChallenge, type PkceMethod, verifyPkce } from './middleware/pkce';
15
- export { parseMultipart } from './multipart';
15
+ export { type MultipartResult, parseMultipart } from './multipart';
16
16
  export { generateOpenApiDocument, type OpenApiConfig, type OpenApiDocument, type OpenApiInfo, type OpenApiServer, openApiRoute, } from './openapi';
17
17
  export { createRateLimiter, type RateLimitConfig } from './rate-limit';
18
18
  export { errorResponse, parseBody, respondJson } from './raw';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../src/tools/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,CAAC,CAAC,qBAAqB,GAC7B,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAiD5B;AAsKD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAqDpE"}
1
+ {"version":3,"file":"flatten.d.ts","sourceRoot":"","sources":["../../src/tools/flatten.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,CAAC,CAAC,qBAAqB,GAC7B,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAiD5B;AA6TD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,OAAO,CAqDpE"}
@@ -48,6 +48,15 @@ export interface McpMountConfig {
48
48
  export declare function validateMcpSchemas(services: ServiceDef[], onIncompatibleSchema?: IncompatibleSchemaPolicy, logger?: StitchLogger, options?: {
49
49
  extend?: ToolExtend;
50
50
  flattenUnionInput?: boolean;
51
+ /**
52
+ * Also fail a tool whose advertised schema has a property with no type
53
+ * information — nothing for a model to obey. Off by default because a
54
+ * contract may legitimately declare `z.unknown()`; `allowUntyped` lists the
55
+ * dotted paths that are deliberate, and anything else is a finding. → ADR 0044.
56
+ */
57
+ requireTypedProperties?: boolean;
58
+ /** Dotted paths (`tool.property`) that are deliberately unconstrained. */
59
+ allowUntyped?: readonly string[];
51
60
  }): void;
52
61
  export declare function mountMcp(mcpServer: McpServer, services: ServiceDef | ServiceDef[], config?: McpMountConfig): void;
53
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/tools/mcp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/tools/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** One property the model would be shown with no idea what it is. */
2
+ export interface UntypedProperty {
3
+ /** Dotted path from the tool's argument root, e.g. `operations.partIndex`. */
4
+ path: string;
5
+ /** Its `description`, when it has one — usually the only clue present. */
6
+ description?: string;
7
+ }
8
+ /**
9
+ * Every property in a JSON Schema that carries no type information, deep.
10
+ *
11
+ * Walks `properties`, `items`, `additionalProperties`, `$defs` / `definitions`
12
+ * and the `allOf` / `anyOf` / `oneOf` branches — an intersection root emits
13
+ * `allOf` with no root `properties` at all, so reading the top level alone would
14
+ * inspect nothing and pass.
15
+ */
16
+ export declare function findUntypedProperties(schema: unknown, prefix?: string): UntypedProperty[];
17
+ //# sourceMappingURL=untyped-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"untyped-properties.d.ts","sourceRoot":"","sources":["../../src/tools/untyped-properties.ts"],"names":[],"mappings":"AAkBA,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,SAAK,GAAG,eAAe,EAAE,CA+DrF"}
package/dist/tools.d.ts CHANGED
@@ -12,7 +12,7 @@ export { buildMcpServer, type IncompatibleSchemaPolicy, type McpMountConfig, typ
12
12
  export { EXT_APPS_BUNDLE_PLACEHOLDER, inlineMcpAppBundle, type McpAppCsp, type McpAppResourceMeta, type McpResourceDef, RESOURCE_MIME_TYPE, } from './tools/mcp-app';
13
13
  export { createMcpHandler, type McpHandlerConfig } from './tools/mcp-handler';
14
14
  export { createStdioMcpServer, type StdioMcpServerConfig } from './tools/mcp-stdio';
15
- export { collectTools, type MountableTool, type ToolExtend } from './tools/mount';
15
+ export { type CollectToolsConfig, collectTools, type MountableTool, type ToolExtend, } from './tools/mount';
16
16
  export { type DownloadToolConfig, mountDownload } from './tools/mount-download';
17
17
  export { mountUpload, type UploadToolConfig } from './tools/mount-upload';
18
18
  export { mountWait, type WaitToolConfig } from './tools/mount-wait';
@@ -22,5 +22,6 @@ export { type ImplementRemoteOptions, implementRemote } from './tools/remote';
22
22
  export { createToolLogger, type ToolCallRecord, type ToolLoggerConfig, } from './tools/tool-logger';
23
23
  export { createToolkit, type Toolkit } from './tools/toolkit';
24
24
  export { summarizeTransports, type TransportCounts, type TransportSummary, } from './tools/transports';
25
- export { type McpMediaContent, mountViewFile, resolveMedia } from './tools/view-file';
25
+ export { findUntypedProperties, type UntypedProperty } from './tools/untyped-properties';
26
+ export { type McpAnnotations, type McpMediaContent, mountViewFile, resolveMedia, type ViewFileOptions, } from './tools/view-file';
26
27
  //# sourceMappingURL=tools.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAClF,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EACL,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EACV,WAAW,EACX,eAAe,EACf,aAAa,EACb,aAAa,EACb,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,cAAc,EACd,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,QAAQ,EACR,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,2BAA2B,EAC3B,kBAAkB,EAClB,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EACL,KAAK,kBAAkB,EACvB,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,kBAAkB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,uBAAuB,EAC5B,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EACL,mBAAmB,EACnB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,aAAa,EACb,YAAY,EACZ,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC"}
package/dist/tools.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  readCapped,
22
22
  toolResultFromError,
23
23
  writeDownload
24
- } from "./index-jr8vf7g8.js";
24
+ } from "./index-bfabej0h.js";
25
25
  import {
26
26
  toJsonSchema
27
27
  } from "./index-0ed3bx43.js";
@@ -139,6 +139,77 @@ function inlineMcpAppBundle(html) {
139
139
  return html.replace(EXT_APPS_BUNDLE_PLACEHOLDER, () => bundle);
140
140
  }
141
141
 
142
+ // src/tools/untyped-properties.ts
143
+ var TYPE_KEYWORDS = ["type", "enum", "const", "anyOf", "oneOf", "allOf", "$ref", "not"];
144
+ function saysWhatItIs(schema) {
145
+ return TYPE_KEYWORDS.some((keyword) => schema[keyword] !== undefined);
146
+ }
147
+ function findUntypedProperties(schema, prefix = "") {
148
+ if (!isRecord(schema))
149
+ return [];
150
+ const found = [];
151
+ const properties = schema.properties;
152
+ if (isRecord(properties)) {
153
+ for (const [key, value] of Object.entries(properties)) {
154
+ const path = prefix ? `${prefix}.${key}` : key;
155
+ if (isRecord(value)) {
156
+ if (!saysWhatItIs(value)) {
157
+ const description = value.description;
158
+ found.push({
159
+ path,
160
+ ...typeof description === "string" && { description }
161
+ });
162
+ }
163
+ found.push(...findUntypedProperties(value, path));
164
+ }
165
+ }
166
+ }
167
+ for (const key of ["items", "additionalProperties"]) {
168
+ const child = schema[key];
169
+ if (isRecord(child))
170
+ found.push(...findUntypedProperties(child, prefix));
171
+ if (Array.isArray(child)) {
172
+ for (const entry of child) {
173
+ if (isRecord(entry))
174
+ found.push(...findUntypedProperties(entry, prefix));
175
+ }
176
+ }
177
+ }
178
+ for (const key of ["prefixItems"]) {
179
+ const child = schema[key];
180
+ if (Array.isArray(child)) {
181
+ for (const entry of child) {
182
+ if (isRecord(entry))
183
+ found.push(...findUntypedProperties(entry, prefix));
184
+ }
185
+ }
186
+ }
187
+ const patterned = schema.patternProperties;
188
+ if (isRecord(patterned)) {
189
+ for (const value of Object.values(patterned)) {
190
+ if (isRecord(value))
191
+ found.push(...findUntypedProperties(value, prefix));
192
+ }
193
+ }
194
+ for (const key of ["$defs", "definitions"]) {
195
+ const container = schema[key];
196
+ if (!isRecord(container))
197
+ continue;
198
+ for (const definition of Object.values(container)) {
199
+ if (isRecord(definition))
200
+ found.push(...findUntypedProperties(definition, prefix));
201
+ }
202
+ }
203
+ for (const key of ["allOf", "anyOf", "oneOf"]) {
204
+ const branches = schema[key];
205
+ if (Array.isArray(branches)) {
206
+ for (const branch of branches)
207
+ found.push(...findUntypedProperties(branch, prefix));
208
+ }
209
+ }
210
+ return found;
211
+ }
212
+
142
213
  // src/tools/mcp.ts
143
214
  function textBlock(text) {
144
215
  return [{ type: "text", text }];
@@ -187,7 +258,7 @@ function reportIncompatible(message, policy, logger, failures) {
187
258
  }
188
259
  function throwIfFailures(failures) {
189
260
  if (failures.length > 0) {
190
- throw new Error(`[stitchkit] ${failures.length} MCP tool(s) have an incompatible schema:
261
+ throw new Error(`[stitchkit] ${failures.length} problem(s) with MCP tool schemas:
191
262
  - ${failures.join(`
192
263
  - `)}`);
193
264
  }
@@ -217,9 +288,19 @@ function prepareMcpTool(mountable, policy, logger, failures, seen) {
217
288
  function validateMcpSchemas(services, onIncompatibleSchema = "throw", logger, options) {
218
289
  const seen = new Set;
219
290
  const failures = [];
291
+ const allowed = new Set(options?.allowUntyped ?? []);
220
292
  for (const service of services) {
221
293
  for (const mountable of collectTools(service, "MCP", options)) {
222
- prepareMcpTool(mountable, onIncompatibleSchema, logger, failures, seen);
294
+ const prepared = prepareMcpTool(mountable, onIncompatibleSchema, logger, failures, seen);
295
+ if (!prepared || !options?.requireTypedProperties)
296
+ continue;
297
+ for (const untyped of findUntypedProperties(toJsonSchema(mountable.schema, "input"))) {
298
+ const path = `${mountable.name}.${untyped.path}`;
299
+ if (allowed.has(path))
300
+ continue;
301
+ const clue = untyped.description ? ` (only a description: "${untyped.description}")` : "";
302
+ reportIncompatible(`MCP tool "${mountable.name}" — property "${untyped.path}" carries no type, enum or $ref${clue}. ` + "A model is given no way to know what to send. Widen the contract, or list it in `allowUntyped` if it is deliberately free-form.", onIncompatibleSchema === "skip" ? "warn" : onIncompatibleSchema, logger, failures);
303
+ }
223
304
  }
224
305
  }
225
306
  throwIfFailures(failures);
@@ -1410,6 +1491,7 @@ export {
1410
1491
  implementRemote,
1411
1492
  flattenUnionsDeep,
1412
1493
  flattenDiscriminatedUnion,
1494
+ findUntypedProperties,
1413
1495
  createToolkit,
1414
1496
  createToolLogger,
1415
1497
  createStdioMcpServer,
package/llms-full.txt CHANGED
@@ -1524,6 +1524,30 @@ cannot become a tool. `onIncompatibleSchema` decides what happens:
1524
1524
  `validateMcpSchemas(services)` runs the same check on its own — useful in a
1525
1525
  startup assertion or a test.
1526
1526
 
1527
+ #### Is every property actually usable by a model?
1528
+
1529
+ A tool schema is the only instruction a model gets about the shape of its
1530
+ arguments. A property that carries a `description` and no `type` / `enum` /
1531
+ `anyOf` / `$ref` tells it nothing — and nothing fails: the schema converts, the
1532
+ mount succeeds, the tool is advertised, and the model then guesses, retrying the
1533
+ same wrong guess because the error does not say what the right one would be.
1534
+
1535
+ ```ts
1536
+ validateMcpSchemas(services, 'throw', logger, {
1537
+ flattenUnionInput: true, // mirror the live mount
1538
+ requireTypedProperties: true,
1539
+ allowUntyped: ['docs_create.payload'], // deliberately free-form
1540
+ })
1541
+ ```
1542
+
1543
+ Off by default, because a contract may legitimately declare `z.unknown()`.
1544
+ `allowUntyped` takes dotted `tool.property` paths — an entry there is a decision,
1545
+ anything else is a finding. Pass the **same** `extend` / `flattenUnionInput` the
1546
+ mount uses, or the check vets a different document than the one advertised.
1547
+
1548
+ `findUntypedProperties(jsonSchema)` is the same walk, exported on its own if you
1549
+ want to assert on a schema you built elsewhere.
1550
+
1527
1551
  ### Discriminated unions for weaker models — `flattenUnionInput`
1528
1552
 
1529
1553
  A discriminated union in a tool's input becomes a JSON Schema `oneOf` / `anyOf`.
@@ -1533,6 +1557,15 @@ the field or mangle its strings. Set `flattenUnionInput: true` (on
1533
1557
  union as a **single flat object** instead — the discriminator becomes an enum and
1534
1558
  each variant's fields become optional with a `Required if <disc> = …` hint.
1535
1559
 
1560
+ **A field several variants declare keeps its type.** Flattening puts every
1561
+ variant's fields side by side, so a key two variants share has to be advertised
1562
+ as one thing. Where they agree, that is what you get; where they disagree — a
1563
+ `.refine()` only one of them carries, two different bounds on the same number, an
1564
+ enum against a free string — the *constraint* is dropped and the **type** is not.
1565
+ A field that is a number in every variant is advertised as a number, not as a
1566
+ bare description. Only genuinely different kinds (a string in one variant, a
1567
+ number in another) fall back to unconstrained. → ADR 0044
1568
+
1536
1569
  It is **deep**: unions are flattened at every depth — top level, object fields,
1537
1570
  array items, and through `optional` / `nullable` / `default` / intersection
1538
1571
  wrappers — so no `oneOf` survives anywhere (e.g. a `content.parts[]` that is an
@@ -3746,6 +3779,7 @@ Also re-exports the error helpers from `stitchkit/contract`.
3746
3779
  | `ResolvedError` | _type_ | the normalised error handed to `createErrorHook`'s `render` |
3747
3780
  | `createBearerResolver` | function | a bearer-token identity resolver |
3748
3781
  | `signJwt` | function | sign an HS256 JWT |
3782
+ | `VerifyJwtOptions` | _type_ | options for `verifyJwt` |
3749
3783
  | `verifyJwt` | function | verify an HS256 JWT |
3750
3784
  | `extractToken` | function | read a bearer token from header or cookie |
3751
3785
  | `deriveCodeChallenge` | function | PKCE — derive the `code_challenge` from a verifier |
@@ -3793,10 +3827,14 @@ Also re-exports the error helpers from `stitchkit/contract`.
3793
3827
  |--------|------|---------|
3794
3828
  | `streamSSE` | function | an async generator → SSE `Response` — [guide](../guide/server.md#sse-streaming) |
3795
3829
  | `parseSSE` | function | parse an SSE `Response` (also on the root entrypoint) |
3830
+ | `MultipartResult` | _type_ | what `parseMultipart` returns |
3796
3831
  | `parseMultipart` | function | parse a `multipart/form-data` request — [guide](../guide/server.md#multipart) |
3797
3832
  | `createRateLimiter` | function | token-bucket rate limiting — [guide](../guide/server.md#rate-limiting) |
3798
3833
  | `createCache` | function | an in-memory TTL cache |
3799
3834
  | `cacheHeaders` | function | build a `Cache-Control` header |
3835
+ | `EventBusOptions` | _type_ | options for `createEventBus` |
3836
+ | `EventHandler` | _type_ | one event-bus subscriber |
3837
+ | `DefaultEventMap` | _type_ | the default event map — `Record<string, unknown>` |
3800
3838
  | `createEventBus` | function | typed in-process pub/sub — [guide](../guide/server.md#event-bus) |
3801
3839
  | `generateTraceId` | function | a fresh trace id |
3802
3840
  | `resolveTraceId` | function | the default per-request trace-id resolver |
@@ -3840,6 +3878,7 @@ audit event. See the [Observability guide](../guide/observability.md).
3840
3878
 
3841
3879
  | Export | Kind | Summary |
3842
3880
  |--------|------|---------|
3881
+ | `WrapRequestContextOptions` | _type_ | options for `wrapInRequestContext` |
3843
3882
  | `wrapInRequestContext` | function | run a fetch handler inside a request context — [guide](../guide/observability.md#request-context) |
3844
3883
  | `getRequestContext` | function | the active request context |
3845
3884
  | `getTraceId` | function | the active trace id — pass as `traceId` to `createServer` |
@@ -3912,6 +3951,11 @@ Server-only. Turns contracts into MCP and AI-agent tools. Needs the
3912
3951
  | `ErrorHintFn` | _type_ | `(toolName, errorCode) => string \| null` — a per-tool recovery hint, shared by every mount |
3913
3952
  | `ToolResult` | _type_ | the result of one tool call |
3914
3953
  | `ToolCallContext` | _type_ | the context every tool hook receives — `{ source }` plus whatever the mount's `context` added |
3954
+ | `ViewFileOptions` | _type_ | options for `mountViewFile` |
3955
+ | `McpAnnotations` | _type_ | MCP annotations on a media result |
3956
+ | `CollectToolsConfig` | _type_ | options for `collectTools` |
3957
+ | `findUntypedProperties` | function | every property in a JSON Schema with no `type`/`enum`/`$ref` — what a model is shown and cannot obey ([guide](../guide/mcp-and-agents.md)) |
3958
+ | `UntypedProperty` | _type_ | one such property — `{ path, description? }` |
3915
3959
  | `ToolNameEntry` | _type_ | one `listToolNames` row — `{ name, service, method, transports }` |
3916
3960
  | `IncompatibleSchemaPolicy` | _type_ | `'throw' \| 'skip' \| 'warn'` |
3917
3961
  | `McpMediaContent` | _type_ | a multimodal MCP content item |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -86,7 +86,7 @@
86
86
  "build:server": "bun build src/server/index.ts src/node.ts src/tools.ts src/cli.ts src/observability/index.ts --outdir dist --target node --packages external --splitting --root src",
87
87
  "build:js": "bun run build:browser && bun run build:server",
88
88
  "build:types": "bun x tsc -p tsconfig.build.json --emitDeclarationOnly",
89
- "build": "rm -rf dist && bun run build:js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-env-live.mjs",
89
+ "build": "rm -rf dist && bun run build:js && bun run build:types && bun scripts/check-browser-clean.mjs && bun scripts/check-env-live.mjs && bun scripts/check-public-types.mjs",
90
90
  "dev": "bun run build:js -- --watch",
91
91
  "prepublishOnly": "cp ../../README.md ./README.md && bun ../../scripts/gen-llms.ts && bun run build",
92
92
  "test": "bun test",