Skip to content

Commit b43ef9b

Browse files
committed
test(prompts,diff): assert whole-lines guidance in apply_diff description and no-match error
1 parent ebd3978 commit b43ef9b

2 files changed

Lines changed: 63 additions & 0 deletions

File tree

‎src/core/diff/strategies/__tests__/multi-search-replace.spec.ts‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,29 @@ replacement content here
905905
expect(error).toContain("Best Match Length: 0 characters")
906906
})
907907

908+
it("should include a whole-lines tip when no sufficiently similar match is found", async () => {
909+
const originalContent = "line one\nline two"
910+
const diffContent = `test.ts
911+
<<<<<<< SEARCH
912+
:start_line:999
913+
-------
914+
non-existent content that cannot be found in the file
915+
=======
916+
replacement content here
917+
>>>>>>> REPLACE`
918+
919+
const result = await strategy.applyDiff(originalContent, diffContent)
920+
expect(result.success).toBe(false)
921+
const error =
922+
!result.success && result.failParts?.[0]
923+
? "error" in result.failParts[0]
924+
? result.failParts[0].error
925+
: ""
926+
: ""
927+
expect(error).toContain("No sufficiently similar match found")
928+
expect(error).toContain("Tip: The SEARCH block must contain complete, whole lines")
929+
})
930+
908931
it("should include scoped original content when search fails with start_line that has a low-score match", async () => {
909932
const originalContent = "function existing() {\n return 42;\n}\n"
910933
const diffContent = `test.ts
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type OpenAI from "openai"
2+
import { apply_diff } from "../apply_diff"
3+
4+
// Helper type to access function tools
5+
type FunctionTool = OpenAI.Chat.ChatCompletionTool & { type: "function" }
6+
7+
// Helper to get function definition from tool
8+
const getFunctionDef = (tool: OpenAI.Chat.ChatCompletionTool) => (tool as FunctionTool).function
9+
10+
// OpenAI types the parameter schema as FunctionParameters (Record<string, unknown>).
11+
// Narrow it with runtime checks instead of assertions so the spec tracks schema changes.
12+
function asRecord(value: unknown): Record<string, unknown> {
13+
if (typeof value !== "object" || value === null) {
14+
throw new Error("expected an object value in the apply_diff parameter schema")
15+
}
16+
return value as Record<string, unknown>
17+
}
18+
19+
const getDiffParameterDescription = (): string => {
20+
const parameters = asRecord(getFunctionDef(apply_diff).parameters)
21+
const properties = asRecord(parameters["properties"])
22+
const diff = asRecord(properties["diff"])
23+
const description = diff["description"]
24+
if (typeof description !== "string") {
25+
throw new Error("diff parameter must declare a string description")
26+
}
27+
return description
28+
}
29+
30+
describe("apply_diff diff parameter description", () => {
31+
const diffDescription = getDiffParameterDescription()
32+
33+
it("should require complete, whole lines in the SEARCH block", () => {
34+
expect(diffDescription).toContain("The SEARCH block must contain complete, whole lines")
35+
})
36+
37+
it("should warn that partial-line (substring) matching is not supported", () => {
38+
expect(diffDescription).toContain("partial-line (substring) matching is not supported")
39+
})
40+
})

0 commit comments

Comments
 (0)