fix(codemode): unify catalog signatures (#35452)

This commit is contained in:
Aiden Cline
2026-07-06 00:52:37 -05:00
committed by GitHub
parent e0ec9be238
commit d4f7039932
12 changed files with 430 additions and 361 deletions
+36 -36
View File
@@ -40,21 +40,21 @@ describe("pretty signature rendering", () => {
[
"{",
" /** Repository owner */",
" owner: string",
" owner: string,",
" /** Cursor from the previous response's pageInfo */",
" after?: string",
" after?: string,",
" /**",
" * Results per page",
" * @default 30",
" */",
" perPage?: number",
" perPage?: number,",
" /**",
" * Filter by labels",
" * @minItems 1",
" * @maxItems 10",
" */",
" labels?: Array<string>",
' state?: "open" | "closed"',
" labels?: Array<string>,",
' state?: "open" | "closed",',
"}",
].join("\n"),
)
@@ -83,7 +83,7 @@ describe("pretty signature rendering", () => {
true,
)
expect(pretty).toBe(
["{", " /** Search filter */", " filter?: {", " /** Issue state */", " state?: string", " }", "}"].join(
["{", " /** Search filter */", " filter?: {", " /** Issue state */", " state?: string,", " },", "}"].join(
"\n",
),
)
@@ -91,10 +91,10 @@ describe("pretty signature rendering", () => {
test("Effect Schema annotations become JSDoc on input and output fields", () => {
expect(inputTypeScript(lookupOrder, true)).toBe(
["{", " /** Order identifier */", " id: string", " verbose?: boolean", "}"].join("\n"),
["{", " /** Order identifier */", " id: string,", " verbose?: boolean,", "}"].join("\n"),
)
expect(outputTypeScript(lookupOrder, true)).toBe(
["{", " /** Current order status */", " status: string", "}"].join("\n"),
["{", " /** Current order status */", " status: string,", "}"].join("\n"),
)
})
@@ -129,7 +129,7 @@ describe("pretty signature rendering", () => {
{ type: "object", properties: { size: { type: "number", default: 1n } } },
true,
)
expect(pretty).toBe(["{", " size?: number", "}"].join("\n"))
expect(pretty).toBe(["{", " size?: number,", "}"].join("\n"))
})
test("neutralizes */ inside descriptions so nothing closes the comment early", () => {
@@ -150,7 +150,7 @@ describe("pretty signature rendering", () => {
true,
)
expect(pretty).toBe(
["{", " /**", " * First line", " *", " * Second line", " */", " query?: string", "}"].join("\n"),
["{", " /**", " * First line", " *", " * Second line", " */", " query?: string,", "}"].join("\n"),
)
})
@@ -235,12 +235,12 @@ describe("non-identifier property names render as quoted keys", () => {
expect(jsonSchemaToTypeScript(rawSchema, true)).toBe(
[
"{",
' "123"?: number',
' "foo-bar"?: string',
' "@type": string',
' "123"?: number,',
' "foo-bar"?: string,',
' "@type": string,',
" /** Dotted name */",
' "x.y"?: number',
" plain?: boolean",
' "x.y"?: number,',
" plain?: boolean,",
"}",
].join("\n"),
)
@@ -259,7 +259,7 @@ describe("non-identifier property names render as quoted keys", () => {
})
expect(inputTypeScript(tool)).toContain('"foo-bar"?: string')
expect(outputTypeScript(tool)).toBe('{ "content-type": string }')
expect(outputTypeScript(tool, true)).toBe(["{", ' "content-type": string', "}"].join("\n"))
expect(outputTypeScript(tool, true)).toBe(["{", ' "content-type": string,', "}"].join("\n"))
})
test("Effect Schema structs with non-identifier field names quote too", () => {
@@ -269,7 +269,7 @@ describe("non-identifier property names render as quoted keys", () => {
run: () => Effect.succeed(null),
})
expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number }')
expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string', " plain?: number", "}"].join("\n"))
expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string,', " plain?: number,", "}"].join("\n"))
})
})
@@ -332,7 +332,7 @@ describe("union schemas render every alternative", () => {
})
})
describe("pretty signatures in search results", () => {
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) => {
@@ -341,7 +341,7 @@ describe("pretty signatures in search results", () => {
)
expect(result.ok).toBe(true)
if (!result.ok) throw new Error("search failed")
return result.value as { items: Array<{ path: string; signature: string }>; total: number }
return result.value as { items: Array<{ path: string; signature: string }>; remaining: number }
}
test("a raw JSON Schema (MCP-style) tool's result signature carries field JSDoc and tags", async () => {
@@ -351,21 +351,21 @@ describe("pretty signatures in search results", () => {
[
"tools.github.list_issues(input: {",
" /** Repository owner */",
" owner: string",
" owner: string,",
" /** Cursor from the previous response's pageInfo */",
" after?: string",
" after?: string,",
" /**",
" * Results per page",
" * @default 30",
" */",
" perPage?: number",
" perPage?: number,",
" /**",
" * Filter by labels",
" * @minItems 1",
" * @maxItems 10",
" */",
" labels?: Array<string>",
' state?: "open" | "closed"',
" labels?: Array<string>,",
' state?: "open" | "closed",',
"}): Promise<unknown>",
].join("\n"),
)
@@ -379,26 +379,26 @@ describe("pretty signatures in search results", () => {
[
"tools.orders.lookup(input: {",
" /** Order identifier */",
" id: string",
" verbose?: boolean",
" id: string,",
" verbose?: boolean,",
"}): Promise<{",
" /** Current order status */",
" status: string",
" status: string,",
"}>",
].join("\n"),
)
}
})
test("the inline catalog line for the same tool stays single-line compact", () => {
test("the inline catalog uses the same JSDoc signatures", async () => {
const instructions = runtime.instructions()
expect(instructions).toContain(
' - tools.github.list_issues(input: { owner: string; after?: string; perPage?: number; labels?: Array<string>; state?: "open" | "closed" }): Promise<unknown> // List issues in a repository',
)
expect(instructions).toContain(
" - tools.orders.lookup(input: { id: string; verbose?: boolean }): Promise<{ status: string }> // Look up an order",
)
expect(instructions).not.toContain("/**")
const github = (await search("list issues repository")).items.find(
({ path }) => path === "tools.github.list_issues",
)!
const orders = (await search("look up order")).items.find(({ path }) => path === "tools.orders.lookup")!
expect(instructions).toContain(` - ${github.signature} // List issues in a repository`)
expect(instructions).toContain(` - ${orders.signature} // Look up an order`)
expect(instructions).toContain("/** Repository owner */")
})
})
@@ -421,7 +421,7 @@ describe("non-identifier tool paths", () => {
const instructions = runtime.instructions()
expect(instructions).toContain(
'tools.context7["resolve-library-id"](input: { query: string; libraryName: string }): Promise<unknown>',
'tools.context7["resolve-library-id"](input: {\n query: string,\n libraryName: string,\n}): Promise<unknown>',
)
expect(instructions).toContain("Do not infer or normalize tool names")
expect(instructions).toContain("bracket notation and quotes are part of the path")