fix: fix plan mode on non-default toolsets (#398)

Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
Charles Packer
2025-12-26 12:29:07 -08:00
committed by GitHub
parent f51deb1229
commit 63388074a7
2 changed files with 25 additions and 6 deletions

View File

@@ -206,7 +206,7 @@ function getPlanModeReminder(): string {
Plan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits (with the exception of the plan file mentioned below), run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supercedes any other instructions you have received.
## Plan File Info:
${planFilePath ? `No plan file exists yet. You should create your plan at ${planFilePath} using the Write tool.` : "No plan file path assigned."}
${planFilePath ? `No plan file exists yet. You should create your plan at ${planFilePath} using a write tool (e.g. Write, ApplyPatch, etc. depending on your toolset).` : "No plan file path assigned."}
You should build your plan incrementally by writing to or editing this file. NOTE that this is the only file you are allowed to edit - other than this you are only allowed to take READ-ONLY actions.
@@ -5002,7 +5002,7 @@ DO NOT respond to these messages or otherwise consider them in your response unl
handlePlanKeepPlanning(
`You must write your plan to the plan file before exiting plan mode.\n` +
`Plan file path: ${planFilePath || "not set"}\n` +
`Use the Write tool to create your plan, then call ExitPlanMode again.`,
`Use a write tool (e.g. Write, ApplyPatch, etc.) to create your plan, then call ExitPlanMode again.`,
);
}
}, [pendingApprovals, approvalResults.length, handlePlanKeepPlanning]);

View File

@@ -151,14 +151,18 @@ class PermissionModeManager {
"ReadManyFiles",
];
const writeTools = [
// Anthropic toolset
// Anthropic toolset (PascalCase only)
"Write",
"Edit",
"MultiEdit",
"NotebookEdit",
// Codex toolset
// Codex toolset (snake_case and PascalCase)
"apply_patch",
"ApplyPatch",
// Gemini toolset (snake_case and PascalCase)
"write_file_gemini",
"WriteFileGemini",
"replace",
"Replace",
];
if (allowedInPlan.includes(toolName)) {
@@ -168,9 +172,24 @@ class PermissionModeManager {
// Special case: allow writes to the plan file only
if (writeTools.includes(toolName)) {
const planFilePath = this.getPlanFilePath();
const targetPath =
let targetPath =
(toolArgs?.file_path as string) || (toolArgs?.path as string);
// ApplyPatch/apply_patch: extract file path from patch input
if (
(toolName === "ApplyPatch" || toolName === "apply_patch") &&
toolArgs?.input
) {
const input = toolArgs.input as string;
// Extract path from "*** Add File: path", "*** Update File: path", or "*** Delete File: path"
const match = input.match(
/\*\*\* (?:Add|Update|Delete) File:\s*(.+)/,
);
if (match?.[1]) {
targetPath = match[1].trim();
}
}
if (planFilePath && targetPath && targetPath === planFilePath) {
return "allow";
}