fix(plugin): make tool values structural (#37202)

This commit is contained in:
Kit Langton 2026-07-15 22:25:01 -04:00 committed by GitHub
commit 0a5530d0be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 296 additions and 267 deletions

View file

@ -4,7 +4,7 @@ This folder owns Core's one local tool representation, process and Location regi
## Representations
- `tool.ts` defines the opaque canonical `Tool.make({ description, input, output, execute, toModelOutput })` value. Shipped built-ins and plugin tools use the same type.
- `tool.ts` defines the structural canonical `Tool.make({ description, input, output, execute, toModelOutput })` declaration. Shipped built-ins and plugin tools use the same type.
- `tools.ts` exposes the registration-only `Tools.Service` view used by Location producers.
- `registry.ts` stores only canonical Location registrations, derives definitions, invokes tools, and applies generic output bounding.
@ -12,7 +12,7 @@ Do not add a second executable entry type, registry-owned executor, authorizatio
## Construction
Tool schemas and projection use `input` and `output` terminology. A tool value is opaque: its codecs, executor, definition derivation, and catalog permission declaration are private runtime details.
Tool schemas and projection use `input` and `output` terminology. A tool value carries its schemas, executor, projection, and optional catalog permission directly so separately loaded plugin package instances can exchange it structurally.
Location-scoped built-in layers acquire `PermissionV2.Service` and every other required Location service while the layer is constructed. The executor captures those services. Permission sources are always constructed from the canonical invocation context:

View file

@ -107,17 +107,6 @@ describe("ToolRegistry", () => {
}),
)
it.effect("reuses model definitions across requests", () =>
Effect.gen(function* () {
const service = yield* ToolRegistry.Service
yield* service.register({ echo: make() }, { codemode: false })
const first = yield* toolDefinitions(service)
const second = yield* toolDefinitions(service)
expect(second[0]).toBe(first[0])
}),
)
it.effect("removes a scoped registration", () =>
Effect.gen(function* () {
const service = yield* ToolRegistry.Service