diff --git a/src/index.ts b/src/index.ts index c47d4f5..ef80466 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1391,6 +1391,10 @@ export function createApplyPatchTool(): ApplyPatchToolDefinition { label: "ApplyPatch", description: APPLY_PATCH_FREEFORM_DESCRIPTION, parameters: APPLY_PATCH_PARAMS, + // Pi's public grammar hook: models whose provider sets `compat.supportsOpenAIGrammarTools` + // receive apply_patch as a native OpenAI custom tool constrained by the Codex Lark grammar. + // Other providers fall back to the plain function tool. + constrainedSampling: { type: "grammar", variants: { openai_lark: APPLY_PATCH_LARK_GRAMMAR } }, prepareArguments: normalizeApplyPatchArguments, promptSnippet: "Apply Codex-format file patches with apply_patch", promptGuidelines: [ diff --git a/test/index.test.ts b/test/index.test.ts index c8e22be..4759881 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -112,11 +112,13 @@ describe("pi-apply-patch", () => { let capturedToolName: string | undefined; let capturedDescription: string | undefined; let capturedFreeform: FreeformToolFormat | undefined; + let capturedConstrainedSampling: ReturnType["constrainedSampling"]; const extensionApi = { registerTool(tool: ReturnType) { capturedToolName = tool.name; capturedDescription = tool.description; capturedFreeform = tool.freeform; + capturedConstrainedSampling = tool.constrainedSampling; }, on() { return () => {}; @@ -138,6 +140,10 @@ describe("pi-apply-patch", () => { syntax: "lark", definition: APPLY_PATCH_LARK_GRAMMAR, }); + expect(capturedConstrainedSampling).toEqual({ + type: "grammar", + variants: { openai_lark: APPLY_PATCH_LARK_GRAMMAR }, + }); }); it("#given GPT model after reload with apply_patch already active #when session starts #then keeps apply_patch active", async () => {