@basicmemory/openclaw-basic-memory 0.1.1 → 0.1.3

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.
package/bm-client.ts CHANGED
@@ -7,7 +7,6 @@ const DEFAULT_RETRY_DELAYS_MS = [500, 1000, 2000]
7
7
 
8
8
  const REQUIRED_TOOLS = [
9
9
  "search_notes",
10
- "search_by_metadata",
11
10
  "read_note",
12
11
  "write_note",
13
12
  "edit_note",
@@ -153,12 +152,6 @@ export interface SchemaDiffResult {
153
152
  cardinality_changes: string[]
154
153
  }
155
154
 
156
- export interface MetadataSearchResult {
157
- results: SearchResult[]
158
- current_page: number
159
- page_size: number
160
- }
161
-
162
155
  function getErrorMessage(err: unknown): string {
163
156
  return err instanceof Error ? err.message : String(err)
164
157
  }
@@ -502,25 +495,29 @@ export class BmClient {
502
495
  }
503
496
 
504
497
  async search(
505
- query: string,
498
+ query?: string,
506
499
  limit = 10,
507
500
  project?: string,
508
501
  metadata?: {
509
502
  filters?: Record<string, unknown>
510
503
  tags?: string[]
511
504
  status?: string
505
+ note_types?: string[]
506
+ entity_types?: string[]
512
507
  },
513
508
  ): Promise<SearchResult[]> {
514
509
  const args: Record<string, unknown> = {
515
- query,
516
510
  page: 1,
517
511
  page_size: limit,
518
512
  output_format: "json",
519
513
  }
514
+ if (query) args.query = query
520
515
  if (project) args.project = project
521
516
  if (metadata?.filters) args.metadata_filters = metadata.filters
522
517
  if (metadata?.tags) args.tags = metadata.tags
523
518
  if (metadata?.status) args.status = metadata.status
519
+ if (metadata?.note_types) args.note_types = metadata.note_types
520
+ if (metadata?.entity_types) args.entity_types = metadata.entity_types
524
521
 
525
522
  const payload = await this.callTool("search_notes", args)
526
523
 
@@ -809,27 +806,6 @@ export class BmClient {
809
806
  return payload as unknown as SchemaDiffResult
810
807
  }
811
808
 
812
- async searchByMetadata(
813
- filters: Record<string, unknown>,
814
- limit = 20,
815
- project?: string,
816
- ): Promise<MetadataSearchResult> {
817
- const args: Record<string, unknown> = {
818
- filters,
819
- limit,
820
- output_format: "json",
821
- }
822
- if (project) args.project = project
823
-
824
- const payload = await this.callTool("search_by_metadata", args)
825
-
826
- if (!isRecord(payload) || !Array.isArray(payload.results)) {
827
- throw new Error("invalid search_by_metadata response")
828
- }
829
-
830
- return payload as unknown as MetadataSearchResult
831
- }
832
-
833
809
  async indexConversation(
834
810
  userMessage: string,
835
811
  assistantResponse: string,
package/hooks/recall.ts CHANGED
@@ -1,8 +1,4 @@
1
- import type {
2
- BmClient,
3
- MetadataSearchResult,
4
- RecentResult,
5
- } from "../bm-client.ts"
1
+ import type { BmClient, RecentResult, SearchResult } from "../bm-client.ts"
6
2
  import type { BasicMemoryConfig } from "../config.ts"
7
3
  import { log } from "../logger.ts"
8
4
 
@@ -11,14 +7,14 @@ import { log } from "../logger.ts"
11
7
  * Returns empty string if nothing was found.
12
8
  */
13
9
  export function formatRecallContext(
14
- tasks: MetadataSearchResult,
10
+ tasks: SearchResult[],
15
11
  recent: RecentResult[],
16
12
  prompt: string,
17
13
  ): string {
18
14
  const sections: string[] = []
19
15
 
20
- if (tasks.results.length > 0) {
21
- const taskLines = tasks.results.map((t) => {
16
+ if (tasks.length > 0) {
17
+ const taskLines = tasks.map((t) => {
22
18
  const preview =
23
19
  t.content.length > 120 ? `${t.content.slice(0, 120)}...` : t.content
24
20
  return `- **${t.title}** — ${preview}`
@@ -46,7 +42,10 @@ export function buildRecallHandler(client: BmClient, cfg: BasicMemoryConfig) {
46
42
  return async (_event: Record<string, unknown>) => {
47
43
  try {
48
44
  const [tasks, recent] = await Promise.all([
49
- client.searchByMetadata({ entity_type: "Task", status: "active" }, 5),
45
+ client.search(undefined, 5, undefined, {
46
+ note_types: ["Task"],
47
+ status: "active",
48
+ }),
50
49
  client.recentActivity("1d"),
51
50
  ])
52
51
 
@@ -54,7 +53,7 @@ export function buildRecallHandler(client: BmClient, cfg: BasicMemoryConfig) {
54
53
  if (!context) return {}
55
54
 
56
55
  log.debug(
57
- `recall: ${tasks.results.length} active tasks, ${recent.length} recent items`,
56
+ `recall: ${tasks.length} active tasks, ${recent.length} recent items`,
58
57
  )
59
58
 
60
59
  return { context }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basicmemory/openclaw-basic-memory",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "description": "Basic Memory plugin for OpenClaw — local-first knowledge graph for agent memory",
6
6
  "license": "MIT",
@@ -8,16 +8,16 @@ type: schema
8
8
  entity: Task
9
9
  version: 1
10
10
  schema:
11
- description: string, what needs to be done
12
- status?(enum): [active, blocked, done, abandoned], current state
13
- assigned_to?: string, who is working on this
14
- steps?(array): string, ordered steps to complete
15
- current_step?: integer, which step number we're on (1-indexed)
16
- context?: string, key context needed to resume after memory loss
17
- started?: string, when work began
18
- completed?: string, when work finished
19
- blockers?(array): string, what's preventing progress
20
- parent_task?: Task, parent task if this is a subtask
11
+ description: "string, what needs to be done"
12
+ status?(enum): "[active, blocked, done, abandoned], current state"
13
+ assigned_to?: "string, who is working on this"
14
+ steps?(array): "string, ordered steps to complete"
15
+ current_step?: "integer, which step number we're on (1-indexed)"
16
+ context?: "string, key context needed to resume after memory loss"
17
+ started?: "string, when work began"
18
+ completed?: "string, when work finished"
19
+ blockers?(array): "string, what's preventing progress"
20
+ parent_task?: "Task, parent task if this is a subtask"
21
21
  settings:
22
22
  validation: warn
23
23
  ---
@@ -60,8 +60,8 @@ async function searchMemoryFile(
60
60
 
61
61
  /**
62
62
  * Search for active tasks via BM knowledge graph.
63
- * Uses structured metadata filtering via search_by_metadata for precise querying.
64
- * Falls back to filesystem scan if metadata search fails.
63
+ * Uses search_notes with note_types and status filters for precise querying.
64
+ * Falls back to filesystem scan if search fails.
65
65
  */
66
66
  async function searchActiveTasks(
67
67
  query: string,
@@ -69,44 +69,29 @@ async function searchActiveTasks(
69
69
  workspaceDir: string,
70
70
  memoryDir: string,
71
71
  ): Promise<string> {
72
- // Try structured metadata search first
72
+ // Try structured search first
73
73
  try {
74
- const filters: Record<string, unknown> = { type: "task", status: "active" }
75
- const metaResults = await client.searchByMetadata(filters, 10)
76
-
77
- if (metaResults.results.length > 0) {
78
- // If the caller provided a query, filter results by keyword match
79
- const queryLower = query.toLowerCase()
80
- const terms = queryLower.split(/\s+/).filter((t) => t.length > 0)
81
-
82
- const filtered =
83
- terms.length > 0
84
- ? metaResults.results.filter((r) => {
85
- const text = `${r.title} ${r.content ?? ""}`.toLowerCase()
86
- return terms.some((term) => text.includes(term))
87
- })
88
- : metaResults.results
89
-
90
- if (filtered.length > 0) {
91
- const matches: string[] = []
92
- for (const r of filtered) {
93
- const score = r.score ? ` (${r.score.toFixed(2)})` : ""
94
- const preview =
95
- (r.content ?? "").length > 200
96
- ? `${(r.content ?? "").slice(0, 200)}…`
97
- : (r.content ?? "")
98
- matches.push(
99
- `- **${r.title}**${score} — ${r.file_path}\n > ${preview.replace(/\n/g, "\n > ")}`,
100
- )
101
- }
102
- return matches.join("\n\n")
74
+ const results = await client.search(query || undefined, 10, undefined, {
75
+ note_types: ["task"],
76
+ status: "active",
77
+ })
78
+
79
+ if (results.length > 0) {
80
+ const matches: string[] = []
81
+ for (const r of results) {
82
+ const score = r.score ? ` (${r.score.toFixed(2)})` : ""
83
+ const preview =
84
+ (r.content ?? "").length > 200
85
+ ? `${(r.content ?? "").slice(0, 200)}…`
86
+ : (r.content ?? "")
87
+ matches.push(
88
+ `- **${r.title}**${score} — ${r.file_path}\n > ${preview.replace(/\n/g, "\n > ")}`,
89
+ )
103
90
  }
91
+ return matches.join("\n\n")
104
92
  }
105
93
  } catch (err) {
106
- log.debug(
107
- "BM metadata task search failed, falling back to filesystem scan",
108
- err,
109
- )
94
+ log.debug("BM task search failed, falling back to filesystem scan", err)
110
95
  }
111
96
 
112
97
  // Fallback: filesystem scan for tasks not yet indexed