@basicmemory/openclaw-basic-memory 0.2.3 → 0.23.0

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 (91) hide show
  1. package/README.md +49 -19
  2. package/bm-client.ts +55 -21
  3. package/commands/cli.ts +1 -2
  4. package/commands/skills.ts +71 -10
  5. package/commands/slash.ts +4 -2
  6. package/config.ts +0 -16
  7. package/context-engine/basic-memory-context-engine.ts +22 -90
  8. package/dist/bm-client.d.ts +179 -0
  9. package/dist/bm-client.js +582 -0
  10. package/dist/commands/cli.d.ts +4 -0
  11. package/dist/commands/cli.js +116 -0
  12. package/dist/commands/skills.d.ts +2 -0
  13. package/dist/commands/skills.js +86 -0
  14. package/dist/commands/slash.d.ts +3 -0
  15. package/dist/commands/slash.js +92 -0
  16. package/dist/config.d.ts +17 -0
  17. package/dist/config.js +99 -0
  18. package/dist/context-engine/basic-memory-context-engine.d.ts +34 -0
  19. package/dist/context-engine/basic-memory-context-engine.js +176 -0
  20. package/dist/hooks/capture.d.ts +24 -0
  21. package/dist/hooks/capture.js +88 -0
  22. package/dist/hooks/recall.d.ts +24 -0
  23. package/dist/hooks/recall.js +56 -0
  24. package/dist/index.d.ts +9 -0
  25. package/dist/index.js +135 -0
  26. package/dist/logger.d.ts +13 -0
  27. package/dist/logger.js +34 -0
  28. package/dist/schema/conversation-schema.d.ts +5 -0
  29. package/dist/schema/conversation-schema.js +33 -0
  30. package/dist/schema/task-schema.d.ts +5 -0
  31. package/dist/schema/task-schema.js +34 -0
  32. package/dist/tools/build-context.d.ts +3 -0
  33. package/dist/tools/build-context.js +100 -0
  34. package/dist/tools/delete-note.d.ts +3 -0
  35. package/dist/tools/delete-note.js +52 -0
  36. package/dist/tools/edit-note.d.ts +3 -0
  37. package/dist/tools/edit-note.js +81 -0
  38. package/dist/tools/list-memory-projects.d.ts +3 -0
  39. package/dist/tools/list-memory-projects.js +86 -0
  40. package/dist/tools/list-workspaces.d.ts +3 -0
  41. package/dist/tools/list-workspaces.js +64 -0
  42. package/dist/tools/memory-provider.d.ts +15 -0
  43. package/dist/tools/memory-provider.js +274 -0
  44. package/dist/tools/move-note.d.ts +3 -0
  45. package/dist/tools/move-note.js +56 -0
  46. package/dist/tools/read-note.d.ts +3 -0
  47. package/dist/tools/read-note.js +57 -0
  48. package/dist/tools/schema-diff.d.ts +3 -0
  49. package/dist/tools/schema-diff.js +81 -0
  50. package/dist/tools/schema-infer.d.ts +3 -0
  51. package/dist/tools/schema-infer.js +66 -0
  52. package/dist/tools/schema-validate.d.ts +3 -0
  53. package/dist/tools/schema-validate.js +73 -0
  54. package/dist/tools/search-notes.d.ts +3 -0
  55. package/dist/tools/search-notes.js +97 -0
  56. package/dist/tools/write-note.d.ts +3 -0
  57. package/dist/tools/write-note.js +80 -0
  58. package/index.ts +27 -17
  59. package/openclaw.plugin.json +27 -20
  60. package/package.json +27 -8
  61. package/scripts/fetch-skills.ts +62 -67
  62. package/scripts/setup-bm.sh +27 -10
  63. package/skills/manifest.json +25 -0
  64. package/skills/memory-capture/SKILL.md +275 -0
  65. package/skills/memory-ci-capture/SKILL.md +56 -0
  66. package/skills/memory-continue/SKILL.md +148 -0
  67. package/skills/memory-curate/SKILL.md +243 -0
  68. package/skills/memory-literary-analysis/SKILL.md +15 -12
  69. package/skills/memory-notes/SKILL.md +22 -6
  70. package/skills/memory-onboarding/SKILL.md +142 -0
  71. package/skills/memory-onboarding/evals/evals.json +29 -0
  72. package/skills/memory-onboarding/references/assistant-setup.md +64 -0
  73. package/skills/memory-onboarding/references/conventions.md +118 -0
  74. package/skills/memory-onboarding/references/domain-playbooks.md +159 -0
  75. package/skills/memory-onboarding/references/schema-guide.md +136 -0
  76. package/skills/memory-schema/SKILL.md +7 -5
  77. package/skills/memory-tasks/SKILL.md +1 -1
  78. package/tools/build-context.ts +1 -1
  79. package/tools/delete-note.ts +1 -1
  80. package/tools/edit-note.ts +1 -1
  81. package/tools/list-memory-projects.ts +3 -2
  82. package/tools/list-workspaces.ts +1 -1
  83. package/tools/memory-provider.ts +1 -1
  84. package/tools/move-note.ts +1 -1
  85. package/tools/read-note.ts +1 -1
  86. package/tools/schema-diff.ts +1 -1
  87. package/tools/schema-infer.ts +1 -1
  88. package/tools/schema-validate.ts +1 -1
  89. package/tools/search-notes.ts +1 -1
  90. package/tools/write-note.ts +1 -1
  91. package/context-engine/basic-memory-context-engine.test.ts +0 -398
@@ -1,25 +1,33 @@
1
- import { createRequire } from "node:module"
2
- import { dirname, resolve } from "node:path"
3
- import { pathToFileURL } from "node:url"
4
- import type { AgentMessage } from "@mariozechner/pi-agent-core"
5
1
  import type {
6
2
  AssembleResult,
7
3
  BootstrapResult,
8
4
  CompactResult,
9
5
  ContextEngine,
6
+ SubagentSpawnPreparation,
10
7
  } from "openclaw/plugin-sdk"
8
+ import { delegateCompactionToRuntime } from "openclaw/plugin-sdk/core"
11
9
  import type { BmClient } from "../bm-client.ts"
12
10
  import type { BasicMemoryConfig } from "../config.ts"
13
11
  import { selectCaptureTurn } from "../hooks/capture.ts"
14
12
  import { loadRecallState } from "../hooks/recall.ts"
15
13
  import { log } from "../logger.ts"
16
14
 
17
- const require = createRequire(import.meta.url)
18
15
  export const MAX_ASSEMBLE_RECALL_CHARS = 1200
19
16
  const TRUNCATED_RECALL_SUFFIX = "\n\n[Basic Memory recall truncated]"
20
17
  const SUBAGENT_HANDOFF_FOLDER = "agent/subagents"
21
18
  const MAX_SUBAGENT_RECALL_CHARS = 800
22
19
 
20
+ type BootstrapParams = Parameters<NonNullable<ContextEngine["bootstrap"]>>[0]
21
+ type AssembleParams = Parameters<ContextEngine["assemble"]>[0]
22
+ type AfterTurnParams = Parameters<NonNullable<ContextEngine["afterTurn"]>>[0]
23
+ type CompactParams = Parameters<ContextEngine["compact"]>[0]
24
+ type PrepareSubagentSpawnParams = Parameters<
25
+ NonNullable<ContextEngine["prepareSubagentSpawn"]>
26
+ >[0]
27
+ type OnSubagentEndedParams = Parameters<
28
+ NonNullable<ContextEngine["onSubagentEnded"]>
29
+ >[0]
30
+
23
31
  interface SessionMemoryState {
24
32
  recallContext: string
25
33
  }
@@ -104,36 +112,6 @@ function buildSubagentCompletionUpdate(params: {
104
112
  ].join("\n")
105
113
  }
106
114
 
107
- type LegacyContextEngineModule = {
108
- LegacyContextEngine: new () => {
109
- compact(params: {
110
- sessionId: string
111
- sessionFile: string
112
- tokenBudget?: number
113
- force?: boolean
114
- currentTokenCount?: number
115
- compactionTarget?: "budget" | "threshold"
116
- customInstructions?: string
117
- runtimeContext?: Record<string, unknown>
118
- }): Promise<CompactResult>
119
- }
120
- }
121
-
122
- async function loadLegacyContextEngine(): Promise<
123
- LegacyContextEngineModule["LegacyContextEngine"]
124
- > {
125
- const pluginSdkPath = require.resolve("openclaw/plugin-sdk")
126
- const legacyPath = resolve(
127
- dirname(pluginSdkPath),
128
- "context-engine",
129
- "legacy.js",
130
- )
131
- const module = (await import(
132
- pathToFileURL(legacyPath).href
133
- )) as LegacyContextEngineModule
134
- return module.LegacyContextEngine
135
- }
136
-
137
115
  export class BasicMemoryContextEngine implements ContextEngine {
138
116
  readonly info = {
139
117
  id: "openclaw-basic-memory",
@@ -144,19 +122,13 @@ export class BasicMemoryContextEngine implements ContextEngine {
144
122
 
145
123
  private readonly sessionState = new Map<string, SessionMemoryState>()
146
124
  private readonly subagentState = new Map<string, SubagentHandoffState>()
147
- private legacyContextEnginePromise: Promise<
148
- InstanceType<LegacyContextEngineModule["LegacyContextEngine"]>
149
- > | null = null
150
125
 
151
126
  constructor(
152
127
  private readonly client: BmClient,
153
128
  private readonly cfg: BasicMemoryConfig,
154
129
  ) {}
155
130
 
156
- async bootstrap(params: {
157
- sessionId: string
158
- sessionFile: string
159
- }): Promise<BootstrapResult> {
131
+ async bootstrap(params: BootstrapParams): Promise<BootstrapResult> {
160
132
  if (!this.cfg.autoRecall) {
161
133
  this.sessionState.delete(params.sessionId)
162
134
  return { bootstrapped: false, reason: "autoRecall disabled" }
@@ -189,11 +161,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
189
161
  return { ingested: false }
190
162
  }
191
163
 
192
- async assemble(params: {
193
- sessionId: string
194
- messages: AgentMessage[]
195
- tokenBudget?: number
196
- }): Promise<AssembleResult> {
164
+ async assemble(params: AssembleParams): Promise<AssembleResult> {
197
165
  const state = this.sessionState.get(params.sessionId)
198
166
 
199
167
  return {
@@ -203,16 +171,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
203
171
  }
204
172
  }
205
173
 
206
- async afterTurn(params: {
207
- sessionId: string
208
- sessionFile: string
209
- messages: AgentMessage[]
210
- prePromptMessageCount: number
211
- autoCompactionSummary?: string
212
- isHeartbeat?: boolean
213
- tokenBudget?: number
214
- runtimeContext?: Record<string, unknown>
215
- }): Promise<void> {
174
+ async afterTurn(params: AfterTurnParams): Promise<void> {
216
175
  if (!this.cfg.autoCapture) return
217
176
 
218
177
  const newMessages = params.messages.slice(params.prePromptMessageCount)
@@ -233,25 +192,13 @@ export class BasicMemoryContextEngine implements ContextEngine {
233
192
  }
234
193
  }
235
194
 
236
- async compact(params: {
237
- sessionId: string
238
- sessionFile: string
239
- tokenBudget?: number
240
- force?: boolean
241
- currentTokenCount?: number
242
- compactionTarget?: "budget" | "threshold"
243
- customInstructions?: string
244
- runtimeContext?: Record<string, unknown>
245
- }): Promise<CompactResult> {
246
- const legacy = await this.getLegacyContextEngine()
247
- return legacy.compact(params)
195
+ async compact(params: CompactParams): Promise<CompactResult> {
196
+ return delegateCompactionToRuntime(params)
248
197
  }
249
198
 
250
- async prepareSubagentSpawn(params: {
251
- parentSessionKey: string
252
- childSessionKey: string
253
- ttlMs?: number
254
- }): Promise<{ rollback: () => Promise<void> } | undefined> {
199
+ async prepareSubagentSpawn(
200
+ params: PrepareSubagentSpawnParams,
201
+ ): Promise<SubagentSpawnPreparation | undefined> {
255
202
  const parentState = this.sessionState.get(params.parentSessionKey)
256
203
  const noteTitle = buildSubagentNoteTitle(params.childSessionKey)
257
204
 
@@ -291,10 +238,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
291
238
  }
292
239
  }
293
240
 
294
- async onSubagentEnded(params: {
295
- childSessionKey: string
296
- reason: "deleted" | "completed" | "swept" | "released"
297
- }): Promise<void> {
241
+ async onSubagentEnded(params: OnSubagentEndedParams): Promise<void> {
298
242
  const handoff = this.subagentState.get(params.childSessionKey)
299
243
  if (!handoff) return
300
244
 
@@ -315,16 +259,4 @@ export class BasicMemoryContextEngine implements ContextEngine {
315
259
  this.sessionState.clear()
316
260
  this.subagentState.clear()
317
261
  }
318
-
319
- private async getLegacyContextEngine(): Promise<
320
- InstanceType<LegacyContextEngineModule["LegacyContextEngine"]>
321
- > {
322
- if (!this.legacyContextEnginePromise) {
323
- this.legacyContextEnginePromise = loadLegacyContextEngine().then(
324
- (LegacyContextEngine) => new LegacyContextEngine(),
325
- )
326
- }
327
-
328
- return this.legacyContextEnginePromise
329
- }
330
262
  }
@@ -0,0 +1,179 @@
1
+ export declare class NoteAlreadyExistsError extends Error {
2
+ readonly permalink: string;
3
+ constructor(title: string, permalink: string);
4
+ }
5
+ export interface SearchResult {
6
+ title: string;
7
+ permalink: string;
8
+ content: string;
9
+ score?: number;
10
+ file_path: string;
11
+ }
12
+ export interface NoteResult {
13
+ title: string;
14
+ permalink: string;
15
+ content: string;
16
+ file_path: string;
17
+ frontmatter?: Record<string, unknown> | null;
18
+ checksum?: string | null;
19
+ action?: "created" | "updated";
20
+ }
21
+ export interface EditNoteResult {
22
+ title: string;
23
+ permalink: string;
24
+ file_path: string;
25
+ operation: "append" | "prepend" | "find_replace" | "replace_section";
26
+ checksum?: string | null;
27
+ }
28
+ interface ReadNoteOptions {
29
+ includeFrontmatter?: boolean;
30
+ }
31
+ interface EditNoteOptions {
32
+ find_text?: string;
33
+ section?: string;
34
+ expected_replacements?: number;
35
+ }
36
+ export interface ContextResult {
37
+ results: Array<{
38
+ primary_result: NoteResult;
39
+ observations: Array<{
40
+ category: string;
41
+ content: string;
42
+ }>;
43
+ related_results: Array<{
44
+ type: "relation" | "entity";
45
+ title?: string;
46
+ permalink: string;
47
+ relation_type?: string;
48
+ from_entity?: string;
49
+ to_entity?: string;
50
+ }>;
51
+ }>;
52
+ }
53
+ export interface RecentResult {
54
+ title: string;
55
+ permalink: string;
56
+ file_path: string;
57
+ created_at: string;
58
+ }
59
+ export interface ProjectListResult {
60
+ name: string;
61
+ path: string;
62
+ display_name?: string | null;
63
+ is_private?: boolean;
64
+ is_default?: boolean;
65
+ isDefault?: boolean;
66
+ workspace_name?: string | null;
67
+ workspace_slug?: string | null;
68
+ workspace_type?: string | null;
69
+ workspace_tenant_id?: string | null;
70
+ }
71
+ export interface WorkspaceResult {
72
+ tenant_id: string;
73
+ name: string;
74
+ workspace_type: string;
75
+ role: string;
76
+ organization_id?: string | null;
77
+ has_active_subscription: boolean;
78
+ }
79
+ export interface SchemaValidationResult {
80
+ entity_type: string | null;
81
+ total_notes: number;
82
+ total_entities: number;
83
+ valid_count: number;
84
+ warning_count: number;
85
+ error_count: number;
86
+ results: Array<{
87
+ identifier: string;
88
+ valid: boolean;
89
+ warnings: string[];
90
+ errors: string[];
91
+ }>;
92
+ }
93
+ export interface SchemaInferResult {
94
+ entity_type: string;
95
+ notes_analyzed: number;
96
+ field_frequencies: Array<{
97
+ name: string;
98
+ percentage: number;
99
+ count: number;
100
+ total: number;
101
+ source: string;
102
+ sample_values?: string[];
103
+ is_array?: boolean;
104
+ target_type?: string | null;
105
+ }>;
106
+ suggested_schema: Record<string, unknown>;
107
+ suggested_required: string[];
108
+ suggested_optional: string[];
109
+ excluded: string[];
110
+ }
111
+ export interface SchemaDiffResult {
112
+ entity_type: string;
113
+ schema_found: boolean;
114
+ new_fields: Array<{
115
+ name: string;
116
+ source: string;
117
+ count: number;
118
+ total: number;
119
+ percentage: number;
120
+ }>;
121
+ dropped_fields: Array<{
122
+ name: string;
123
+ source: string;
124
+ declared_in?: string;
125
+ }>;
126
+ cardinality_changes: string[];
127
+ }
128
+ export declare class BmClient {
129
+ private bmPath;
130
+ private project;
131
+ private cwd?;
132
+ private env?;
133
+ private shouldRun;
134
+ private client;
135
+ private transport;
136
+ private connectPromise;
137
+ private retryDelaysMs;
138
+ constructor(bmPath: string, project: string);
139
+ start(options?: {
140
+ cwd?: string;
141
+ env?: Record<string, string>;
142
+ }): Promise<void>;
143
+ stop(): Promise<void>;
144
+ private connectWithRetries;
145
+ private ensureConnected;
146
+ private connectFresh;
147
+ private assertRequiredTools;
148
+ private disconnectCurrent;
149
+ private callToolRaw;
150
+ private callTool;
151
+ private routedProject;
152
+ ensureProject(projectPath: string): Promise<void>;
153
+ listWorkspaces(): Promise<WorkspaceResult[]>;
154
+ listProjects(workspace?: string): Promise<ProjectListResult[]>;
155
+ search(query?: string, limit?: number, project?: string, metadata?: {
156
+ filters?: Record<string, unknown>;
157
+ tags?: string[];
158
+ status?: string;
159
+ note_types?: string[];
160
+ entity_types?: string[];
161
+ }): Promise<SearchResult[]>;
162
+ readNote(identifier: string, options?: ReadNoteOptions, project?: string): Promise<NoteResult>;
163
+ writeNote(title: string, content: string, folder: string, project?: string, overwrite?: boolean): Promise<NoteResult>;
164
+ buildContext(url: string, depth?: number, project?: string): Promise<ContextResult>;
165
+ recentActivity(timeframe?: string, project?: string): Promise<RecentResult[]>;
166
+ editNote(identifier: string, operation: "append" | "prepend" | "find_replace" | "replace_section", content: string, options?: EditNoteOptions, project?: string): Promise<EditNoteResult>;
167
+ deleteNote(identifier: string, project?: string): Promise<{
168
+ title: string;
169
+ permalink: string;
170
+ file_path: string;
171
+ }>;
172
+ moveNote(identifier: string, newFolder: string, project?: string): Promise<NoteResult>;
173
+ schemaValidate(noteType?: string, identifier?: string, project?: string): Promise<SchemaValidationResult>;
174
+ schemaInfer(noteType: string, threshold?: number, project?: string): Promise<SchemaInferResult>;
175
+ schemaDiff(noteType: string, project?: string): Promise<SchemaDiffResult>;
176
+ indexConversation(userMessage: string, assistantResponse: string): Promise<void>;
177
+ getProject(): string;
178
+ }
179
+ export {};