diff --git a/packages/core/test/session-runner-tool-registry.test.ts b/packages/core/test/session-runner-tool-registry.test.ts index 00ac5ca5ce..8e486f02d3 100644 --- a/packages/core/test/session-runner-tool-registry.test.ts +++ b/packages/core/test/session-runner-tool-registry.test.ts @@ -99,17 +99,14 @@ describe("ToolRegistry", () => { return Effect.gen(function* () { const service = yield* ToolRegistry.Service const text = "x".repeat(ToolOutputStore.MAX_STRUCTURED_BYTES) - yield* service.register( - { - structured_only: Tool.make({ - description: "Return structured output", - input: Schema.Struct({}), - output: Schema.Struct({ text: Schema.String }), - execute: () => Effect.succeed({ text }), - }), - }, - { codemode: false }, - ) + yield* service.register({ + structured_only: Tool.make({ + description: "Return structured output", + input: Schema.Struct({}), + output: Schema.Struct({ text: Schema.String }), + execute: () => Effect.succeed({ text }), + }), + }, { codemode: false }) const settled = yield* settleTool(service, { sessionID, ...identity, @@ -162,15 +159,12 @@ describe("ToolRegistry", () => { it.effect("filters disabled tools with edit aliases and ordered wildcard precedence", () => Effect.gen(function* () { const service = yield* ToolRegistry.Service - yield* service.register( - { - question: make(), - bash: make(), - edit: make("edit"), - write: make("edit"), - }, - { codemode: false }, - ) + yield* service.register({ + question: make(), + bash: make(), + edit: make("edit"), + write: make("edit"), + }, { codemode: false }) const names = (permissions: PermissionV2.Ruleset) => toolDefinitions(service, permissions).pipe(Effect.map((definitions) => definitions.map((tool) => tool.name))) @@ -243,17 +237,14 @@ describe("ToolRegistry", () => { it.effect("returns model errors without swallowing interruption or defects", () => Effect.gen(function* () { const service = yield* ToolRegistry.Service - yield* service.register( - { - failed: Tool.make({ - description: "Failed", - input: Schema.Struct({}), - output: Schema.Struct({ ok: Schema.Boolean }), - execute: () => Effect.fail(new Tool.Failure({ message: "Denied" })), - }), - }, - { codemode: false }, - ) + yield* service.register({ + failed: Tool.make({ + description: "Failed", + input: Schema.Struct({}), + output: Schema.Struct({ ok: Schema.Boolean }), + execute: () => Effect.fail(new Tool.Failure({ message: "Denied" })), + }), + }, { codemode: false }) expect( yield* executeTool(service, { sessionID, @@ -269,17 +260,14 @@ describe("ToolRegistry", () => { }), ).toEqual({ type: "error", value: "Unknown tool: missing" }) - yield* service.register( - { - defect: Tool.make({ - description: "Defect", - input: Schema.Struct({}), - output: Schema.Struct({}), - execute: () => Effect.die("unexpected executor defect"), - }), - }, - { codemode: false }, - ) + yield* service.register({ + defect: Tool.make({ + description: "Defect", + input: Schema.Struct({}), + output: Schema.Struct({}), + execute: () => Effect.die("unexpected executor defect"), + }), + }, { codemode: false }) expect( yield* service.materialize().pipe( Effect.flatMap((materialized) => @@ -322,23 +310,22 @@ describe("ToolRegistry", () => { Effect.gen(function* () { const service = yield* ToolRegistry.Service const contexts: Tool.Context[] = [] - yield* service.register( - { - context: Tool.make({ - description: "Context", - input: Schema.Struct({}), - output: Schema.Struct({ ok: Schema.Boolean }), - execute: (_, context) => Effect.sync(() => contexts.push(context)).pipe(Effect.as({ ok: true })), - }), - }, - { codemode: false }, - ) + yield* service.register({ + context: Tool.make({ + description: "Context", + input: Schema.Struct({}), + output: Schema.Struct({ ok: Schema.Boolean }), + execute: (_, context) => Effect.sync(() => contexts.push(context)).pipe(Effect.as({ ok: true })), + }), + }, { codemode: false }) yield* executeTool(service, { sessionID, ...identity, call: { type: "tool-call", id: "call-context", name: "context", input: {} }, }) - expect(contexts).toEqual([{ sessionID, ...identity, callID: "call-context", progress: expect.any(Function) }]) + expect(contexts).toEqual([ + { sessionID, ...identity, callID: "call-context", progress: expect.any(Function) }, + ]) }), ) @@ -365,23 +352,20 @@ describe("ToolRegistry", () => { it.effect("normalizes image tool output at settlement and drops unresizable images", () => Effect.gen(function* () { const service = yield* ToolRegistry.Service - yield* service.register( - { - snapshot: Tool.make({ - description: "Return images", - input: Schema.Struct({ text: Schema.String }), - output: Schema.Struct({ text: Schema.String }), - execute: ({ text }) => Effect.succeed({ text }), - toModelOutput: ({ output }) => [ - { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "frame.png" }, - { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "too-large.png" }, - { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "corrupt.png" }, - { type: "text", text: output.text }, - ], - }), - }, - { codemode: false }, - ) + yield* service.register({ + snapshot: Tool.make({ + description: "Return images", + input: Schema.Struct({ text: Schema.String }), + output: Schema.Struct({ text: Schema.String }), + execute: ({ text }) => Effect.succeed({ text }), + toModelOutput: ({ output }) => [ + { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "frame.png" }, + { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "too-large.png" }, + { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "corrupt.png" }, + { type: "text", text: output.text }, + ], + }), + }, { codemode: false }) const settlement = yield* settleTool(service, call("snapshot")) expect(settlement.output?.content).toEqual([ @@ -396,26 +380,23 @@ describe("ToolRegistry", () => { it.effect("normalizes image progress content before it is published", () => Effect.gen(function* () { const service = yield* ToolRegistry.Service - yield* service.register( - { - progressive: Tool.make({ - description: "Emit image progress", - input: Schema.Struct({ text: Schema.String }), - output: Schema.Struct({ text: Schema.String }), - execute: ({ text }, context) => - context - .progress({ - structured: { stage: "capture" }, - content: [ - { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "frame.png" }, - { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "too-large.png" }, - ], - }) - .pipe(Effect.as({ text })), - }), - }, - { codemode: false }, - ) + yield* service.register({ + progressive: Tool.make({ + description: "Emit image progress", + input: Schema.Struct({ text: Schema.String }), + output: Schema.Struct({ text: Schema.String }), + execute: ({ text }, context) => + context + .progress({ + structured: { stage: "capture" }, + content: [ + { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "frame.png" }, + { type: "file", data: "aW1hZ2U=", mime: "image/png", name: "too-large.png" }, + ], + }) + .pipe(Effect.as({ text })), + }), + }, { codemode: false }) const updates: ToolRegistry.Progress[] = [] yield* settleTool(service, { @@ -447,18 +428,15 @@ describe("ToolRegistry", () => { encode: SchemaGetter.transform((value) => value === "yes"), }), ) - yield* service.register( - { - transformed: Tool.make({ - description: "Transform values", - input: Schema.Struct({ value: Transformed }), - output: Schema.Struct({ value: Transformed }), - execute: ({ value }) => Effect.sync(() => executed.push(value)).pipe(Effect.as({ value })), - toModelOutput: ({ output }) => [{ type: "text", text: String(output.value) }], - }), - }, - { codemode: false }, - ) + yield* service.register({ + transformed: Tool.make({ + description: "Transform values", + input: Schema.Struct({ value: Transformed }), + output: Schema.Struct({ value: Transformed }), + execute: ({ value }) => Effect.sync(() => executed.push(value)).pipe(Effect.as({ value })), + toModelOutput: ({ output }) => [{ type: "text", text: String(output.value) }], + }), + }, { codemode: false }) expect( yield* executeTool(service, { @@ -477,28 +455,25 @@ describe("ToolRegistry", () => { ).toMatchObject({ type: "error", value: expect.stringContaining("Invalid tool input") }) expect(executed).toEqual(["yes"]) - yield* service.register( - { - invalid_output: Tool.make({ - description: "Return invalid output", - input: Schema.Struct({}), - output: Schema.Struct({ - value: Schema.Boolean.pipe( - Schema.decodeTo(Schema.String, { - decode: SchemaGetter.transform((value) => String(value)), - encode: SchemaGetter.transformOrFail((value) => - value === "valid" - ? Effect.succeed(true) - : Effect.fail(new SchemaIssue.InvalidValue(Option.some(value), { message: "invalid output" })), - ), - }), - ), - }), - execute: () => Effect.succeed({ value: "invalid" }), + yield* service.register({ + invalid_output: Tool.make({ + description: "Return invalid output", + input: Schema.Struct({}), + output: Schema.Struct({ + value: Schema.Boolean.pipe( + Schema.decodeTo(Schema.String, { + decode: SchemaGetter.transform((value) => String(value)), + encode: SchemaGetter.transformOrFail((value) => + value === "valid" + ? Effect.succeed(true) + : Effect.fail(new SchemaIssue.InvalidValue(Option.some(value), { message: "invalid output" })), + ), + }), + ), }), - }, - { codemode: false }, - ) + execute: () => Effect.succeed({ value: "invalid" }), + }), + }, { codemode: false }) expect( yield* executeTool(service, { sessionID, diff --git a/packages/core/test/tool-search.test.ts b/packages/core/test/tool-search.test.ts index 45a3e42296..b9ee0bc07d 100644 --- a/packages/core/test/tool-search.test.ts +++ b/packages/core/test/tool-search.test.ts @@ -86,8 +86,8 @@ describe("search tools", () => { const glob = yield* settleTool(registry, call("glob", { pattern: "*" })) const grep = yield* settleTool(registry, call("grep", { pattern: "needle" })) - expect(glob.output?.structured).toHaveLength(FileSystem.DEFAULT_SEARCH_LIMIT) - expect(grep.output?.structured).toHaveLength(FileSystem.DEFAULT_SEARCH_LIMIT) + expect(glob.output?.structured).toEqual({ count: FileSystem.DEFAULT_SEARCH_LIMIT }) + expect(grep.output?.structured).toEqual({ matches: FileSystem.DEFAULT_SEARCH_LIMIT }) }), ) }),