59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
/**
|
|
* Protected Paths Extension
|
|
*
|
|
* Blocks write and edit operations to protected paths.
|
|
*
|
|
* Adapted from pi's bundled `examples/extensions/protected-paths.ts`. Upstream ships a
|
|
* three-entry demo list (.env, .git/, node_modules/); the list below names the files
|
|
* that actually matter in this dotfiles tree — the ones holding secrets, and the git
|
|
* metadata the agent has no business rewriting.
|
|
*
|
|
* Scope, so this isn't over-trusted: it guards against the *model* calling write/edit.
|
|
* It cannot stop pi's own `/login`, which rewrites auth.json with the literal key —
|
|
* that is why auth.json is gitignored and auth.json.example is the tracked copy.
|
|
*/
|
|
|
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
const protectedPaths = [
|
|
// Secrets. `secrets.fish` holds $DUSKADIY_API_KEY; auth.json is pi's own
|
|
// credential map and must keep $VAR references rather than literals.
|
|
"secrets.fish",
|
|
"auth.json",
|
|
".env",
|
|
"fish_variables",
|
|
|
|
// Credentials outside the repo.
|
|
".ssh/",
|
|
".gnupg/",
|
|
".aws/",
|
|
".netrc",
|
|
|
|
// Repo plumbing and vendored trees — never hand-edited.
|
|
".git/",
|
|
"node_modules/",
|
|
];
|
|
|
|
pi.on("tool_call", async (event, ctx) => {
|
|
if (event.toolName !== "write" && event.toolName !== "edit") {
|
|
return undefined;
|
|
}
|
|
|
|
const path = event.input.path as string;
|
|
// Substring match, like upstream: cheap, and these names are distinctive enough.
|
|
// Note `auth.json.example` is intentionally caught too — it is a tracked file
|
|
// whose whole job is to contain no secret, so an agent rewrite is worth a look.
|
|
const isProtected = protectedPaths.some((p) => path.includes(p));
|
|
|
|
if (isProtected) {
|
|
if (ctx.hasUI) {
|
|
ctx.ui.notify(`Blocked write to protected path: ${path}`, "warning");
|
|
}
|
|
return { block: true, reason: `Path "${path}" is protected` };
|
|
}
|
|
|
|
return undefined;
|
|
});
|
|
}
|