Files
oh-my-pi/packages/ai/test/tool-examples.test.ts
T
can1357 7687810c5d feat: added syntax-aware tool example rendering across catalog, AI, and agent modules
- Added model-to-syntax mapping in catalog with preferred tool-call syntax API.
- Added `ToolExample` typing and `ToolCallSyntax` exports across tool/grammar interfaces.
- Added syntax-aware tool example rendering through provider-specific grammar invocations.
- Added `exampleSyntax` context flow and example metadata so rendered prompts include examples.
2026-06-15 07:33:25 +02:00

163 lines
4.1 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { renderToolExamples } from "../src/grammar/examples";
import type { InbandTool } from "../src/grammar/types";
describe("renderToolExamples", () => {
it("renders call example in anthropic format", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: {
paths: { type: "array", items: { type: "string" } },
},
required: ["paths"],
},
examples: [
{
caption: "Find files",
call: { paths: ["src/**/*.ts"] },
},
],
};
const rendered = renderToolExamples(tool, "anthropic");
expect(rendered).toContain("<examples>");
expect(rendered).toContain("# Find files");
expect(rendered).toContain('<invoke name="find">');
expect(rendered).toContain('<parameter name="paths"');
expect(rendered).toContain("</examples>");
});
it("renders call example in pi format", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: {
paths: { type: "array", items: { type: "string" } },
},
required: ["paths"],
},
examples: [
{
caption: "Find files",
call: { paths: ["src/**/*.ts"] },
},
],
};
const rendered = renderToolExamples(tool, "pi");
expect(rendered).toContain("<call:find>");
expect(rendered).toContain("<paths>");
expect(rendered).toContain("src/**/*.ts");
});
it("renders call example in hermes format", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: {
paths: { type: "array", items: { type: "string" } },
},
required: ["paths"],
},
examples: [
{
caption: "Find files",
call: { paths: ["src/**/*.ts"] },
},
],
};
const rendered = renderToolExamples(tool, "hermes");
expect(rendered).toContain("<tool_call>");
expect(rendered).toContain('"name":"find"');
expect(rendered).toContain('"paths"');
});
it("returns empty string for empty examples", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: { type: "object", properties: {} },
examples: [],
};
expect(renderToolExamples(tool, "anthropic")).toBe("");
});
it("renders compare examples with WRONG and RIGHT", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: {
paths: { type: "array", items: { type: "string" } },
},
required: ["paths"],
},
examples: [
{
caption: "Avoid broad scans",
bad: { paths: ["**/*.ts"] },
good: { paths: ["src/**/*.ts"] },
},
],
};
const rendered = renderToolExamples(tool, "anthropic");
expect(rendered).toContain("WRONG:");
expect(rendered).toContain("RIGHT:");
expect(rendered).toContain('<parameter name="paths"');
expect(rendered).toContain('["**/*.ts"]');
});
it("injects the intent-field placeholder when intentField is provided", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: {
_i: { type: "string" },
paths: { type: "array", items: { type: "string" } },
},
required: ["_i", "paths"],
},
examples: [
{
caption: "Find files",
call: { paths: ["src/**/*.ts"] },
},
],
};
const rendered = renderToolExamples(tool, "anthropic", "_i");
expect(rendered).toContain('<parameter name="_i"');
expect(rendered).toContain("…");
// Placeholder leads the args, matching schema-injection order.
expect(rendered.indexOf('name="_i"')).toBeLessThan(rendered.indexOf('name="paths"'));
});
it("omits the intent-field placeholder when intentField is undefined", () => {
const tool: InbandTool = {
name: "find",
description: "Find files.",
parameters: {
type: "object",
properties: { paths: { type: "array", items: { type: "string" } } },
required: ["paths"],
},
examples: [{ caption: "Find files", call: { paths: ["src/**/*.ts"] } }],
};
expect(renderToolExamples(tool, "anthropic")).not.toContain("_i");
});
});