diff --git a/src/contracts/toolInputReferences.test.ts b/src/contracts/toolInputReferences.test.ts index 24985ed210..657b77f3cd 100644 --- a/src/contracts/toolInputReferences.test.ts +++ b/src/contracts/toolInputReferences.test.ts @@ -10,9 +10,41 @@ import { presentInputJsonSchema, } from "./inputSchemaPresentation.js"; import { toolContract } from "./toolContracts.js"; -import { toolInputSchemaWithMetadata } from "./toolSchemaMetadata.js"; +import { + toolInputSchemaWithMetadata, + transformAdvertisedInputJsonSchema, +} from "./toolSchemaMetadata.js"; import { JAVASCRIPT_APPLICATION_EVIDENCE_EXAMPLE } from "./javascript/javascriptRuntimeReconciliationExample.js"; +it.each(["draft-2020-12", "draft-07"] as const)( + "honors projection options independently of cached wire transformations in %s", + (target) => { + const range = z.strictObject({ offset: z.number(), length: z.number() }); + const canonical = toolInputSchemaWithMetadata({ + ...toolContract("open_binary"), + inputSchema: z.strictObject({ before: range, after: range }), + }); + const transform = (schema: Record) => ({ + ...schema, + title: "Transformed range inputs", + }); + const options = { target, libraryOptions: { reused: "inline" as const } }; + for (const inlineFirst of [false, true]) { + const wrapped = transformAdvertisedInputJsonSchema(canonical, transform); + const project = wrapped["~standard"].jsonSchema.input; + if (inlineFirst) project(options); + const shared = project({ target }); + expect(JSON.stringify(shared)).toContain('"$ref":'); + const inline = project(options); + expect(inline).toEqual( + transform(canonical["~standard"].jsonSchema.input(options)), + ); + expect(JSON.stringify(inline)).not.toContain('"$ref":'); + expect(project({ target })).toBe(shared); + } + }, +); + it.each(["draft-2020-12", "draft-07"] as const)( "preserves the complete inline Evidence contract before deferred authentication in %s", (target) => { diff --git a/src/contracts/toolSchemaMetadata.ts b/src/contracts/toolSchemaMetadata.ts index 093f4845ca..a0821612db 100644 --- a/src/contracts/toolSchemaMetadata.ts +++ b/src/contracts/toolSchemaMetadata.ts @@ -146,7 +146,10 @@ export const transformAdvertisedInputJsonSchema = ( const byTarget = new Map>(); const transformedInput = (options: unknown): unknown => { const target = Reflect.get(options as object, "target"); - if (typeof target === "string") { + const cacheable = + typeof target === "string" && + Reflect.get(options as object, "libraryOptions") === undefined; + if (cacheable) { const cached = byTarget.get(target); if (cached !== undefined) return cached; } @@ -154,7 +157,7 @@ export const transformAdvertisedInputJsonSchema = ( const transformed = isSchemaRecord(projected) ? transform(projected) : projected; - if (typeof target === "string" && isSchemaRecord(transformed)) + if (cacheable && isSchemaRecord(transformed)) byTarget.set(target, transformed); return transformed; };