feat(codemode): make search a global built-in and rewrite README (#36450)
This commit is contained in:
parent
1ccaca826e
commit
6eeeb4bfcf
11 changed files with 274 additions and 416 deletions
|
|
@ -541,11 +541,11 @@ describe("CodeMode public contract", () => {
|
|||
" - tools.orders.lookup(input: {\n id: string,\n}): Promise<{\n id: string,\n status: string,\n}> // Look up an order by ID",
|
||||
)
|
||||
// A fully inlined catalog does not advertise search in the instructions...
|
||||
expect(runtime.instructions()).not.toMatch(/\$codemode/)
|
||||
expect(runtime.instructions()).not.toContain("search(")
|
||||
|
||||
// ...but the search tool stays registered, so a speculative call still works with the
|
||||
// ...but the search built-in stays available, so a speculative call still works with the
|
||||
// same signature as the inline catalog.
|
||||
const result = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({ query: "order" })`))
|
||||
const result = await Effect.runPromise(runtime.execute(`return search({ query: "order" })`))
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) {
|
||||
expect(result.value).toStrictEqual({
|
||||
|
|
@ -583,9 +583,7 @@ describe("CodeMode public contract", () => {
|
|||
'tools.context7["resolve-library-id"](input: {\n libraryName: string,\n}): Promise<string>',
|
||||
)
|
||||
|
||||
const search = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "resolve library id" })`),
|
||||
)
|
||||
const search = await Effect.runPromise(runtime.execute(`return search({ query: "resolve library id" })`))
|
||||
expect(search.ok).toBe(true)
|
||||
if (search.ok) {
|
||||
expect(search.value).toStrictEqual({
|
||||
|
|
@ -608,7 +606,7 @@ describe("CodeMode public contract", () => {
|
|||
if (call.ok) expect(call.value).toBe("/resolved/TypeScript")
|
||||
|
||||
const exact = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: 'tools.context7["resolve-library-id"]' })`),
|
||||
runtime.execute(`return search({ query: 'tools.context7["resolve-library-id"]' })`),
|
||||
)
|
||||
expect(exact.ok).toBe(true)
|
||||
if (exact.ok) expect(exact.value).toMatchObject({ remaining: 0, next: null })
|
||||
|
|
@ -632,7 +630,7 @@ describe("CodeMode public contract", () => {
|
|||
expect(instructions).toContain("Do not infer or normalize tool names")
|
||||
expect(instructions).toContain("bracket notation and quotes are part of the path")
|
||||
expect(instructions).toContain("surrounding agent tools are not available")
|
||||
expect(instructions).toContain("Only Code Mode tools listed here and internal runtime tools")
|
||||
expect(instructions).toContain("Only Code Mode tools listed here are available")
|
||||
// Placeholders use generic namespace/tool/field names only - no fabricated real tools
|
||||
// and no real catalog tools cherry-picked into example lines.
|
||||
expect(instructions).toContain("`const result = await tools.<namespace>.<tool>(input)`")
|
||||
|
|
@ -651,15 +649,11 @@ describe("CodeMode public contract", () => {
|
|||
// PARTIAL: the workflow starts with search (with query-style guidance that is clearly
|
||||
// a query string, never a tool name) and the browse-namespace rule appears.
|
||||
expect(partial).toContain(
|
||||
'1. If needed, discover tools: `return await tools.$codemode.search({ query: "<intent + key nouns>" })`.',
|
||||
'1. If needed, discover tools with the built-in search function: `return search({ query: "<intent + key nouns>" })`.',
|
||||
)
|
||||
expect(partial).toContain("In the next execution, copy a returned path exactly")
|
||||
expect(partial).toContain(
|
||||
"Only Code Mode tools listed here or returned by `tools.$codemode.search` and internal runtime tools",
|
||||
)
|
||||
expect(partial).toContain(
|
||||
'- Browse one namespace: `await tools.$codemode.search({ query: "", namespace: "<name>" })`.',
|
||||
)
|
||||
expect(partial).toContain("Only Code Mode tools listed here or returned by the built-in `search` function")
|
||||
expect(partial).toContain('- Browse one namespace: `search({ query: "", namespace: "<name>" })`.')
|
||||
expect(partial).toContain("repeat the same search with `offset: next.offset`")
|
||||
expect(partial).toContain(" limit?: number,\n offset?: number,")
|
||||
expect(partial).not.toContain("total_count")
|
||||
|
|
@ -696,7 +690,7 @@ describe("CodeMode public contract", () => {
|
|||
expect(instructions).toContain("## Available tools")
|
||||
expect(instructions).not.toContain("## Workflow")
|
||||
expect(instructions).not.toContain("## Rules")
|
||||
expect(instructions).not.toMatch(/\$codemode/)
|
||||
expect(instructions).not.toContain("search(")
|
||||
})
|
||||
|
||||
test("uses one ranked search returning complete definitions for large catalogs", async () => {
|
||||
|
|
@ -716,17 +710,15 @@ describe("CodeMode public contract", () => {
|
|||
tools: { thread: { uploadFile: upload, generateImage: generate }, orders: { lookup } },
|
||||
discovery: { catalogBudget: 0 },
|
||||
})
|
||||
expect(runtime.instructions()).toContain(
|
||||
"Available tools (PARTIAL - 0 of 3 shown; find the rest with tools.$codemode.search)",
|
||||
)
|
||||
expect(runtime.instructions()).toContain("Available tools (PARTIAL - 0 of 3 shown; find the rest with search(...))")
|
||||
expect(runtime.instructions()).toContain("- thread (2 tools, none shown)")
|
||||
expect(runtime.instructions()).toContain("- orders (1 tool, none shown)")
|
||||
expect(runtime.instructions()).toMatch(/\$codemode\.search/)
|
||||
expect(runtime.instructions()).toContain("Search returns complete callable signatures:\n- search(input: {")
|
||||
expect(runtime.instructions()).not.toMatch(/tools\.thread\.uploadFile\(input/)
|
||||
|
||||
const result = await Effect.runPromise(
|
||||
runtime.execute(`
|
||||
return await tools.$codemode.search({
|
||||
return search({
|
||||
query: "send message attachment upload file to current Discord thread",
|
||||
limit: 2
|
||||
})
|
||||
|
|
@ -750,14 +742,14 @@ describe("CodeMode public contract", () => {
|
|||
remaining: 0,
|
||||
next: null,
|
||||
})
|
||||
expect(result.toolCalls).toStrictEqual([{ name: "$codemode.search" }])
|
||||
expect(result.toolCalls).toStrictEqual([{ name: "search" }])
|
||||
|
||||
const variants = await Effect.runPromise(
|
||||
runtime.execute(`
|
||||
return await Promise.all([
|
||||
tools.$codemode.search({ query: "file" }),
|
||||
tools.$codemode.search({ query: "image" })
|
||||
])
|
||||
return [
|
||||
search({ query: "file" }),
|
||||
search({ query: "image" })
|
||||
]
|
||||
`),
|
||||
)
|
||||
expect(variants.ok).toBe(true)
|
||||
|
|
@ -770,13 +762,41 @@ describe("CodeMode public contract", () => {
|
|||
)
|
||||
}
|
||||
|
||||
const removed = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.describe({ path: "thread.uploadFile" })`),
|
||||
)
|
||||
// The retired $codemode namespace is gone from the tools tree entirely.
|
||||
const removed = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({ query: "file" })`))
|
||||
expect(removed.ok).toBe(false)
|
||||
if (!removed.ok) expect(removed.error.kind).toBe("UnknownTool")
|
||||
})
|
||||
|
||||
test("search is a counted tool call: it burns maxToolCalls and fires the hooks", async () => {
|
||||
const started: Array<string> = []
|
||||
const ended: Array<string> = []
|
||||
const limited = CodeMode.make({
|
||||
tools,
|
||||
limits: { maxToolCalls: 1 },
|
||||
onToolCallStart: (call) => Effect.sync(() => void started.push(call.name)),
|
||||
onToolCallEnd: (call) => Effect.sync(() => void ended.push(`${call.name}:${call.outcome}`)),
|
||||
})
|
||||
const result = await Effect.runPromise(limited.execute(`search({}); return search({})`))
|
||||
expect(result.ok).toBe(false)
|
||||
if (!result.ok) expect(result.error.kind).toBe("ToolCallLimitExceeded")
|
||||
expect(started).toEqual(["search"])
|
||||
expect(ended).toEqual(["search:success"])
|
||||
})
|
||||
|
||||
test("search is an opaque, shadowable global like other built-ins", async () => {
|
||||
const runtime = CodeMode.make({ tools })
|
||||
expect(await Effect.runPromise(runtime.execute(`return typeof search`))).toMatchObject({ value: "function" })
|
||||
// A program-level declaration shadows the global, as JS module scope does.
|
||||
const shadowed = await Effect.runPromise(runtime.execute(`const search = () => "local"; return search()`))
|
||||
expect(shadowed.ok).toBe(true)
|
||||
if (shadowed.ok) expect(shadowed.value).toBe("local")
|
||||
// The reference itself cannot cross the data boundary.
|
||||
const escaped = await Effect.runPromise(runtime.execute(`return { search }`))
|
||||
expect(escaped.ok).toBe(false)
|
||||
if (!escaped.ok) expect(escaped.error.kind).toBe("InvalidDataValue")
|
||||
})
|
||||
|
||||
test("search defaults to 10 results and resolves exact tool paths", async () => {
|
||||
const tool = (index: number) =>
|
||||
Tool.make({
|
||||
|
|
@ -791,7 +811,7 @@ describe("CodeMode public contract", () => {
|
|||
},
|
||||
})
|
||||
|
||||
const browse = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({})`))
|
||||
const browse = await Effect.runPromise(runtime.execute(`return search({})`))
|
||||
expect(browse.ok).toBe(true)
|
||||
if (browse.ok) {
|
||||
const value = browse.value as {
|
||||
|
|
@ -805,9 +825,7 @@ describe("CodeMode public contract", () => {
|
|||
}
|
||||
|
||||
for (const query of ["many.tool13", "tools.many.tool13"]) {
|
||||
const exact = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: ${JSON.stringify(query)} })`),
|
||||
)
|
||||
const exact = await Effect.runPromise(runtime.execute(`return search({ query: ${JSON.stringify(query)} })`))
|
||||
expect(exact.ok).toBe(true)
|
||||
if (exact.ok) {
|
||||
expect(exact.value).toStrictEqual({
|
||||
|
|
@ -841,9 +859,7 @@ describe("CodeMode public contract", () => {
|
|||
})
|
||||
|
||||
// Empty query + namespace browses just that namespace, alphabetical by path.
|
||||
const browse = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "", namespace: "github" })`),
|
||||
)
|
||||
const browse = await Effect.runPromise(runtime.execute(`return search({ query: "", namespace: "github" })`))
|
||||
expect(browse.ok).toBe(true)
|
||||
if (browse.ok) {
|
||||
const value = browse.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -855,9 +871,7 @@ describe("CodeMode public contract", () => {
|
|||
}
|
||||
|
||||
// A query + namespace ranks within that namespace only.
|
||||
const scoped = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "issues", namespace: "linear" })`),
|
||||
)
|
||||
const scoped = await Effect.runPromise(runtime.execute(`return search({ query: "issues", namespace: "linear" })`))
|
||||
expect(scoped.ok).toBe(true)
|
||||
if (scoped.ok) {
|
||||
const value = scoped.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -865,9 +879,7 @@ describe("CodeMode public contract", () => {
|
|||
expect(value.items[0]?.path).toBe("tools.linear.list_issues")
|
||||
}
|
||||
|
||||
const invalid = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "issues", namespace: 7 })`),
|
||||
)
|
||||
const invalid = await Effect.runPromise(runtime.execute(`return search({ query: "issues", namespace: 7 })`))
|
||||
expect(invalid.ok).toBe(false)
|
||||
if (!invalid.ok) expect(invalid.error.kind).toBe("InvalidToolInput")
|
||||
})
|
||||
|
|
@ -892,9 +904,7 @@ describe("CodeMode public contract", () => {
|
|||
|
||||
// "attachment" appears in neither path nor description - only in the input schema's
|
||||
// property names, which the searchable text includes.
|
||||
const byParameter = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "attachment" })`),
|
||||
)
|
||||
const byParameter = await Effect.runPromise(runtime.execute(`return search({ query: "attachment" })`))
|
||||
expect(byParameter.ok).toBe(true)
|
||||
if (byParameter.ok) {
|
||||
const value = byParameter.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -903,9 +913,7 @@ describe("CodeMode public contract", () => {
|
|||
}
|
||||
|
||||
// Substring matching: a partial word ("docum") still hits the description.
|
||||
const bySubstring = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "docum" })`),
|
||||
)
|
||||
const bySubstring = await Effect.runPromise(runtime.execute(`return search({ query: "docum" })`))
|
||||
expect(bySubstring.ok).toBe(true)
|
||||
if (bySubstring.ok) {
|
||||
const value = bySubstring.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -932,9 +940,7 @@ describe("CodeMode public contract", () => {
|
|||
})
|
||||
|
||||
// "issues" still finds the singular-only tool (term OR singular(term) per field)...
|
||||
const plural = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "issues", namespace: "tracker" })`),
|
||||
)
|
||||
const plural = await Effect.runPromise(runtime.execute(`return search({ query: "issues", namespace: "tracker" })`))
|
||||
expect(plural.ok).toBe(true)
|
||||
if (plural.ok) {
|
||||
const value = plural.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -943,7 +949,7 @@ describe("CodeMode public contract", () => {
|
|||
}
|
||||
|
||||
// ...while a true "issues" path match still outranks the singular-only description match.
|
||||
const ranked = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({ query: "issues" })`))
|
||||
const ranked = await Effect.runPromise(runtime.execute(`return search({ query: "issues" })`))
|
||||
expect(ranked.ok).toBe(true)
|
||||
if (ranked.ok) {
|
||||
const value = ranked.value as { items: Array<{ path: string }>; remaining: number }
|
||||
|
|
@ -970,7 +976,7 @@ describe("CodeMode public contract", () => {
|
|||
alpha: { beta: simple("Middle"), aardvark: simple("First") },
|
||||
},
|
||||
})
|
||||
const browse = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({})`))
|
||||
const browse = await Effect.runPromise(runtime.execute(`return search({})`))
|
||||
expect(browse.ok).toBe(true)
|
||||
if (browse.ok) {
|
||||
const value = browse.value as { items: Array<{ path: string }>; remaining: number; next: unknown }
|
||||
|
|
@ -983,9 +989,7 @@ describe("CodeMode public contract", () => {
|
|||
expect(value.next).toBeNull()
|
||||
}
|
||||
|
||||
const middle = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ limit: 1, offset: 1 })`),
|
||||
)
|
||||
const middle = await Effect.runPromise(runtime.execute(`return search({ limit: 1, offset: 1 })`))
|
||||
expect(middle.ok).toBe(true)
|
||||
if (middle.ok) {
|
||||
expect(middle.value).toMatchObject({
|
||||
|
|
@ -995,9 +999,7 @@ describe("CodeMode public contract", () => {
|
|||
})
|
||||
}
|
||||
|
||||
const exhausted = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ limit: 1, offset: 3 })`),
|
||||
)
|
||||
const exhausted = await Effect.runPromise(runtime.execute(`return search({ limit: 1, offset: 3 })`))
|
||||
expect(exhausted.ok).toBe(true)
|
||||
if (exhausted.ok) expect(exhausted.value).toStrictEqual({ items: [], remaining: 0, next: null })
|
||||
})
|
||||
|
|
@ -1028,16 +1030,14 @@ describe("CodeMode public contract", () => {
|
|||
})
|
||||
|
||||
const instructions = runtime.instructions()
|
||||
expect(instructions).toContain(
|
||||
"Available tools (PARTIAL - 2 of 3 shown; find the rest with tools.$codemode.search)",
|
||||
)
|
||||
expect(instructions).toContain("Available tools (PARTIAL - 2 of 3 shown; find the rest with search(...))")
|
||||
expect(instructions).toContain("- alpha (2 tools, 1 shown)")
|
||||
expect(instructions).toContain(" - tools.alpha.cheap(input: {\n q: string,\n}): Promise<string> // Cheap")
|
||||
expect(instructions).not.toContain("tools.alpha.expensive(")
|
||||
// Fully shown namespaces read cleanly (no "shown" annotation).
|
||||
expect(instructions).toContain("- beta (1 tool)")
|
||||
expect(instructions).toContain(" - tools.beta.cheap(input: {\n q: string,\n}): Promise<string> // Cheap")
|
||||
expect(instructions).toMatch(/\$codemode\.search/)
|
||||
expect(instructions).toContain("Search returns complete callable signatures:\n- search(input: {")
|
||||
})
|
||||
|
||||
test("charges inline JSDoc against the catalog token budget", () => {
|
||||
|
|
@ -1058,9 +1058,7 @@ describe("CodeMode public contract", () => {
|
|||
})
|
||||
|
||||
expect(runtime.catalog()[0]?.signature).toContain("/** A detailed identifier description.")
|
||||
expect(runtime.instructions()).toContain(
|
||||
"Available tools (PARTIAL - 0 of 1 shown; find the rest with tools.$codemode.search)",
|
||||
)
|
||||
expect(runtime.instructions()).toContain("Available tools (PARTIAL - 0 of 1 shown; find the rest with search(...))")
|
||||
expect(runtime.instructions()).not.toContain("tools.records.lookup(input:")
|
||||
})
|
||||
|
||||
|
|
@ -1138,7 +1136,7 @@ describe("CodeMode public contract", () => {
|
|||
CodeMode.make({
|
||||
tools,
|
||||
discovery: { catalogBudget: 0 },
|
||||
}).execute(`return await tools.$codemode.search({ query: "order", limit: 0.5 })`),
|
||||
}).execute(`return search({ query: "order", limit: 0.5 })`),
|
||||
)
|
||||
expect(result.ok).toBe(false)
|
||||
if (result.ok) return
|
||||
|
|
@ -1146,9 +1144,7 @@ describe("CodeMode public contract", () => {
|
|||
|
||||
for (const offset of [-1, 0.5, Number.MAX_SAFE_INTEGER + 1, "1"]) {
|
||||
const invalidOffset = await Effect.runPromise(
|
||||
CodeMode.make({ tools }).execute(
|
||||
`return await tools.$codemode.search({ query: "order", offset: ${JSON.stringify(offset)} })`,
|
||||
),
|
||||
CodeMode.make({ tools }).execute(`return search({ query: "order", offset: ${JSON.stringify(offset)} })`),
|
||||
)
|
||||
expect(invalidOffset.ok).toBe(false)
|
||||
if (!invalidOffset.ok) expect(invalidOffset.error.kind).toBe("InvalidToolInput")
|
||||
|
|
@ -1200,7 +1196,10 @@ describe("CodeMode public contract", () => {
|
|||
expect(elapsedMs).toBeLessThan(3_000)
|
||||
})
|
||||
|
||||
test("reserves the discovery namespace", () => {
|
||||
expect(() => CodeMode.make({ tools: { $codemode: { lookup } } })).toThrow(/reserved for CodeMode discovery tools/)
|
||||
test("a host $codemode namespace is an ordinary namespace now that search is a built-in", async () => {
|
||||
const runtime = CodeMode.make({ tools: { $codemode: { lookup } } })
|
||||
const result = await Effect.runPromise(runtime.execute(`return await tools.$codemode.lookup({ id: "order_1" })`))
|
||||
expect(result.ok).toBe(true)
|
||||
if (result.ok) expect(result.value).toStrictEqual({ id: "order_1", status: "open" })
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ describe("Object.keys over tool references", () => {
|
|||
const namespaces = Object.keys(tools)
|
||||
return { namespaces, count: namespaces.length }
|
||||
`),
|
||||
).toEqual({ namespaces: ["github", "memory", "playwright", "$codemode"], count: 4 })
|
||||
).toEqual({ namespaces: ["github", "memory", "playwright"], count: 3 })
|
||||
})
|
||||
|
||||
test("enumerates tool names at a nested namespace", async () => {
|
||||
|
|
@ -52,8 +52,10 @@ describe("Object.keys over tool references", () => {
|
|||
expect(await value(`return Object.keys(tools.github.list_issues)`)).toEqual([])
|
||||
})
|
||||
|
||||
test("the internal discovery namespace enumerates its callable surface", async () => {
|
||||
expect(await value(`return Object.keys(tools.$codemode)`)).toEqual(["search"])
|
||||
test("search is a global built-in function, not a tools namespace", async () => {
|
||||
expect(await value(`return typeof search`)).toBe("function")
|
||||
const failure = await error(`return Object.keys(tools.$codemode)`)
|
||||
expect(failure.kind).toBe("UnknownTool")
|
||||
})
|
||||
|
||||
test("an unknown namespace is an UnknownTool error pointing at the discovery idioms", async () => {
|
||||
|
|
@ -68,7 +70,7 @@ describe("Object.keys over tool references", () => {
|
|||
const failure = await error(`return Object.${method}(tools)`)
|
||||
expect(failure.kind).toBe("InvalidDataValue")
|
||||
expect(failure.message).toContain(
|
||||
`Object.${method}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or tools.$codemode.search({ query }) for signatures.`,
|
||||
`Object.${method}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or search({ query }) for signatures.`,
|
||||
)
|
||||
}
|
||||
const nested = await error(`return Object.entries(tools.github)`)
|
||||
|
|
@ -146,7 +148,7 @@ describe("for...in", () => {
|
|||
}
|
||||
return names
|
||||
`),
|
||||
).toEqual(["github.list_issues", "github.get_issue", "memory.search", "playwright.navigate", "$codemode.search"])
|
||||
).toEqual(["github.list_issues", "github.get_issue", "memory.search", "playwright.navigate"])
|
||||
})
|
||||
|
||||
test("unsupported values fail with a hint at for...of and Object.keys", async () => {
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ describe("OpenAPI.fromSpec", () => {
|
|||
runtime
|
||||
.execute(
|
||||
`
|
||||
return await tools.$codemode.search({ query: "global health", namespace: "opencode", limit: 1 })
|
||||
return search({ query: "global health", namespace: "opencode", limit: 1 })
|
||||
`,
|
||||
)
|
||||
.pipe(Effect.provide(layer)),
|
||||
|
|
|
|||
|
|
@ -342,9 +342,7 @@ describe("JSDoc signatures in catalogs and search results", () => {
|
|||
const runtime = CodeMode.make({ tools: { github: { list_issues: listIssues }, orders: { lookup: lookupOrder } } })
|
||||
|
||||
const search = async (query: string) => {
|
||||
const result = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: ${JSON.stringify(query)} })`),
|
||||
)
|
||||
const result = await Effect.runPromise(runtime.execute(`return search({ query: ${JSON.stringify(query)} })`))
|
||||
expect(result.ok).toBe(true)
|
||||
if (!result.ok) throw new Error("search failed")
|
||||
return result.value as { items: Array<{ path: string; signature: string }>; remaining: number }
|
||||
|
|
@ -436,9 +434,7 @@ describe("non-identifier tool paths", () => {
|
|||
})
|
||||
|
||||
test("search results return callable bracket-notation paths and signatures", async () => {
|
||||
const result = await Effect.runPromise(
|
||||
runtime.execute(`return await tools.$codemode.search({ query: "resolve library" })`),
|
||||
)
|
||||
const result = await Effect.runPromise(runtime.execute(`return search({ query: "resolve library" })`))
|
||||
expect(result.ok).toBe(true)
|
||||
if (!result.ok) throw new Error("search failed")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue