@basicmemory/openclaw-basic-memory 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +38 -18
  2. package/commands/cli.ts +1 -1
  3. package/commands/skills.ts +22 -10
  4. package/commands/slash.ts +4 -2
  5. package/config.ts +1 -0
  6. package/context-engine/basic-memory-context-engine.ts +38 -57
  7. package/dist/bm-client.d.ts +177 -0
  8. package/dist/bm-client.js +572 -0
  9. package/dist/commands/cli.d.ts +4 -0
  10. package/dist/commands/cli.js +117 -0
  11. package/dist/commands/skills.d.ts +2 -0
  12. package/dist/commands/skills.js +47 -0
  13. package/dist/commands/slash.d.ts +3 -0
  14. package/dist/commands/slash.js +92 -0
  15. package/dist/config.d.ts +22 -0
  16. package/dist/config.js +109 -0
  17. package/dist/context-engine/basic-memory-context-engine.d.ts +94 -0
  18. package/dist/context-engine/basic-memory-context-engine.js +176 -0
  19. package/dist/hooks/capture.d.ts +24 -0
  20. package/dist/hooks/capture.js +88 -0
  21. package/dist/hooks/recall.d.ts +24 -0
  22. package/dist/hooks/recall.js +56 -0
  23. package/dist/index.d.ts +8 -0
  24. package/dist/index.js +125 -0
  25. package/dist/logger.d.ts +13 -0
  26. package/dist/logger.js +34 -0
  27. package/dist/schema/conversation-schema.d.ts +5 -0
  28. package/dist/schema/conversation-schema.js +33 -0
  29. package/dist/schema/task-schema.d.ts +5 -0
  30. package/dist/schema/task-schema.js +34 -0
  31. package/dist/tools/build-context.d.ts +3 -0
  32. package/dist/tools/build-context.js +100 -0
  33. package/dist/tools/delete-note.d.ts +3 -0
  34. package/dist/tools/delete-note.js +52 -0
  35. package/dist/tools/edit-note.d.ts +3 -0
  36. package/dist/tools/edit-note.js +81 -0
  37. package/dist/tools/list-memory-projects.d.ts +3 -0
  38. package/dist/tools/list-memory-projects.js +85 -0
  39. package/dist/tools/list-workspaces.d.ts +3 -0
  40. package/dist/tools/list-workspaces.js +64 -0
  41. package/dist/tools/memory-provider.d.ts +15 -0
  42. package/dist/tools/memory-provider.js +274 -0
  43. package/dist/tools/move-note.d.ts +3 -0
  44. package/dist/tools/move-note.js +56 -0
  45. package/dist/tools/read-note.d.ts +3 -0
  46. package/dist/tools/read-note.js +57 -0
  47. package/dist/tools/schema-diff.d.ts +3 -0
  48. package/dist/tools/schema-diff.js +81 -0
  49. package/dist/tools/schema-infer.d.ts +3 -0
  50. package/dist/tools/schema-infer.js +66 -0
  51. package/dist/tools/schema-validate.d.ts +3 -0
  52. package/dist/tools/schema-validate.js +73 -0
  53. package/dist/tools/search-notes.d.ts +3 -0
  54. package/dist/tools/search-notes.js +97 -0
  55. package/dist/tools/write-note.d.ts +3 -0
  56. package/dist/tools/write-note.js +80 -0
  57. package/index.ts +4 -5
  58. package/openclaw.plugin.json +28 -8
  59. package/package.json +24 -6
  60. package/tools/build-context.ts +1 -1
  61. package/tools/delete-note.ts +1 -1
  62. package/tools/edit-note.ts +1 -1
  63. package/tools/list-memory-projects.ts +1 -1
  64. package/tools/list-workspaces.ts +1 -1
  65. package/tools/memory-provider.ts +1 -1
  66. package/tools/move-note.ts +1 -1
  67. package/tools/read-note.ts +1 -1
  68. package/tools/schema-diff.ts +1 -1
  69. package/tools/schema-infer.ts +1 -1
  70. package/tools/schema-validate.ts +1 -1
  71. package/tools/search-notes.ts +9 -5
  72. package/tools/write-note.ts +1 -1
  73. package/context-engine/basic-memory-context-engine.test.ts +0 -398
@@ -0,0 +1,73 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { log } from "../logger.js";
3
+ export function registerSchemaValidateTool(api, client) {
4
+ api.registerTool({
5
+ name: "schema_validate",
6
+ label: "Schema Validate",
7
+ description: "Validate notes against their Picoschema definitions. " +
8
+ "Validates a specific note by identifier, or all notes of a given type.",
9
+ parameters: Type.Object({
10
+ noteType: Type.Optional(Type.String({
11
+ description: 'Note type to batch-validate (e.g., "person", "meeting")',
12
+ })),
13
+ identifier: Type.Optional(Type.String({
14
+ description: "Specific note to validate (permalink, title, or path)",
15
+ })),
16
+ project: Type.Optional(Type.String({
17
+ description: "Target project name (defaults to current project)",
18
+ })),
19
+ }),
20
+ async execute(_toolCallId, params) {
21
+ log.debug(`schema_validate: noteType="${params.noteType ?? ""}" identifier="${params.identifier ?? ""}"`);
22
+ try {
23
+ const result = await client.schemaValidate(params.noteType, params.identifier, params.project);
24
+ // Handle error responses from BM (e.g., no schema found)
25
+ const resultRecord = result;
26
+ if ("error" in result && typeof resultRecord.error === "string") {
27
+ return {
28
+ content: [{ type: "text", text: resultRecord.error }],
29
+ details: result,
30
+ };
31
+ }
32
+ const lines = [];
33
+ if (result.entity_type) {
34
+ lines.push(`**Type:** ${result.entity_type}`);
35
+ }
36
+ lines.push(`**Notes:** ${result.total_notes ?? 0} | **Valid:** ${result.valid_count ?? 0} | **Warnings:** ${result.warning_count ?? 0} | **Errors:** ${result.error_count ?? 0}`);
37
+ if (result.results && result.results.length > 0) {
38
+ lines.push("");
39
+ for (const r of result.results) {
40
+ const status = r.valid ? "valid" : "invalid";
41
+ lines.push(`- **${r.identifier}** — ${status}`);
42
+ for (const w of r.warnings) {
43
+ lines.push(` - warning: ${w}`);
44
+ }
45
+ for (const e of r.errors) {
46
+ lines.push(` - error: ${e}`);
47
+ }
48
+ }
49
+ }
50
+ return {
51
+ content: [{ type: "text", text: lines.join("\n") }],
52
+ details: result,
53
+ };
54
+ }
55
+ catch (err) {
56
+ log.error("schema_validate failed", err);
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: "Schema validation failed. Check logs for details.",
62
+ },
63
+ ],
64
+ details: {
65
+ noteType: params.noteType ?? null,
66
+ identifier: params.identifier ?? null,
67
+ error: "schema_validate_failed",
68
+ },
69
+ };
70
+ }
71
+ },
72
+ }, { name: "schema_validate" });
73
+ }
@@ -0,0 +1,3 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
2
+ import type { BmClient } from "../bm-client.ts";
3
+ export declare function registerSearchTool(api: OpenClawPluginApi, client: BmClient): void;
@@ -0,0 +1,97 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { log } from "../logger.js";
3
+ export function registerSearchTool(api, client) {
4
+ api.registerTool({
5
+ name: "search_notes",
6
+ label: "Knowledge Search",
7
+ description: "Search the Basic Memory knowledge graph for relevant notes, concepts, and connections. " +
8
+ "Returns matching notes with titles, content previews, and relevance scores. " +
9
+ "Optionally filter by frontmatter metadata fields, tags, or status.",
10
+ parameters: Type.Object({
11
+ query: Type.String({ description: "Search query" }),
12
+ limit: Type.Optional(Type.Number({ description: "Max results (default: 10)" })),
13
+ project: Type.Optional(Type.String({
14
+ description: "Target project name (defaults to current project)",
15
+ })),
16
+ metadata_filters: Type.Optional(Type.Object({}, {
17
+ additionalProperties: true,
18
+ description: "Filter by frontmatter fields. Supports equality, $in, $gt/$gte/$lt/$lte, $between, and array-contains operators.",
19
+ })),
20
+ tags: Type.Optional(Type.Array(Type.String(), {
21
+ description: "Filter by frontmatter tags (all must match)",
22
+ })),
23
+ status: Type.Optional(Type.String({
24
+ description: "Filter by frontmatter status field",
25
+ })),
26
+ }),
27
+ async execute(_toolCallId, params) {
28
+ const limit = params.limit ?? 10;
29
+ log.debug(`search_notes: query="${params.query}" limit=${limit} project="${params.project ?? "default"}"`);
30
+ const metadata = params.metadata_filters || params.tags || params.status
31
+ ? {
32
+ filters: params.metadata_filters,
33
+ tags: params.tags,
34
+ status: params.status,
35
+ }
36
+ : undefined;
37
+ try {
38
+ const results = await client.search(params.query, limit, params.project, metadata);
39
+ if (results.length === 0) {
40
+ return {
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: "No matching notes found in the knowledge graph.",
45
+ },
46
+ ],
47
+ details: {
48
+ count: 0,
49
+ results: [],
50
+ },
51
+ };
52
+ }
53
+ const text = results
54
+ .map((r, i) => {
55
+ const score = r.score ? ` (${(r.score * 100).toFixed(0)}%)` : "";
56
+ const content = r.content ?? "";
57
+ const preview = content.length > 200 ? `${content.slice(0, 200)}...` : content;
58
+ return `${i + 1}. **${r.title}**${score}\n ${preview}`;
59
+ })
60
+ .join("\n\n");
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: `Found ${results.length} notes:\n\n${text}`,
66
+ },
67
+ ],
68
+ details: {
69
+ count: results.length,
70
+ results: results.map((r) => ({
71
+ title: r.title,
72
+ permalink: r.permalink,
73
+ score: r.score,
74
+ })),
75
+ },
76
+ };
77
+ }
78
+ catch (err) {
79
+ log.error("search_notes failed", err);
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: "Search failed. Is Basic Memory running? Check logs for details.",
85
+ },
86
+ ],
87
+ details: {
88
+ count: 0,
89
+ results: [],
90
+ query: params.query,
91
+ error: "search_notes_failed",
92
+ },
93
+ };
94
+ }
95
+ },
96
+ }, { name: "search_notes" });
97
+ }
@@ -0,0 +1,3 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
2
+ import type { BmClient } from "../bm-client.ts";
3
+ export declare function registerWriteTool(api: OpenClawPluginApi, client: BmClient): void;
@@ -0,0 +1,80 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { NoteAlreadyExistsError } from "../bm-client.js";
3
+ import { log } from "../logger.js";
4
+ export function registerWriteTool(api, client) {
5
+ api.registerTool({
6
+ name: "write_note",
7
+ label: "Write Note",
8
+ description: "Create a note in the Basic Memory knowledge graph. " +
9
+ "If the note already exists, returns an error by default. " +
10
+ "Pass overwrite=true to replace, or use edit_note for incremental updates.",
11
+ parameters: Type.Object({
12
+ title: Type.String({ description: "Note title" }),
13
+ content: Type.String({
14
+ description: "Note content in Markdown format",
15
+ }),
16
+ folder: Type.String({ description: "Folder to write the note in" }),
17
+ project: Type.Optional(Type.String({
18
+ description: "Target project name (defaults to current project)",
19
+ })),
20
+ overwrite: Type.Optional(Type.Boolean({
21
+ description: "Set to true to replace an existing note. Defaults to false.",
22
+ })),
23
+ }),
24
+ async execute(_toolCallId, params) {
25
+ log.debug(`write_note: title=${params.title} folder=${params.folder}`);
26
+ try {
27
+ const note = await client.writeNote(params.title, params.content, params.folder, params.project, params.overwrite);
28
+ const msg = `Note saved: ${note.title} (${note.permalink})`;
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: msg,
34
+ },
35
+ ],
36
+ details: {
37
+ title: note.title,
38
+ permalink: note.permalink,
39
+ file_path: note.file_path,
40
+ },
41
+ };
42
+ }
43
+ catch (err) {
44
+ if (err instanceof NoteAlreadyExistsError) {
45
+ const hint = [
46
+ `Note already exists: "${params.title}" (${err.permalink})`,
47
+ "",
48
+ "To update this note, use one of:",
49
+ ` - edit_note("${err.permalink}", operation="append", content="...")`,
50
+ ` - edit_note("${err.permalink}", operation="replace_section", section="...", content="...")`,
51
+ ` - write_note("${params.title}", ..., overwrite=true) to fully replace`,
52
+ ` - read_note("${err.permalink}") to inspect current content first`,
53
+ ].join("\n");
54
+ return {
55
+ content: [{ type: "text", text: hint }],
56
+ details: {
57
+ title: params.title,
58
+ permalink: err.permalink,
59
+ error: "note_already_exists",
60
+ },
61
+ };
62
+ }
63
+ log.error("write_note failed", err);
64
+ return {
65
+ content: [
66
+ {
67
+ type: "text",
68
+ text: "Failed to write note. Is Basic Memory running? Check logs for details.",
69
+ },
70
+ ],
71
+ details: {
72
+ title: params.title,
73
+ folder: params.folder,
74
+ error: "write_note_failed",
75
+ },
76
+ };
77
+ }
78
+ },
79
+ }, { name: "write_note" });
80
+ }
package/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { execSync } from "node:child_process"
2
2
 
3
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
3
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry"
4
4
  import { BmClient } from "./bm-client.ts"
5
5
  import { registerCli } from "./commands/cli.ts"
6
6
  import { registerSkillCommands } from "./commands/skills.ts"
@@ -33,15 +33,14 @@ import { registerWriteTool } from "./tools/write-note.ts"
33
33
 
34
34
  const BASIC_MEMORY_RELEASE_TAG = "v0.20.2"
35
35
 
36
- export default {
36
+ export default definePluginEntry({
37
37
  id: "openclaw-basic-memory",
38
38
  name: "Basic Memory",
39
39
  description:
40
40
  "Local-first knowledge graph for OpenClaw — persistent memory with graph search and composited memory_search",
41
- kind: "memory" as const,
42
41
  configSchema: basicMemoryConfigSchema,
43
42
 
44
- register(api: OpenClawPluginApi) {
43
+ register(api) {
45
44
  const cfg = parseConfig(api.pluginConfig)
46
45
 
47
46
  initLogger(api.logger, cfg.debug)
@@ -159,4 +158,4 @@ export default {
159
158
  },
160
159
  })
161
160
  },
162
- }
161
+ })
@@ -23,6 +23,7 @@
23
23
  "skills/memory-defrag",
24
24
  "skills/memory-ingest",
25
25
  "skills/memory-lifecycle",
26
+ "skills/memory-literary-analysis",
26
27
  "skills/memory-metadata-search",
27
28
  "skills/memory-notes",
28
29
  "skills/memory-reflect",
@@ -52,16 +53,26 @@
52
53
  "help": "Path to the basic-memory CLI binary (default: 'bm')",
53
54
  "advanced": true
54
55
  },
55
- "indexInterval": {
56
- "label": "Index Interval (seconds)",
57
- "placeholder": "300",
58
- "help": "Seconds between periodic re-indexing sweeps",
59
- "advanced": true
60
- },
61
56
  "autoCapture": {
62
57
  "label": "Auto-Capture",
63
58
  "help": "Automatically index conversation content after each turn"
64
59
  },
60
+ "captureMinChars": {
61
+ "label": "Capture Min Characters",
62
+ "placeholder": "10",
63
+ "help": "Minimum user/assistant text length before auto-capture indexes a turn",
64
+ "advanced": true
65
+ },
66
+ "autoRecall": {
67
+ "label": "Auto-Recall",
68
+ "help": "Automatically load relevant Basic Memory context when a session starts"
69
+ },
70
+ "recallPrompt": {
71
+ "label": "Recall Prompt",
72
+ "placeholder": "Check for active tasks and recent activity...",
73
+ "help": "Prompt used to gather initial Basic Memory context",
74
+ "advanced": true
75
+ },
65
76
  "debug": {
66
77
  "label": "Debug Logging",
67
78
  "help": "Enable verbose debug logs",
@@ -85,18 +96,27 @@
85
96
  "properties": {
86
97
  "project": { "type": "string" },
87
98
  "memoryDir": { "type": "string" },
99
+ "memory_dir": { "type": "string" },
88
100
  "memoryFile": { "type": "string" },
101
+ "memory_file": { "type": "string" },
89
102
  "bmPath": { "type": "string" },
90
- "indexInterval": { "type": "number", "minimum": 30, "maximum": 3600 },
91
103
  "autoCapture": { "type": "boolean" },
104
+ "captureMinChars": { "type": "number", "minimum": 0 },
105
+ "capture_min_chars": { "type": "number", "minimum": 0 },
106
+ "autoRecall": { "type": "boolean" },
107
+ "auto_recall": { "type": "boolean" },
108
+ "recallPrompt": { "type": "string" },
109
+ "recall_prompt": { "type": "string" },
92
110
  "debug": { "type": "boolean" },
93
111
  "projectPath": { "type": "string" },
94
112
  "cloud": {
95
113
  "type": "object",
114
+ "additionalProperties": false,
96
115
  "properties": {
97
116
  "url": { "type": "string" },
98
117
  "api_key": { "type": "string" }
99
- }
118
+ },
119
+ "required": ["url", "api_key"]
100
120
  }
101
121
  },
102
122
  "required": []
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "@basicmemory/openclaw-basic-memory",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
5
7
  "description": "Basic Memory plugin for OpenClaw — local-first knowledge graph for agent memory",
6
8
  "license": "MIT",
7
9
  "repository": {
@@ -11,7 +13,7 @@
11
13
  "files": [
12
14
  "index.ts",
13
15
  "bm-client.ts",
14
- "context-engine/",
16
+ "context-engine/basic-memory-context-engine.ts",
15
17
  "config.ts",
16
18
  "logger.ts",
17
19
  "commands/cli.ts",
@@ -35,6 +37,7 @@
35
37
  "schema/task-schema.ts",
36
38
  "schema/conversation-schema.ts",
37
39
  "skills/",
40
+ "dist/",
38
41
  "scripts/fetch-skills.ts",
39
42
  "scripts/setup-bm.sh",
40
43
  "openclaw.plugin.json",
@@ -53,25 +56,40 @@
53
56
  },
54
57
  "scripts": {
55
58
  "postinstall": "bash scripts/setup-bm.sh || true",
59
+ "build": "tsc -p tsconfig.build.json",
56
60
  "check-types": "tsc --noEmit",
57
61
  "lint": "bunx @biomejs/biome ci .",
58
62
  "lint:fix": "bunx @biomejs/biome check --write .",
59
63
  "fetch-skills": "bun scripts/fetch-skills.ts",
60
- "prepack": "bun scripts/fetch-skills.ts",
64
+ "prepack": "bun run fetch-skills && bun run build",
61
65
  "test": "bun test",
62
66
  "test:int": "BM_INTEGRATION=1 BM_BIN=${BM_BIN:-./scripts/bm-local.sh} bun test integration --timeout 120000",
63
67
  "test:coverage": "bun test --coverage",
64
- "release:check": "bun run check-types && bun test && npm pack --dry-run"
68
+ "release:check": "bun run check-types && bun run build && bun test && npm pack --dry-run"
65
69
  },
66
70
  "openclaw": {
67
71
  "extensions": [
68
72
  "./index.ts"
69
- ]
73
+ ],
74
+ "runtimeExtensions": [
75
+ "./dist/index.js"
76
+ ],
77
+ "compat": {
78
+ "pluginApi": ">=2026.5.2",
79
+ "minGatewayVersion": "2026.5.2"
80
+ },
81
+ "build": {
82
+ "openclawVersion": "2026.5.4",
83
+ "pluginSdkVersion": "2026.5.4"
84
+ },
85
+ "install": {
86
+ "minHostVersion": ">=2026.5.2"
87
+ }
70
88
  },
71
89
  "devDependencies": {
72
90
  "@biomejs/biome": "^2.4.6",
73
91
  "@types/node": "^20.0.0",
74
- "openclaw": "^2026.3.8",
92
+ "openclaw": "^2026.5.4",
75
93
  "typescript": "^5.9.3"
76
94
  }
77
95
  }
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient, ProjectListResult } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient, WorkspaceResult } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,7 +1,7 @@
1
1
  import { readdir, readFile } from "node:fs/promises"
2
2
  import { join, resolve } from "node:path"
3
3
  import { Type } from "@sinclair/typebox"
4
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
4
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
5
5
  import type { BmClient } from "../bm-client.ts"
6
6
  import type { BasicMemoryConfig } from "../config.ts"
7
7
  import { log } from "../logger.ts"
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { log } from "../logger.ts"
5
5
 
@@ -26,10 +26,14 @@ export function registerSearchTool(
26
26
  }),
27
27
  ),
28
28
  metadata_filters: Type.Optional(
29
- Type.Record(Type.String(), Type.Unknown(), {
30
- description:
31
- "Filter by frontmatter fields. Supports equality, $in, $gt/$gte/$lt/$lte, $between, and array-contains operators.",
32
- }),
29
+ Type.Object(
30
+ {},
31
+ {
32
+ additionalProperties: true,
33
+ description:
34
+ "Filter by frontmatter fields. Supports equality, $in, $gt/$gte/$lt/$lte, $between, and array-contains operators.",
35
+ },
36
+ ),
33
37
  ),
34
38
  tags: Type.Optional(
35
39
  Type.Array(Type.String(), {
@@ -1,5 +1,5 @@
1
1
  import { Type } from "@sinclair/typebox"
2
- import type { OpenClawPluginApi } from "openclaw/plugin-sdk"
2
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
3
3
  import type { BmClient } from "../bm-client.ts"
4
4
  import { NoteAlreadyExistsError } from "../bm-client.ts"
5
5
  import { log } from "../logger.ts"