test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
import { describe, expect, test } from "bun:test"
|
2026-04-18 15:58:38 +00:00
|
|
|
import { Result, Schema } from "effect"
|
|
|
|
|
import { toJsonSchema } from "../../src/util/effect-zod"
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
|
|
|
|
|
// Each tool exports its parameters schema at module scope so this test can
|
|
|
|
|
// import them without running the tool's Effect-based init. The JSON Schema
|
|
|
|
|
// snapshot captures what the LLM sees; the parse assertions pin down the
|
2026-04-18 15:58:38 +00:00
|
|
|
// accepts/rejects contract. `toJsonSchema` is the same helper `session/
|
|
|
|
|
// prompt.ts` uses to emit tool schemas to the LLM, so the snapshots stay
|
|
|
|
|
// byte-identical regardless of whether a tool has migrated from zod to Schema.
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
|
|
|
|
|
import { Parameters as ApplyPatch } from "../../src/tool/apply_patch"
|
|
|
|
|
import { Parameters as Bash } from "../../src/tool/bash"
|
|
|
|
|
import { Parameters as CodeSearch } from "../../src/tool/codesearch"
|
|
|
|
|
import { Parameters as Edit } from "../../src/tool/edit"
|
|
|
|
|
import { Parameters as Glob } from "../../src/tool/glob"
|
|
|
|
|
import { Parameters as Grep } from "../../src/tool/grep"
|
|
|
|
|
import { Parameters as Invalid } from "../../src/tool/invalid"
|
|
|
|
|
import { Parameters as Lsp } from "../../src/tool/lsp"
|
|
|
|
|
import { Parameters as MultiEdit } from "../../src/tool/multiedit"
|
|
|
|
|
import { Parameters as Plan } from "../../src/tool/plan"
|
|
|
|
|
import { Parameters as Question } from "../../src/tool/question"
|
|
|
|
|
import { Parameters as Read } from "../../src/tool/read"
|
|
|
|
|
import { Parameters as Skill } from "../../src/tool/skill"
|
|
|
|
|
import { Parameters as Task } from "../../src/tool/task"
|
|
|
|
|
import { Parameters as Todo } from "../../src/tool/todo"
|
|
|
|
|
import { Parameters as WebFetch } from "../../src/tool/webfetch"
|
|
|
|
|
import { Parameters as WebSearch } from "../../src/tool/websearch"
|
|
|
|
|
import { Parameters as Write } from "../../src/tool/write"
|
|
|
|
|
|
2026-04-18 15:58:38 +00:00
|
|
|
const parse = <S extends Schema.Decoder<unknown>>(schema: S, input: unknown): S["Type"] =>
|
|
|
|
|
Schema.decodeUnknownSync(schema)(input)
|
|
|
|
|
|
|
|
|
|
const accepts = (schema: Schema.Decoder<unknown>, input: unknown): boolean =>
|
|
|
|
|
Result.isSuccess(Schema.decodeUnknownResult(schema)(input))
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
|
|
|
|
|
describe("tool parameters", () => {
|
|
|
|
|
describe("JSON Schema (wire shape)", () => {
|
|
|
|
|
test("apply_patch", () => expect(toJsonSchema(ApplyPatch)).toMatchSnapshot())
|
|
|
|
|
test("bash", () => expect(toJsonSchema(Bash)).toMatchSnapshot())
|
|
|
|
|
test("codesearch", () => expect(toJsonSchema(CodeSearch)).toMatchSnapshot())
|
|
|
|
|
test("edit", () => expect(toJsonSchema(Edit)).toMatchSnapshot())
|
|
|
|
|
test("glob", () => expect(toJsonSchema(Glob)).toMatchSnapshot())
|
|
|
|
|
test("grep", () => expect(toJsonSchema(Grep)).toMatchSnapshot())
|
|
|
|
|
test("invalid", () => expect(toJsonSchema(Invalid)).toMatchSnapshot())
|
|
|
|
|
test("lsp", () => expect(toJsonSchema(Lsp)).toMatchSnapshot())
|
|
|
|
|
test("multiedit", () => expect(toJsonSchema(MultiEdit)).toMatchSnapshot())
|
|
|
|
|
test("plan", () => expect(toJsonSchema(Plan)).toMatchSnapshot())
|
|
|
|
|
test("question", () => expect(toJsonSchema(Question)).toMatchSnapshot())
|
|
|
|
|
test("read", () => expect(toJsonSchema(Read)).toMatchSnapshot())
|
|
|
|
|
test("skill", () => expect(toJsonSchema(Skill)).toMatchSnapshot())
|
|
|
|
|
test("task", () => expect(toJsonSchema(Task)).toMatchSnapshot())
|
|
|
|
|
test("todo", () => expect(toJsonSchema(Todo)).toMatchSnapshot())
|
|
|
|
|
test("webfetch", () => expect(toJsonSchema(WebFetch)).toMatchSnapshot())
|
|
|
|
|
test("websearch", () => expect(toJsonSchema(WebSearch)).toMatchSnapshot())
|
|
|
|
|
test("write", () => expect(toJsonSchema(Write)).toMatchSnapshot())
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("apply_patch", () => {
|
|
|
|
|
test("accepts patchText", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(ApplyPatch, { patchText: "*** Begin Patch\n*** End Patch" })).toEqual({
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
patchText: "*** Begin Patch\n*** End Patch",
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing patchText", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(ApplyPatch, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects non-string patchText", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(ApplyPatch, { patchText: 123 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("bash", () => {
|
|
|
|
|
test("accepts minimum: command + description", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Bash, { command: "ls", description: "list" })).toEqual({ command: "ls", description: "list" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts optional timeout + workdir", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Bash, { command: "ls", description: "list", timeout: 5000, workdir: "/tmp" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.timeout).toBe(5000)
|
|
|
|
|
expect(parsed.workdir).toBe("/tmp")
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing description (required by zod)", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Bash, { command: "ls" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects missing command", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Bash, { description: "list" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("codesearch", () => {
|
|
|
|
|
test("accepts query; tokensNum defaults to 5000", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(CodeSearch, { query: "hooks" })).toEqual({ query: "hooks", tokensNum: 5000 })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts override tokensNum", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(CodeSearch, { query: "hooks", tokensNum: 10000 }).tokensNum).toBe(10000)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects tokensNum under 1000", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(CodeSearch, { query: "x", tokensNum: 500 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects tokensNum over 50000", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(CodeSearch, { query: "x", tokensNum: 60000 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("edit", () => {
|
|
|
|
|
test("accepts all four fields", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Edit, { filePath: "/a", oldString: "x", newString: "y", replaceAll: true })).toEqual({
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
filePath: "/a",
|
|
|
|
|
oldString: "x",
|
|
|
|
|
newString: "y",
|
|
|
|
|
replaceAll: true,
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
test("replaceAll is optional", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Edit, { filePath: "/a", oldString: "x", newString: "y" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.replaceAll).toBeUndefined()
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing filePath", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Edit, { oldString: "x", newString: "y" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("glob", () => {
|
|
|
|
|
test("accepts pattern-only", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Glob, { pattern: "**/*.ts" })).toEqual({ pattern: "**/*.ts" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts optional path", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Glob, { pattern: "**/*.ts", path: "/tmp" }).path).toBe("/tmp")
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects missing pattern", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Glob, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("grep", () => {
|
|
|
|
|
test("accepts pattern-only", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Grep, { pattern: "TODO" })).toEqual({ pattern: "TODO" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts optional path + include", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Grep, { pattern: "TODO", path: "/tmp", include: "*.ts" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.path).toBe("/tmp")
|
|
|
|
|
expect(parsed.include).toBe("*.ts")
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing pattern", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Grep, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("invalid", () => {
|
|
|
|
|
test("accepts tool + error", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Invalid, { tool: "foo", error: "bar" })).toEqual({ tool: "foo", error: "bar" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects missing fields", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Invalid, { tool: "foo" })).toBe(false)
|
|
|
|
|
expect(accepts(Invalid, { error: "bar" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("lsp", () => {
|
|
|
|
|
test("accepts all fields", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Lsp, { operation: "hover", filePath: "/a.ts", line: 1, character: 1 })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.operation).toBe("hover")
|
|
|
|
|
})
|
|
|
|
|
test("rejects line < 1", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Lsp, { operation: "hover", filePath: "/a.ts", line: 0, character: 1 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects character < 1", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Lsp, { operation: "hover", filePath: "/a.ts", line: 1, character: 0 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects unknown operation", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Lsp, { operation: "bogus", filePath: "/a.ts", line: 1, character: 1 })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("multiedit", () => {
|
|
|
|
|
test("accepts empty edits array", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(MultiEdit, { filePath: "/a", edits: [] }).edits).toEqual([])
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts an edit entry", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(MultiEdit, {
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
filePath: "/a",
|
2026-04-18 16:54:29 +00:00
|
|
|
edits: [{ oldString: "x", newString: "y" }],
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
expect(parsed.edits.length).toBe(1)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("plan", () => {
|
|
|
|
|
test("accepts empty object", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Plan, {})).toEqual({})
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("question", () => {
|
|
|
|
|
test("accepts questions array", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Question, {
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
questions: [
|
|
|
|
|
{
|
|
|
|
|
question: "pick one",
|
|
|
|
|
header: "Header",
|
|
|
|
|
custom: false,
|
|
|
|
|
options: [{ label: "a", description: "desc" }],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
})
|
|
|
|
|
expect(parsed.questions.length).toBe(1)
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing questions", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Question, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("read", () => {
|
|
|
|
|
test("accepts filePath-only", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Read, { filePath: "/a" }).filePath).toBe("/a")
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("accepts optional offset + limit", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Read, { filePath: "/a", offset: 10, limit: 100 })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.offset).toBe(10)
|
|
|
|
|
expect(parsed.limit).toBe(100)
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("skill", () => {
|
|
|
|
|
test("accepts name", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Skill, { name: "foo" }).name).toBe("foo")
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects missing name", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Skill, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("task", () => {
|
|
|
|
|
test("accepts description + prompt + subagent_type", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Task, { description: "d", prompt: "p", subagent_type: "general" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
expect(parsed.subagent_type).toBe("general")
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing prompt", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Task, { description: "d", subagent_type: "general" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("todo", () => {
|
|
|
|
|
test("accepts todos array", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
const parsed = parse(Todo, {
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
todos: [{ id: "t1", content: "do x", status: "pending", priority: "medium" }],
|
|
|
|
|
})
|
|
|
|
|
expect(parsed.todos.length).toBe(1)
|
|
|
|
|
})
|
|
|
|
|
test("rejects missing todos", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Todo, {})).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("webfetch", () => {
|
|
|
|
|
test("accepts url-only", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(WebFetch, { url: "https://example.com" }).url).toBe("https://example.com")
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("websearch", () => {
|
|
|
|
|
test("accepts query", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(WebSearch, { query: "opencode" }).query).toBe("opencode")
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
describe("write", () => {
|
|
|
|
|
test("accepts content + filePath", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(parse(Write, { content: "hi", filePath: "/a" })).toEqual({ content: "hi", filePath: "/a" })
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
test("rejects missing filePath", () => {
|
2026-04-18 15:58:38 +00:00
|
|
|
expect(accepts(Write, { content: "hi" })).toBe(false)
|
test(tool): pin every tool's parameters schema before migration
Pre-migration safety net for the upcoming tool-by-tool zod\u2192Schema
conversion. Every tool's parameters schema now has:
1. A JSON Schema snapshot (`z.toJSONSchema` with `io: "input"`) \u2014 this
captures exactly what the LLM sees at tool registration time, so any
drift caused by a future migration fails the snapshot.
2. Parse-accept/parse-reject assertions per tool pinning the
user-visible behavioural contract (required fields, refinement
bounds, enum membership, default values).
To make the snapshots possible without standing up each tool's full
Effect runtime, every tool file now exports its parameters schema as
`Parameters` at module scope:
- 9 tools already had a module-level const \u2014 just added `export`, and
standardised the name to `Parameters` (uppercase) where it was
previously `parameters`.
- 9 tools had their schema inline inside `Tool.define` \u2014 hoisted to
module scope under the same `Parameters` name and wired back through.
Zero behaviour change: Tool.define still sees the same schema, runtime
validation path is identical, SDK (types.gen.ts + openapi.json) is
byte-identical, and the full 2054-test suite passes.
18 JSON Schema snapshots and 43 explicit parse/reject assertions for the
18 built-in tools (apply_patch, bash, codesearch, edit, glob, grep,
invalid, lsp, multiedit, plan, question, read, skill, task, todo,
webfetch, websearch, write).
2026-04-18 04:01:50 +00:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
})
|