Skip to content

Commit 4df3cd2

Browse files
authored
Infer defineTool handler args from parameters schema (#68)
1 parent dade9c9 commit 4df3cd2

4 files changed

Lines changed: 15 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const triage = agent({
161161
```
162162

163163
Rig defaults agent tools to `skipPermission: true`, and you can also place plain tool objects in `tools`; rig will convert `s.*` parameter schemas into JSON Schema before creating the Copilot session.
164+
When `parameters` uses `s.*` schemas, `handler` args are inferred automatically; for plain JSON Schema, pass an explicit generic like `defineTool<{ issue: string }>(...)`.
164165

165166
## Evaluating agentic performance
166167

skills/rig/SKILL.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ s.nonEmptyArray(s.string) // string[] with at least one element
170170
## Tools
171171

172172
Register custom tools with `defineTool` using an SDK-neutral tool shape. Use `s.*` schemas for `parameters`. Rig defaults tools to `skipPermission: true`.
173+
When `parameters` uses `s.*` schemas, `handler` args are inferred automatically; for plain JSON Schema, pass an explicit generic like `defineTool<{ issue: string }>(...)`.
173174

174175
```ts
175176
import { agent, defineTool, s } from "rig";

skills/rig/rig.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,14 @@ export type ToolConfig<TArgs = unknown> = {
540540
overridesBuiltInTool?: boolean;
541541
skipPermission?: boolean;
542542
};
543-
544-
export function defineTool<T = unknown>(name: string, config: ToolConfig<T>): Tool<T> {
543+
type InferToolArgs<TParameters extends ToolParameters> = TParameters extends Schema ? InferSchema<TParameters> : unknown;
544+
545+
export function defineTool<const TParameters extends ToolParameters>(
546+
name: string,
547+
config: Omit<ToolConfig<InferToolArgs<TParameters>>, "parameters"> & { parameters: TParameters },
548+
): Tool<InferToolArgs<TParameters>>;
549+
export function defineTool<T = unknown>(name: string, config: ToolConfig<T>): Tool<T>;
550+
export function defineTool(name: string, config: ToolConfig<any>): Tool<any> {
545551
return {
546552
name,
547553
...normalizeToolConfig(config),

src/rig.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ vi.mock("@github/copilot-sdk", () => ({
5252
}));
5353

5454
import { AgentError, PromptBuilder, agent, analyzeResponse, configureAgent, copilotEngine, defineTool, p, s, toJsonSchema } from "rig";
55+
import type { Tool } from "rig";
5556
import { oncePerAgent, repair, steering, timeout } from "rig/addons";
5657

5758
beforeEach(() => {
@@ -537,18 +538,19 @@ describe("agent invocation", () => {
537538
});
538539

539540
it("defines tools with rig schemas using the Copilot SDK helper shape", () => {
540-
const handler = vi.fn(async ({ issue }: { issue: string }) => `Issue ${issue}`);
541541
const lookupIssue = defineTool("lookup_issue", {
542542
description: "Look up an issue by id.",
543543
parameters: s.object({ issue: s.string }),
544-
handler,
544+
handler: vi.fn(async ({ issue }) => `Issue ${issue}`),
545545
});
546+
const expectIssueTool = (_tool: Tool<{ issue: string }>) => true;
547+
expect(expectIssueTool(lookupIssue)).toBe(true);
546548

547549
expect(lookupIssue).toEqual({
548550
name: "lookup_issue",
549551
description: "Look up an issue by id.",
550552
parameters: toJsonSchema(s.object({ issue: s.string })),
551-
handler,
553+
handler: expect.any(Function),
552554
skipPermission: true,
553555
});
554556
});

0 commit comments

Comments
 (0)