Fix hashline-edit deduplication and validation

- Canonicalize anchors in dedupe keys to handle whitespace variants
- Make lines field required in edit operations
- Only allow unanchored append/prepend to create missing files
- Reorder delete/rename validation to prevent edge cases
- Add allow_non_gpt_model and max_prompt_tokens to config schema
  ```
This commit is contained in:
minpeter
2026-02-26 17:43:49 +09:00
parent 58201220cc
commit b1203b9501
7 changed files with 117 additions and 15 deletions
@@ -33,7 +33,7 @@ function resolveToolCallID(ctx: ToolContextWithCallID): string | undefined {
function canCreateFromMissingFile(edits: HashlineEdit[]): boolean {
if (edits.length === 0) return false
return edits.every((edit) => edit.op === "append" || edit.op === "prepend")
return edits.every((edit) => (edit.op === "append" || edit.op === "prepend") && !edit.pos)
}
function buildSuccessMeta(
@@ -86,19 +86,19 @@ export async function executeHashlineEditTool(args: HashlineEditArgs, context: T
const filePath = args.filePath
const { delete: deleteMode, rename } = args
if (deleteMode && rename) {
return "Error: delete and rename cannot be used together"
}
if (deleteMode && args.edits.length > 0) {
return "Error: delete mode requires edits to be an empty array"
}
if (!deleteMode && (!args.edits || !Array.isArray(args.edits) || args.edits.length === 0)) {
return "Error: edits parameter must be a non-empty array"
}
const edits = deleteMode ? [] : normalizeHashlineEdits(args.edits)
if (deleteMode && rename) {
return "Error: delete and rename cannot be used together"
}
if (deleteMode && edits.length > 0) {
return "Error: delete mode requires edits to be an empty array"
}
const file = Bun.file(filePath)
const exists = await file.exists()
if (!exists && !deleteMode && !canCreateFromMissingFile(edits)) {