mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
5365f971ef
Signed-off-by: phernandez <paul@basicmachines.co>
124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
import { Type } from "@sinclair/typebox"
|
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
|
|
import type { BmClient } from "../bm-client.ts"
|
|
import { log } from "../logger.ts"
|
|
|
|
export function registerEditTool(
|
|
api: OpenClawPluginApi,
|
|
client: BmClient,
|
|
): void {
|
|
api.registerTool(
|
|
{
|
|
name: "edit_note",
|
|
label: "Edit Note",
|
|
description:
|
|
"Incrementally edit an existing note in the Basic Memory knowledge graph. " +
|
|
"Supports append, prepend, find/replace, and section replacement " +
|
|
"without rewriting the entire note.",
|
|
parameters: Type.Object({
|
|
identifier: Type.String({
|
|
description: "Note title, permalink, or memory:// URL to edit",
|
|
}),
|
|
operation: Type.Union(
|
|
[
|
|
Type.Literal("append"),
|
|
Type.Literal("prepend"),
|
|
Type.Literal("find_replace"),
|
|
Type.Literal("replace_section"),
|
|
],
|
|
{
|
|
description:
|
|
"Edit operation: append (add to end), prepend (add to start), " +
|
|
"find_replace (replace matching text), replace_section (replace a heading section)",
|
|
},
|
|
),
|
|
content: Type.String({
|
|
description: "New content to add or replace with",
|
|
}),
|
|
find_text: Type.Optional(
|
|
Type.String({
|
|
description: "Text to find (required for find_replace)",
|
|
}),
|
|
),
|
|
section: Type.Optional(
|
|
Type.String({
|
|
description:
|
|
"Section heading to replace (required for replace_section)",
|
|
}),
|
|
),
|
|
expected_replacements: Type.Optional(
|
|
Type.Number({
|
|
description:
|
|
"Expected replacement count for find_replace (default: 1)",
|
|
}),
|
|
),
|
|
project: Type.Optional(
|
|
Type.String({
|
|
description: "Target project name (defaults to current project)",
|
|
}),
|
|
),
|
|
}),
|
|
async execute(
|
|
_toolCallId: string,
|
|
params: {
|
|
identifier: string
|
|
operation: "append" | "prepend" | "find_replace" | "replace_section"
|
|
content: string
|
|
find_text?: string
|
|
section?: string
|
|
expected_replacements?: number
|
|
project?: string
|
|
},
|
|
) {
|
|
log.debug(`edit_note: id="${params.identifier}" op=${params.operation}`)
|
|
|
|
try {
|
|
const note = await client.editNote(
|
|
params.identifier,
|
|
params.operation,
|
|
params.content,
|
|
{
|
|
find_text: params.find_text,
|
|
section: params.section,
|
|
expected_replacements: params.expected_replacements,
|
|
},
|
|
params.project,
|
|
)
|
|
|
|
return {
|
|
content: [
|
|
{
|
|
type: "text" as const,
|
|
text: `Note updated: ${note.title} (${note.permalink})`,
|
|
},
|
|
],
|
|
details: {
|
|
title: note.title,
|
|
permalink: note.permalink,
|
|
file_path: note.file_path,
|
|
operation: params.operation,
|
|
checksum: note.checksum ?? null,
|
|
},
|
|
}
|
|
} catch (err) {
|
|
log.error("edit_note failed", err)
|
|
return {
|
|
content: [
|
|
{
|
|
type: "text" as const,
|
|
text: `Failed to edit note "${params.identifier}". It may not exist.`,
|
|
},
|
|
],
|
|
details: {
|
|
identifier: params.identifier,
|
|
operation: params.operation,
|
|
error: "edit_note_failed",
|
|
},
|
|
}
|
|
}
|
|
},
|
|
},
|
|
{ name: "edit_note" },
|
|
)
|
|
}
|