mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-10-03 02:21:23 +00:00
Merge a949311131 into cfa6c7cb17
This commit is contained in:
commit
2deb36a23a
3 changed files with 83 additions and 7 deletions
|
|
@ -180,6 +180,80 @@ describe("ClaudeMemoryTool exact-file matching", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("ClaudeMemoryTool insert line semantics", () => {
|
||||
let tool: ClaudeMemoryTool
|
||||
|
||||
beforeEach(() => {
|
||||
searchExecute.mockReset()
|
||||
addMock.mockReset()
|
||||
mockDocument(FILE_CONTENT)
|
||||
tool = new ClaudeMemoryTool("test-api-key")
|
||||
})
|
||||
|
||||
// The memory_20250818 spec: insert_text is inserted AFTER line insert_line,
|
||||
// 0 inserts at the beginning of the file, and the valid range is [0, n_lines].
|
||||
|
||||
it("insert_line: 0 inserts at the beginning of the file", async () => {
|
||||
const result = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: 0,
|
||||
insert_text: "header",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
const stored = addMock.mock.calls[0]?.[0]?.content as string
|
||||
expect(stored).toBe("header\nline1\nline2\nline3\nline4\nline5")
|
||||
})
|
||||
|
||||
it("inserts AFTER the given line, not before it", async () => {
|
||||
const result = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: 2,
|
||||
insert_text: "after2",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
const stored = addMock.mock.calls[0]?.[0]?.content as string
|
||||
// Regression guard: the old 1-based insert-BEFORE landed this one line early.
|
||||
expect(stored).toBe("line1\nline2\nafter2\nline3\nline4\nline5")
|
||||
})
|
||||
|
||||
it("insert_line: n_lines appends at the end of the file", async () => {
|
||||
const result = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: 5,
|
||||
insert_text: "tail",
|
||||
})
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
const stored = addMock.mock.calls[0]?.[0]?.content as string
|
||||
expect(stored).toBe("line1\nline2\nline3\nline4\nline5\ntail")
|
||||
})
|
||||
|
||||
it("rejects insert_line outside [0, n_lines] without writing", async () => {
|
||||
const below = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: -1,
|
||||
insert_text: "x",
|
||||
})
|
||||
expect(below.success).toBe(false)
|
||||
expect(below.error).toContain("[0, 5]")
|
||||
|
||||
const above = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: 6,
|
||||
insert_text: "x",
|
||||
})
|
||||
expect(above.success).toBe(false)
|
||||
expect(addMock).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe("ClaudeMemoryTool str_replace replacement literalness", () => {
|
||||
let tool: ClaudeMemoryTool
|
||||
|
||||
|
|
|
|||
|
|
@ -490,16 +490,18 @@ export class ClaudeMemoryTool {
|
|||
const originalContent = readResult.document.content
|
||||
const lines = originalContent.split("\n")
|
||||
|
||||
// Validate line number
|
||||
if (insertLine < 1 || insertLine > lines.length + 1) {
|
||||
// Validate line number. Per the memory_20250818 spec the valid range
|
||||
// is [0, n_lines]: text is inserted AFTER `insert_line`, and 0 means
|
||||
// the beginning of the file.
|
||||
if (insertLine < 0 || insertLine > lines.length) {
|
||||
return {
|
||||
success: false,
|
||||
error: `Invalid line number: ${insertLine}. File has ${lines.length} lines.`,
|
||||
error: `Invalid insert_line parameter: ${insertLine}. It should be within the range of lines of the file: [0, ${lines.length}]`,
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the text (insertLine is 1-based)
|
||||
lines.splice(insertLine - 1, 0, insertText)
|
||||
// Insert the text after line `insertLine` (0-based insert-after)
|
||||
lines.splice(insertLine, 0, insertText)
|
||||
const newContent = lines.join("\n")
|
||||
|
||||
// Update the document
|
||||
|
|
@ -517,7 +519,7 @@ export class ClaudeMemoryTool {
|
|||
|
||||
return {
|
||||
success: true,
|
||||
content: `Text inserted at line ${insertLine} in file: ${filePath}`,
|
||||
content: `Text inserted after line ${insertLine} in file: ${filePath}`,
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -309,7 +309,7 @@ describe("ClaudeMemoryTool", () => {
|
|||
const result = await tool.handleCommand({
|
||||
command: "insert",
|
||||
path: FILE_PATH,
|
||||
insert_line: 2,
|
||||
insert_line: 1,
|
||||
insert_text: "",
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue