Diffs: restore system prompt guidance (#36904)

Merged via squash.

Prepared head SHA: 1b3be3c879
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Gustavo Madeira Santana
2026-03-05 19:46:39 -05:00
committed by GitHub
parent 06a229f98f
commit 1a67cf57e3
6 changed files with 48 additions and 4 deletions

View File

@@ -16,7 +16,7 @@ The tool can return:
- `details.filePath`: a local rendered artifact path when file rendering is requested
- `details.fileFormat`: the rendered file format (`png` or `pdf`)
When the plugin is enabled, it also ships a companion skill from `skills/` that guides when to use `diffs`. This guidance is delivered through normal skill loading, not unconditional prompt-hook injection on every turn.
When the plugin is enabled, it also ships a companion skill from `skills/` and prepends stable tool-usage guidance into system-prompt space via `before_prompt_build`. The hook uses `prependSystemContext`, so the guidance stays out of user-prompt space while still being available every turn.
This means an agent can:

View File

@@ -4,7 +4,7 @@ import { createMockServerResponse } from "../../src/test-utils/mock-http-respons
import plugin from "./index.js";
describe("diffs plugin registration", () => {
it("registers the tool and http route", () => {
it("registers the tool, http route, and system-prompt guidance hook", async () => {
const registerTool = vi.fn();
const registerHttpRoute = vi.fn();
const on = vi.fn();
@@ -43,7 +43,14 @@ describe("diffs plugin registration", () => {
auth: "plugin",
match: "prefix",
});
expect(on).not.toHaveBeenCalled();
expect(on).toHaveBeenCalledTimes(1);
expect(on.mock.calls[0]?.[0]).toBe("before_prompt_build");
const beforePromptBuild = on.mock.calls[0]?.[1];
const result = await beforePromptBuild?.({}, {});
expect(result).toMatchObject({
prependSystemContext: expect.stringContaining("prefer the `diffs` tool"),
});
expect(result?.prependContext).toBeUndefined();
});
it("applies plugin-config defaults through registered tool and viewer handler", async () => {

View File

@@ -7,6 +7,7 @@ import {
resolveDiffsPluginSecurity,
} from "./src/config.js";
import { createDiffsHttpHandler } from "./src/http.js";
import { DIFFS_AGENT_GUIDANCE } from "./src/prompt-guidance.js";
import { DiffArtifactStore } from "./src/store.js";
import { createDiffsTool } from "./src/tool.js";
@@ -34,6 +35,9 @@ const plugin = {
allowRemoteViewer: security.allowRemoteViewer,
}),
});
api.on("before_prompt_build", async () => ({
prependSystemContext: DIFFS_AGENT_GUIDANCE,
}));
},
};

View File

@@ -0,0 +1,7 @@
export const DIFFS_AGENT_GUIDANCE = [
"When you need to show edits as a real diff, prefer the `diffs` tool instead of writing a manual summary.",
"It accepts either `before` + `after` text or a unified `patch`.",
"`mode=view` returns `details.viewerUrl` for canvas use; `mode=file` returns `details.filePath`; `mode=both` returns both.",
"If you need to send the rendered file, use the `message` tool with `path` or `filePath`.",
"Include `path` when you know the filename, and omit presentation overrides unless needed.",
].join("\n");