feat(core): support pinned Code Mode tools (#39550)
This commit is contained in:
parent
b985d2eb8e
commit
5cb633a48e
7 changed files with 77 additions and 16 deletions
|
|
@ -16,6 +16,7 @@ describe("CodeMode", () => {
|
|||
description: "Echo text",
|
||||
input: Schema.Struct({ text: Schema.String }),
|
||||
output: Schema.String,
|
||||
options: { pinned: true },
|
||||
execute: ({ text }) => Effect.succeed({ output: text }),
|
||||
}),
|
||||
)
|
||||
|
|
@ -27,6 +28,7 @@ describe("CodeMode", () => {
|
|||
path: "echo",
|
||||
description: "Echo text",
|
||||
signature: "tools.echo(input: {\n text: string,\n}): Promise<string>",
|
||||
pinned: true,
|
||||
},
|
||||
])
|
||||
}).pipe(
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ import { describe, expect, test } from "bun:test"
|
|||
import { CodeModeCatalog } from "@opencode-ai/core/codemode/catalog"
|
||||
import { CodeModeInstructions } from "@opencode-ai/core/codemode/instructions"
|
||||
|
||||
const entry = (path: string, description: string, signature?: string): CodeModeCatalog.Entry => ({
|
||||
const entry = (path: string, description: string, signature?: string, pinned = false): CodeModeCatalog.Entry => ({
|
||||
path,
|
||||
description,
|
||||
signature: signature ?? `tools.${path}(input: {\n q: string,\n}): Promise<string>`,
|
||||
pinned,
|
||||
})
|
||||
|
||||
const lookup = entry(
|
||||
|
|
@ -46,6 +47,30 @@ describe("CodeModeCatalog.summarize", () => {
|
|||
expect(catalog.namespaces.every((namespace) => namespace.entries.length === 0)).toBe(true)
|
||||
})
|
||||
|
||||
test("always retains pinned tools beyond the inline budget", () => {
|
||||
const pinned = [
|
||||
entry("alpha.first", "First", undefined, true),
|
||||
entry("beta.second", "Second", undefined, true),
|
||||
]
|
||||
const catalog = CodeModeCatalog.summarize([...pinned, entry("alpha.unpinned", "Unpinned")], 0)
|
||||
|
||||
expect(catalog.shown).toBe(2)
|
||||
expect(catalog.namespaces.flatMap((namespace) => namespace.entries.map((item) => item.path))).toEqual([
|
||||
"alpha.first",
|
||||
"beta.second",
|
||||
])
|
||||
})
|
||||
|
||||
test("spends the budget remaining after pinned tools on unpinned tools", () => {
|
||||
const pinned = entry("alpha.pinned", "Pinned", undefined, true)
|
||||
const unpinned = entry("beta.unpinned", "Unpinned")
|
||||
const pinCost = Math.round(` - ${pinned.signature} // Pinned`.length / 4)
|
||||
const unpinnedCost = Math.round(` - ${unpinned.signature} // Unpinned`.length / 4)
|
||||
|
||||
expect(CodeModeCatalog.summarize([pinned, unpinned], pinCost + unpinnedCost).shown).toBe(2)
|
||||
expect(CodeModeCatalog.summarize([pinned, unpinned], pinCost + unpinnedCost - 1).shown).toBe(1)
|
||||
})
|
||||
|
||||
test("retains only the rendered portion of inline descriptions", () => {
|
||||
const catalog = CodeModeCatalog.summarize([entry("alpha.one", `Summary\n${"detail".repeat(10_000)}`)])
|
||||
expect(catalog.namespaces[0]?.entries[0]?.line).toEndWith("// Summary")
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ const transform = (
|
|||
) =>
|
||||
service.transform((draft) =>
|
||||
Object.entries(tools).forEach(([name, tool]) =>
|
||||
draft.add({ ...tool, name, options: { ...tool.options, ...options } }),
|
||||
draft.add({ ...tool, name, options: options ?? tool.options }),
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ const permission = Layer.succeed(
|
|||
const transformTools = (registry: Tool.Interface, tools: Readonly<Record<string, Info>>, options?: Tool.Options) =>
|
||||
registry.transform((draft) =>
|
||||
Object.entries(tools).forEach(([name, tool]) =>
|
||||
draft.add({ ...tool, name, options: { ...tool.options, ...options } }),
|
||||
draft.add({ ...tool, name, options: options ?? tool.options }),
|
||||
),
|
||||
)
|
||||
const echo = Layer.effectDiscard(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue