@basicmemory/openclaw-basic-memory 0.2.4 → 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.
- package/README.md +11 -1
- package/bm-client.ts +55 -21
- package/commands/cli.ts +0 -1
- package/commands/skills.ts +51 -2
- package/config.ts +0 -17
- package/context-engine/basic-memory-context-engine.ts +25 -74
- package/dist/bm-client.d.ts +2 -0
- package/dist/bm-client.js +42 -32
- package/dist/commands/cli.js +0 -1
- package/dist/commands/skills.js +41 -2
- package/dist/config.d.ts +0 -5
- package/dist/config.js +0 -10
- package/dist/context-engine/basic-memory-context-engine.d.ts +13 -73
- package/dist/index.d.ts +2 -1
- package/dist/index.js +21 -11
- package/dist/tools/list-memory-projects.js +2 -1
- package/index.ts +23 -12
- package/openclaw.plugin.json +2 -15
- package/package.json +5 -4
- package/scripts/fetch-skills.ts +62 -67
- package/scripts/setup-bm.sh +27 -10
- package/skills/manifest.json +25 -0
- package/skills/memory-capture/SKILL.md +275 -0
- package/skills/memory-ci-capture/SKILL.md +56 -0
- package/skills/memory-continue/SKILL.md +148 -0
- package/skills/memory-curate/SKILL.md +243 -0
- package/skills/memory-literary-analysis/SKILL.md +15 -12
- package/skills/memory-notes/SKILL.md +22 -6
- package/skills/memory-onboarding/SKILL.md +142 -0
- package/skills/memory-onboarding/evals/evals.json +29 -0
- package/skills/memory-onboarding/references/assistant-setup.md +64 -0
- package/skills/memory-onboarding/references/conventions.md +118 -0
- package/skills/memory-onboarding/references/domain-playbooks.md +159 -0
- package/skills/memory-onboarding/references/schema-guide.md +136 -0
- package/skills/memory-schema/SKILL.md +7 -5
- package/skills/memory-tasks/SKILL.md +1 -1
- package/tools/list-memory-projects.ts +2 -1
package/README.md
CHANGED
|
@@ -18,6 +18,14 @@ Over time, your agent builds a knowledge base that grows with you. Context that
|
|
|
18
18
|
|
|
19
19
|
Learn more: [basicmemory.com](https://basicmemory.com) · [GitHub](https://github.com/basicmachines-co/basic-memory) · [Docs](https://docs.basicmemory.com)
|
|
20
20
|
|
|
21
|
+
Source now lives in the canonical [`basic-memory`](https://github.com/basicmachines-co/basic-memory) repository under `integrations/openclaw/`. The npm package remains `@basicmemory/openclaw-basic-memory`.
|
|
22
|
+
|
|
23
|
+
Maintainer check from the monorepo root:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
just package-check-openclaw
|
|
27
|
+
```
|
|
28
|
+
|
|
21
29
|
## What this plugin does
|
|
22
30
|
|
|
23
31
|
This plugin connects Basic Memory to OpenClaw so your agent can:
|
|
@@ -207,6 +215,8 @@ Ten skills ship with the plugin — no installation needed:
|
|
|
207
215
|
bun run fetch-skills
|
|
208
216
|
```
|
|
209
217
|
|
|
218
|
+
In the monorepo, this copies from the canonical top-level [`skills/`](../../skills) directory into the generated `integrations/openclaw/skills/` package bundle.
|
|
219
|
+
|
|
210
220
|
## Task notes
|
|
211
221
|
|
|
212
222
|
The plugin works well with structured task notes in `memory/tasks/`:
|
|
@@ -258,7 +268,7 @@ Cloud extends local-first — still plain Markdown, still yours. [Start a free t
|
|
|
258
268
|
- [Security](./SECURITY.md) — how auto-installation and data handling work
|
|
259
269
|
- [Development](./DEVELOPMENT.md) — contributing, tests, publishing
|
|
260
270
|
- [Basic Memory docs](https://docs.basicmemory.com)
|
|
261
|
-
- [Issues](https://github.com/basicmachines-co/
|
|
271
|
+
- [Issues](https://github.com/basicmachines-co/basic-memory/issues)
|
|
262
272
|
|
|
263
273
|
## Telemetry
|
|
264
274
|
|
package/bm-client.ts
CHANGED
|
@@ -100,6 +100,7 @@ export interface ProjectListResult {
|
|
|
100
100
|
is_default?: boolean
|
|
101
101
|
isDefault?: boolean
|
|
102
102
|
workspace_name?: string | null
|
|
103
|
+
workspace_slug?: string | null
|
|
103
104
|
workspace_type?: string | null
|
|
104
105
|
workspace_tenant_id?: string | null
|
|
105
106
|
}
|
|
@@ -198,7 +199,7 @@ function isRecoverableConnectionError(err: unknown): boolean {
|
|
|
198
199
|
)
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
function
|
|
202
|
+
function isNoteNotFoundError(err: unknown): boolean {
|
|
202
203
|
const msg = getErrorMessage(err).toLowerCase()
|
|
203
204
|
return (
|
|
204
205
|
msg.includes("entity not found") ||
|
|
@@ -213,6 +214,22 @@ function asString(value: unknown): string | null {
|
|
|
213
214
|
return typeof value === "string" ? value : null
|
|
214
215
|
}
|
|
215
216
|
|
|
217
|
+
function projectMatchesWorkspace(
|
|
218
|
+
project: ProjectListResult,
|
|
219
|
+
workspace: string,
|
|
220
|
+
): boolean {
|
|
221
|
+
const requested = workspace.trim().toLowerCase()
|
|
222
|
+
if (!requested) return true
|
|
223
|
+
|
|
224
|
+
return [
|
|
225
|
+
project.workspace_name,
|
|
226
|
+
project.workspace_slug,
|
|
227
|
+
project.workspace_tenant_id,
|
|
228
|
+
].some(
|
|
229
|
+
(value) => typeof value === "string" && value.toLowerCase() === requested,
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
|
|
216
233
|
export class BmClient {
|
|
217
234
|
private bmPath: string
|
|
218
235
|
private project: string
|
|
@@ -465,6 +482,10 @@ export class BmClient {
|
|
|
465
482
|
return structuredPayload
|
|
466
483
|
}
|
|
467
484
|
|
|
485
|
+
private routedProject(project?: string): string {
|
|
486
|
+
return project ?? this.project
|
|
487
|
+
}
|
|
488
|
+
|
|
468
489
|
async ensureProject(projectPath: string): Promise<void> {
|
|
469
490
|
const payload = await this.callTool("create_memory_project", {
|
|
470
491
|
project_name: this.project,
|
|
@@ -491,13 +512,18 @@ export class BmClient {
|
|
|
491
512
|
}
|
|
492
513
|
|
|
493
514
|
async listProjects(workspace?: string): Promise<ProjectListResult[]> {
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const payload = await this.callTool("list_memory_projects", args)
|
|
515
|
+
const payload = await this.callTool("list_memory_projects", {
|
|
516
|
+
output_format: "json",
|
|
517
|
+
})
|
|
498
518
|
|
|
499
519
|
if (isRecord(payload) && Array.isArray(payload.projects)) {
|
|
500
|
-
|
|
520
|
+
const projects = payload.projects as ProjectListResult[]
|
|
521
|
+
if (workspace) {
|
|
522
|
+
return projects.filter((project) =>
|
|
523
|
+
projectMatchesWorkspace(project, workspace),
|
|
524
|
+
)
|
|
525
|
+
}
|
|
526
|
+
return projects
|
|
501
527
|
}
|
|
502
528
|
|
|
503
529
|
throw new Error("invalid list_memory_projects response")
|
|
@@ -519,9 +545,9 @@ export class BmClient {
|
|
|
519
545
|
page: 1,
|
|
520
546
|
page_size: limit,
|
|
521
547
|
output_format: "json",
|
|
548
|
+
project: this.routedProject(project),
|
|
522
549
|
}
|
|
523
550
|
if (query) args.query = query
|
|
524
|
-
if (project) args.project = project
|
|
525
551
|
if (metadata?.filters) args.metadata_filters = metadata.filters
|
|
526
552
|
if (metadata?.tags) args.tags = metadata.tags
|
|
527
553
|
if (metadata?.status) args.status = metadata.status
|
|
@@ -546,8 +572,8 @@ export class BmClient {
|
|
|
546
572
|
identifier,
|
|
547
573
|
include_frontmatter: options.includeFrontmatter === true,
|
|
548
574
|
output_format: "json",
|
|
575
|
+
project: this.routedProject(project),
|
|
549
576
|
}
|
|
550
|
-
if (project) args.project = project
|
|
551
577
|
|
|
552
578
|
const payload = await this.callTool("read_note", args)
|
|
553
579
|
|
|
@@ -585,8 +611,8 @@ export class BmClient {
|
|
|
585
611
|
content,
|
|
586
612
|
directory: folder,
|
|
587
613
|
output_format: "json",
|
|
614
|
+
project: this.routedProject(project),
|
|
588
615
|
}
|
|
589
|
-
if (project) args.project = project
|
|
590
616
|
if (overwrite !== undefined) args.overwrite = overwrite
|
|
591
617
|
|
|
592
618
|
const payload = await this.callTool("write_note", args)
|
|
@@ -632,8 +658,8 @@ export class BmClient {
|
|
|
632
658
|
url,
|
|
633
659
|
depth,
|
|
634
660
|
output_format: "json",
|
|
661
|
+
project: this.routedProject(project),
|
|
635
662
|
}
|
|
636
|
-
if (project) args.project = project
|
|
637
663
|
|
|
638
664
|
const payload = await this.callTool("build_context", args)
|
|
639
665
|
|
|
@@ -651,8 +677,8 @@ export class BmClient {
|
|
|
651
677
|
const args: Record<string, unknown> = {
|
|
652
678
|
timeframe,
|
|
653
679
|
output_format: "json",
|
|
680
|
+
project: this.routedProject(project),
|
|
654
681
|
}
|
|
655
|
-
if (project) args.project = project
|
|
656
682
|
|
|
657
683
|
const payload = await this.callTool("recent_activity", args)
|
|
658
684
|
|
|
@@ -675,12 +701,12 @@ export class BmClient {
|
|
|
675
701
|
operation,
|
|
676
702
|
content,
|
|
677
703
|
output_format: "json",
|
|
704
|
+
project: this.routedProject(project),
|
|
678
705
|
}
|
|
679
706
|
if (options.find_text) args.find_text = options.find_text
|
|
680
707
|
if (options.section) args.section = options.section
|
|
681
708
|
if (options.expected_replacements != null)
|
|
682
709
|
args.expected_replacements = options.expected_replacements
|
|
683
|
-
if (project) args.project = project
|
|
684
710
|
|
|
685
711
|
const payload = await this.callTool("edit_note", args)
|
|
686
712
|
|
|
@@ -712,8 +738,8 @@ export class BmClient {
|
|
|
712
738
|
const args: Record<string, unknown> = {
|
|
713
739
|
identifier,
|
|
714
740
|
output_format: "json",
|
|
741
|
+
project: this.routedProject(project),
|
|
715
742
|
}
|
|
716
|
-
if (project) args.project = project
|
|
717
743
|
|
|
718
744
|
const payload = await this.callTool("delete_note", args)
|
|
719
745
|
|
|
@@ -741,8 +767,8 @@ export class BmClient {
|
|
|
741
767
|
identifier,
|
|
742
768
|
destination_folder: newFolder,
|
|
743
769
|
output_format: "json",
|
|
770
|
+
project: this.routedProject(project),
|
|
744
771
|
}
|
|
745
|
-
if (project) args.project = project
|
|
746
772
|
|
|
747
773
|
const payload = await this.callTool("move_note", args)
|
|
748
774
|
|
|
@@ -770,10 +796,12 @@ export class BmClient {
|
|
|
770
796
|
identifier?: string,
|
|
771
797
|
project?: string,
|
|
772
798
|
): Promise<SchemaValidationResult> {
|
|
773
|
-
const args: Record<string, unknown> = {
|
|
799
|
+
const args: Record<string, unknown> = {
|
|
800
|
+
output_format: "json",
|
|
801
|
+
project: this.routedProject(project),
|
|
802
|
+
}
|
|
774
803
|
if (noteType) args.note_type = noteType
|
|
775
804
|
if (identifier) args.identifier = identifier
|
|
776
|
-
if (project) args.project = project
|
|
777
805
|
|
|
778
806
|
const payload = await this.callTool("schema_validate", args)
|
|
779
807
|
|
|
@@ -793,8 +821,8 @@ export class BmClient {
|
|
|
793
821
|
note_type: noteType,
|
|
794
822
|
threshold,
|
|
795
823
|
output_format: "json",
|
|
824
|
+
project: this.routedProject(project),
|
|
796
825
|
}
|
|
797
|
-
if (project) args.project = project
|
|
798
826
|
|
|
799
827
|
const payload = await this.callTool("schema_infer", args)
|
|
800
828
|
|
|
@@ -812,8 +840,8 @@ export class BmClient {
|
|
|
812
840
|
const args: Record<string, unknown> = {
|
|
813
841
|
note_type: noteType,
|
|
814
842
|
output_format: "json",
|
|
843
|
+
project: this.routedProject(project),
|
|
815
844
|
}
|
|
816
|
-
if (project) args.project = project
|
|
817
845
|
|
|
818
846
|
const payload = await this.callTool("schema_diff", args)
|
|
819
847
|
|
|
@@ -845,13 +873,19 @@ export class BmClient {
|
|
|
845
873
|
"---",
|
|
846
874
|
].join("\n")
|
|
847
875
|
|
|
848
|
-
// Try append first — if it fails for ANY reason, fall through to create
|
|
849
876
|
try {
|
|
850
877
|
await this.editNote(title, "append", entry)
|
|
851
878
|
log.debug(`appended conversation to: ${title}`)
|
|
852
879
|
return
|
|
853
880
|
} catch (err) {
|
|
854
|
-
|
|
881
|
+
if (!isNoteNotFoundError(err)) {
|
|
882
|
+
log.error(`conversation append failed: ${getErrorMessage(err)}`, err)
|
|
883
|
+
throw err
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
log.debug(
|
|
887
|
+
`conversation note missing, will create: ${getErrorMessage(err)}`,
|
|
888
|
+
)
|
|
855
889
|
}
|
|
856
890
|
|
|
857
891
|
// Create the note with frontmatter and first entry
|
|
@@ -868,7 +902,7 @@ export class BmClient {
|
|
|
868
902
|
].join("\n")
|
|
869
903
|
|
|
870
904
|
try {
|
|
871
|
-
await this.writeNote(title, content, "conversations"
|
|
905
|
+
await this.writeNote(title, content, "conversations")
|
|
872
906
|
log.debug(`created conversation note: ${title}`)
|
|
873
907
|
} catch (err) {
|
|
874
908
|
log.error("conversation index failed", err)
|
package/commands/cli.ts
CHANGED
|
@@ -167,7 +167,6 @@ export function registerCli(
|
|
|
167
167
|
console.log(`Memory dir: ${cfg.memoryDir}`)
|
|
168
168
|
console.log(`Memory file: ${cfg.memoryFile}`)
|
|
169
169
|
console.log(`Auto-capture: ${cfg.autoCapture}`)
|
|
170
|
-
console.log(`Cloud: ${cfg.cloud ? cfg.cloud.url : "disabled"}`)
|
|
171
170
|
console.log(`Debug: ${cfg.debug}`)
|
|
172
171
|
})
|
|
173
172
|
},
|
package/commands/skills.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs"
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs"
|
|
2
2
|
import { dirname, resolve } from "node:path"
|
|
3
3
|
import { fileURLToPath } from "node:url"
|
|
4
4
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry"
|
|
@@ -39,13 +39,62 @@ function loadSkill(skillsDir: string, dir: string): string {
|
|
|
39
39
|
return readFileSync(resolve(skillsDir, dir, "SKILL.md"), "utf-8")
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* List a skill's bundled resource files (references/, assets/, ...) so the
|
|
44
|
+
* command can tell the assistant where they live on disk. SKILL.md workflows
|
|
45
|
+
* reference these by relative path; without the mapping, bundled commands
|
|
46
|
+
* would direct the assistant to files it was never given. evals/ is excluded
|
|
47
|
+
* as test fixtures.
|
|
48
|
+
*/
|
|
49
|
+
function listResourceFiles(skillsDir: string, dir: string): string[] {
|
|
50
|
+
const root = resolve(skillsDir, dir)
|
|
51
|
+
const files: string[] = []
|
|
52
|
+
const walk = (rel: string) => {
|
|
53
|
+
for (const entry of readdirSync(resolve(root, rel), {
|
|
54
|
+
withFileTypes: true,
|
|
55
|
+
})) {
|
|
56
|
+
const relPath = rel ? `${rel}/${entry.name}` : entry.name
|
|
57
|
+
if (entry.isDirectory()) {
|
|
58
|
+
if (relPath !== "evals") walk(relPath)
|
|
59
|
+
} else if (relPath !== "SKILL.md") {
|
|
60
|
+
files.push(relPath)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
walk("")
|
|
65
|
+
return files.sort()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resourceSection(
|
|
69
|
+
skillsDir: string,
|
|
70
|
+
dir: string,
|
|
71
|
+
files: string[],
|
|
72
|
+
): string {
|
|
73
|
+
if (files.length === 0) return ""
|
|
74
|
+
const lines = files
|
|
75
|
+
.map((f) => `- \`${f}\` → ${resolve(skillsDir, dir, f)}`)
|
|
76
|
+
.join("\n")
|
|
77
|
+
return (
|
|
78
|
+
"\n\n## Bundled resource files\n\n" +
|
|
79
|
+
"This skill references companion files by relative path. They are installed at:\n\n" +
|
|
80
|
+
`${lines}\n\n` +
|
|
81
|
+
"When the workflow directs you to read one of these files, read it from the absolute path listed above."
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
42
85
|
export function registerSkillCommands(api: OpenClawPluginApi): void {
|
|
43
86
|
const skillsDir = resolveSkillsDir(api)
|
|
44
87
|
const manifest = loadManifest(skillsDir)
|
|
45
88
|
|
|
46
89
|
for (const entry of manifest) {
|
|
47
90
|
const commandName = entry.dir.replace(/^memory-/, "")
|
|
48
|
-
const content =
|
|
91
|
+
const content =
|
|
92
|
+
loadSkill(skillsDir, entry.dir) +
|
|
93
|
+
resourceSection(
|
|
94
|
+
skillsDir,
|
|
95
|
+
entry.dir,
|
|
96
|
+
listResourceFiles(skillsDir, entry.dir),
|
|
97
|
+
)
|
|
49
98
|
|
|
50
99
|
api.registerCommand({
|
|
51
100
|
name: commandName,
|
package/config.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { homedir, hostname } from "node:os"
|
|
2
2
|
import { isAbsolute, resolve } from "node:path"
|
|
3
3
|
|
|
4
|
-
export type CloudConfig = {
|
|
5
|
-
url: string
|
|
6
|
-
api_key: string
|
|
7
|
-
}
|
|
8
|
-
|
|
9
4
|
export type BasicMemoryConfig = {
|
|
10
5
|
project: string
|
|
11
6
|
bmPath: string
|
|
@@ -17,7 +12,6 @@ export type BasicMemoryConfig = {
|
|
|
17
12
|
autoRecall: boolean
|
|
18
13
|
recallPrompt: string
|
|
19
14
|
debug: boolean
|
|
20
|
-
cloud?: CloudConfig
|
|
21
15
|
}
|
|
22
16
|
|
|
23
17
|
const ALLOWED_KEYS = [
|
|
@@ -36,7 +30,6 @@ const ALLOWED_KEYS = [
|
|
|
36
30
|
"recallPrompt",
|
|
37
31
|
"recall_prompt",
|
|
38
32
|
"debug",
|
|
39
|
-
"cloud",
|
|
40
33
|
]
|
|
41
34
|
|
|
42
35
|
function assertAllowedKeys(
|
|
@@ -98,15 +91,6 @@ export function parseConfig(raw: unknown): BasicMemoryConfig {
|
|
|
98
91
|
? (cfg.memory_file as string)
|
|
99
92
|
: "MEMORY.md"
|
|
100
93
|
|
|
101
|
-
let cloud: CloudConfig | undefined
|
|
102
|
-
if (cfg.cloud && typeof cfg.cloud === "object" && !Array.isArray(cfg.cloud)) {
|
|
103
|
-
const c = cfg.cloud as Record<string, unknown>
|
|
104
|
-
assertAllowedKeys(c, ["url", "api_key"], "basic-memory cloud config")
|
|
105
|
-
if (typeof c.url === "string" && typeof c.api_key === "string") {
|
|
106
|
-
cloud = { url: c.url, api_key: c.api_key }
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
94
|
return {
|
|
111
95
|
project:
|
|
112
96
|
typeof cfg.project === "string" && cfg.project.length > 0
|
|
@@ -144,7 +128,6 @@ export function parseConfig(raw: unknown): BasicMemoryConfig {
|
|
|
144
128
|
? (cfg.recall_prompt as string)
|
|
145
129
|
: "Check for active tasks and recent activity. Summarize anything relevant to the current session.",
|
|
146
130
|
debug: typeof cfg.debug === "boolean" ? cfg.debug : false,
|
|
147
|
-
cloud,
|
|
148
131
|
}
|
|
149
132
|
}
|
|
150
133
|
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AssembleResult,
|
|
3
|
+
BootstrapResult,
|
|
4
|
+
CompactResult,
|
|
5
|
+
ContextEngine,
|
|
6
|
+
SubagentSpawnPreparation,
|
|
7
|
+
} from "openclaw/plugin-sdk"
|
|
2
8
|
import { delegateCompactionToRuntime } from "openclaw/plugin-sdk/core"
|
|
3
9
|
import type { BmClient } from "../bm-client.ts"
|
|
4
10
|
import type { BasicMemoryConfig } from "../config.ts"
|
|
@@ -11,41 +17,16 @@ const TRUNCATED_RECALL_SUFFIX = "\n\n[Basic Memory recall truncated]"
|
|
|
11
17
|
const SUBAGENT_HANDOFF_FOLDER = "agent/subagents"
|
|
12
18
|
const MAX_SUBAGENT_RECALL_CHARS = 800
|
|
13
19
|
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
type CompactResult = {
|
|
27
|
-
ok: boolean
|
|
28
|
-
compacted: boolean
|
|
29
|
-
reason?: string
|
|
30
|
-
result?: {
|
|
31
|
-
summary?: string
|
|
32
|
-
firstKeptEntryId?: string
|
|
33
|
-
tokensBefore: number
|
|
34
|
-
tokensAfter?: number
|
|
35
|
-
details?: unknown
|
|
36
|
-
sessionId?: string
|
|
37
|
-
sessionFile?: string
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface ContextEngine {
|
|
42
|
-
readonly info: {
|
|
43
|
-
id: string
|
|
44
|
-
name: string
|
|
45
|
-
version?: string
|
|
46
|
-
ownsCompaction?: boolean
|
|
47
|
-
}
|
|
48
|
-
}
|
|
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]
|
|
49
30
|
|
|
50
31
|
interface SessionMemoryState {
|
|
51
32
|
recallContext: string
|
|
@@ -147,10 +128,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
|
|
|
147
128
|
private readonly cfg: BasicMemoryConfig,
|
|
148
129
|
) {}
|
|
149
130
|
|
|
150
|
-
async bootstrap(params: {
|
|
151
|
-
sessionId: string
|
|
152
|
-
sessionFile: string
|
|
153
|
-
}): Promise<BootstrapResult> {
|
|
131
|
+
async bootstrap(params: BootstrapParams): Promise<BootstrapResult> {
|
|
154
132
|
if (!this.cfg.autoRecall) {
|
|
155
133
|
this.sessionState.delete(params.sessionId)
|
|
156
134
|
return { bootstrapped: false, reason: "autoRecall disabled" }
|
|
@@ -183,11 +161,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
|
|
|
183
161
|
return { ingested: false }
|
|
184
162
|
}
|
|
185
163
|
|
|
186
|
-
async assemble(params: {
|
|
187
|
-
sessionId: string
|
|
188
|
-
messages: AgentMessage[]
|
|
189
|
-
tokenBudget?: number
|
|
190
|
-
}): Promise<AssembleResult> {
|
|
164
|
+
async assemble(params: AssembleParams): Promise<AssembleResult> {
|
|
191
165
|
const state = this.sessionState.get(params.sessionId)
|
|
192
166
|
|
|
193
167
|
return {
|
|
@@ -197,16 +171,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
|
|
|
197
171
|
}
|
|
198
172
|
}
|
|
199
173
|
|
|
200
|
-
async afterTurn(params: {
|
|
201
|
-
sessionId: string
|
|
202
|
-
sessionFile: string
|
|
203
|
-
messages: AgentMessage[]
|
|
204
|
-
prePromptMessageCount: number
|
|
205
|
-
autoCompactionSummary?: string
|
|
206
|
-
isHeartbeat?: boolean
|
|
207
|
-
tokenBudget?: number
|
|
208
|
-
runtimeContext?: Record<string, unknown>
|
|
209
|
-
}): Promise<void> {
|
|
174
|
+
async afterTurn(params: AfterTurnParams): Promise<void> {
|
|
210
175
|
if (!this.cfg.autoCapture) return
|
|
211
176
|
|
|
212
177
|
const newMessages = params.messages.slice(params.prePromptMessageCount)
|
|
@@ -227,24 +192,13 @@ export class BasicMemoryContextEngine implements ContextEngine {
|
|
|
227
192
|
}
|
|
228
193
|
}
|
|
229
194
|
|
|
230
|
-
async compact(params: {
|
|
231
|
-
sessionId: string
|
|
232
|
-
sessionFile: string
|
|
233
|
-
tokenBudget?: number
|
|
234
|
-
force?: boolean
|
|
235
|
-
currentTokenCount?: number
|
|
236
|
-
compactionTarget?: "budget" | "threshold"
|
|
237
|
-
customInstructions?: string
|
|
238
|
-
runtimeContext?: Record<string, unknown>
|
|
239
|
-
}): Promise<CompactResult> {
|
|
195
|
+
async compact(params: CompactParams): Promise<CompactResult> {
|
|
240
196
|
return delegateCompactionToRuntime(params)
|
|
241
197
|
}
|
|
242
198
|
|
|
243
|
-
async prepareSubagentSpawn(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
ttlMs?: number
|
|
247
|
-
}): Promise<{ rollback: () => Promise<void> } | undefined> {
|
|
199
|
+
async prepareSubagentSpawn(
|
|
200
|
+
params: PrepareSubagentSpawnParams,
|
|
201
|
+
): Promise<SubagentSpawnPreparation | undefined> {
|
|
248
202
|
const parentState = this.sessionState.get(params.parentSessionKey)
|
|
249
203
|
const noteTitle = buildSubagentNoteTitle(params.childSessionKey)
|
|
250
204
|
|
|
@@ -284,10 +238,7 @@ export class BasicMemoryContextEngine implements ContextEngine {
|
|
|
284
238
|
}
|
|
285
239
|
}
|
|
286
240
|
|
|
287
|
-
async onSubagentEnded(params: {
|
|
288
|
-
childSessionKey: string
|
|
289
|
-
reason: "deleted" | "completed" | "swept" | "released"
|
|
290
|
-
}): Promise<void> {
|
|
241
|
+
async onSubagentEnded(params: OnSubagentEndedParams): Promise<void> {
|
|
291
242
|
const handoff = this.subagentState.get(params.childSessionKey)
|
|
292
243
|
if (!handoff) return
|
|
293
244
|
|
package/dist/bm-client.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export interface ProjectListResult {
|
|
|
64
64
|
is_default?: boolean;
|
|
65
65
|
isDefault?: boolean;
|
|
66
66
|
workspace_name?: string | null;
|
|
67
|
+
workspace_slug?: string | null;
|
|
67
68
|
workspace_type?: string | null;
|
|
68
69
|
workspace_tenant_id?: string | null;
|
|
69
70
|
}
|
|
@@ -147,6 +148,7 @@ export declare class BmClient {
|
|
|
147
148
|
private disconnectCurrent;
|
|
148
149
|
private callToolRaw;
|
|
149
150
|
private callTool;
|
|
151
|
+
private routedProject;
|
|
150
152
|
ensureProject(projectPath: string): Promise<void>;
|
|
151
153
|
listWorkspaces(): Promise<WorkspaceResult[]>;
|
|
152
154
|
listProjects(workspace?: string): Promise<ProjectListResult[]>;
|