@botbotgo/agent-harness 0.0.281 → 0.0.283

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 (37) hide show
  1. package/README.md +20 -9
  2. package/README.zh.md +20 -9
  3. package/dist/config/catalogs/stores.yaml +1 -1
  4. package/dist/config/catalogs/vector-stores.yaml +1 -1
  5. package/dist/config/knowledge/knowledge-runtime.yaml +60 -0
  6. package/dist/config/runtime/runtime-memory.yaml +3 -3
  7. package/dist/contracts/runtime.d.ts +9 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +1 -0
  10. package/dist/init-project.js +50 -4
  11. package/dist/knowledge/config.d.ts +11 -0
  12. package/dist/knowledge/config.js +32 -0
  13. package/dist/knowledge/contracts.d.ts +45 -0
  14. package/dist/knowledge/contracts.js +1 -0
  15. package/dist/knowledge/index.d.ts +4 -0
  16. package/dist/knowledge/index.js +2 -0
  17. package/dist/knowledge/module.d.ts +21 -0
  18. package/dist/knowledge/module.js +594 -0
  19. package/dist/package-version.d.ts +1 -1
  20. package/dist/package-version.js +1 -1
  21. package/dist/persistence/file-store.d.ts +1 -0
  22. package/dist/persistence/file-store.js +29 -25
  23. package/dist/persistence/sqlite-store.js +1 -1
  24. package/dist/runtime/harness/run/resources.js +4 -2
  25. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -1
  26. package/dist/runtime/harness/system/runtime-memory-records.js +4 -0
  27. package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
  28. package/dist/runtime/harness/system/thread-memory-sync.js +1 -1
  29. package/dist/runtime/harness.d.ts +1 -16
  30. package/dist/runtime/harness.js +95 -613
  31. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -1
  32. package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -1
  33. package/dist/runtime/support/llamaindex.js +1 -1
  34. package/dist/runtime/support/runtime-factories.js +6 -3
  35. package/dist/runtime/support/runtime-layout.d.ts +6 -0
  36. package/dist/runtime/support/runtime-layout.js +19 -0
  37. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { appendFile, readFile, readdir, rm, writeFile } from "node:fs/promises";
3
3
  import { ensureDir, fileExists, readJson, writeJson } from "../utils/fs.js";
4
+ import { resolveRuntimeArtifactsRoot } from "../runtime/support/runtime-layout.js";
4
5
  function nowIso() {
5
6
  return new Date(Date.now()).toISOString();
6
7
  }
@@ -9,39 +10,42 @@ export class FilePersistence {
9
10
  constructor(runRoot) {
10
11
  this.runRoot = runRoot;
11
12
  }
13
+ artifactsRoot() {
14
+ return resolveRuntimeArtifactsRoot(this.runRoot);
15
+ }
12
16
  threadIndexPath(threadId) {
13
- return path.join(this.runRoot, "indexes", "threads", `${threadId}.json`);
17
+ return path.join(this.artifactsRoot(), "indexes", "sessions", `${threadId}.json`);
14
18
  }
15
19
  runIndexPath(runId) {
16
- return path.join(this.runRoot, "indexes", "runs", `${runId}.json`);
20
+ return path.join(this.artifactsRoot(), "indexes", "requests", `${runId}.json`);
17
21
  }
18
22
  approvalIndexPath(approvalId) {
19
- return path.join(this.runRoot, "indexes", "approvals", `${approvalId}.json`);
23
+ return path.join(this.artifactsRoot(), "indexes", "approvals", `${approvalId}.json`);
20
24
  }
21
25
  runQueuePath(runId) {
22
- return path.join(this.runRoot, "indexes", "queue", `${runId}.json`);
26
+ return path.join(this.artifactsRoot(), "indexes", "requests-queue", `${runId}.json`);
23
27
  }
24
28
  runControlPath(runId) {
25
- return path.join(this.runRoot, "indexes", "run-control", `${runId}.json`);
29
+ return path.join(this.artifactsRoot(), "indexes", "requests-control", `${runId}.json`);
26
30
  }
27
31
  traceItemsPath(threadId, runId) {
28
32
  return path.join(this.runDir(threadId, runId), "trace-items.ndjson");
29
33
  }
30
34
  async initialize() {
31
35
  await Promise.all([
32
- "indexes/threads",
33
- "indexes/runs",
36
+ "indexes/sessions",
37
+ "indexes/requests",
34
38
  "indexes/approvals",
35
- "indexes/queue",
36
- "indexes/run-control",
37
- "threads",
38
- ].map((segment) => ensureDir(path.join(this.runRoot, segment))));
39
+ "indexes/requests-queue",
40
+ "indexes/requests-control",
41
+ "sessions",
42
+ ].map((segment) => ensureDir(path.join(this.artifactsRoot(), segment))));
39
43
  }
40
44
  threadDir(threadId) {
41
- return path.join(this.runRoot, "threads", threadId);
45
+ return path.join(this.artifactsRoot(), "sessions", threadId);
42
46
  }
43
47
  runDir(threadId, runId) {
44
- return path.join(this.threadDir(threadId), "runs", runId);
48
+ return path.join(this.threadDir(threadId), "requests", runId);
45
49
  }
46
50
  async createThread(input) {
47
51
  const meta = {
@@ -58,7 +62,7 @@ export class FilePersistence {
58
62
  threadId: input.threadId,
59
63
  items: [],
60
64
  });
61
- await writeJson(path.join(this.runRoot, "indexes", "threads", `${input.threadId}.json`), {
65
+ await writeJson(this.threadIndexPath(input.threadId), {
62
66
  threadId: input.threadId,
63
67
  status: input.status,
64
68
  latestRunId: input.runId,
@@ -118,7 +122,7 @@ export class FilePersistence {
118
122
  hasError: false,
119
123
  lastError: null,
120
124
  }),
121
- writeJson(path.join(this.runRoot, "indexes", "runs", `${input.runId}.json`), {
125
+ writeJson(this.runIndexPath(input.runId), {
122
126
  runId: input.runId,
123
127
  threadId: input.threadId,
124
128
  state: "running",
@@ -175,7 +179,7 @@ export class FilePersistence {
175
179
  kind: "langgraph-checkpoint",
176
180
  });
177
181
  }
178
- await writeJson(path.join(this.runRoot, "indexes", "runs", `${runId}.json`), {
182
+ await writeJson(this.runIndexPath(runId), {
179
183
  runId,
180
184
  threadId,
181
185
  state,
@@ -188,7 +192,7 @@ export class FilePersistence {
188
192
  threadMeta.updatedAt = now;
189
193
  threadMeta.latestRunId = runId;
190
194
  await writeJson(threadMetaPath, threadMeta);
191
- await writeJson(path.join(this.runRoot, "indexes", "threads", `${threadId}.json`), {
195
+ await writeJson(this.threadIndexPath(threadId), {
192
196
  threadId,
193
197
  status: state,
194
198
  latestRunId: runId,
@@ -208,7 +212,7 @@ export class FilePersistence {
208
212
  ]);
209
213
  }
210
214
  async listSessions(filter = {}) {
211
- const threadIndexDir = path.join(this.runRoot, "indexes", "threads");
215
+ const threadIndexDir = path.join(this.artifactsRoot(), "indexes", "sessions");
212
216
  if (!(await fileExists(threadIndexDir))) {
213
217
  return [];
214
218
  }
@@ -253,7 +257,7 @@ export class FilePersistence {
253
257
  return summaries.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
254
258
  }
255
259
  async listRunIndexes() {
256
- const runIndexDir = path.join(this.runRoot, "indexes", "runs");
260
+ const runIndexDir = path.join(this.artifactsRoot(), "indexes", "requests");
257
261
  if (!(await fileExists(runIndexDir))) {
258
262
  return [];
259
263
  }
@@ -314,7 +318,7 @@ export class FilePersistence {
314
318
  return this.readRunSummary(index.threadId, index.runId);
315
319
  }
316
320
  async getSession(threadId) {
317
- const filePath = path.join(this.runRoot, "indexes", "threads", `${threadId}.json`);
321
+ const filePath = this.threadIndexPath(threadId);
318
322
  if (!(await fileExists(filePath))) {
319
323
  return null;
320
324
  }
@@ -360,7 +364,7 @@ export class FilePersistence {
360
364
  return Promise.all(entries.map((entry) => readJson(path.join(eventsDir, entry))));
361
365
  }
362
366
  async listApprovals(filter = {}) {
363
- const approvalsDir = path.join(this.runRoot, "indexes", "approvals");
367
+ const approvalsDir = path.join(this.artifactsRoot(), "indexes", "approvals");
364
368
  if (!(await fileExists(approvalsDir))) {
365
369
  return [];
366
370
  }
@@ -380,7 +384,7 @@ export class FilePersistence {
380
384
  });
381
385
  }
382
386
  async getApproval(approvalId) {
383
- const approvalPath = path.join(this.runRoot, "indexes", "approvals", `${approvalId}.json`);
387
+ const approvalPath = this.approvalIndexPath(approvalId);
384
388
  if (!(await fileExists(approvalPath))) {
385
389
  return null;
386
390
  }
@@ -496,7 +500,7 @@ export class FilePersistence {
496
500
  };
497
501
  await Promise.all([
498
502
  writeJson(path.join(this.runDir(sessionId, requestId), "approvals", `${record.approvalId}.json`), normalized),
499
- writeJson(path.join(this.runRoot, "indexes", "approvals", `${record.approvalId}.json`), normalized),
503
+ writeJson(this.approvalIndexPath(record.approvalId), normalized),
500
504
  ]);
501
505
  }
502
506
  async resolveApproval(threadId, runId, approvalId, status) {
@@ -509,7 +513,7 @@ export class FilePersistence {
509
513
  };
510
514
  await Promise.all([
511
515
  writeJson(approvalPath, updated),
512
- writeJson(path.join(this.runRoot, "indexes", "approvals", `${approvalId}.json`), updated),
516
+ writeJson(this.approvalIndexPath(approvalId), updated),
513
517
  ]);
514
518
  return updated;
515
519
  }
@@ -668,7 +672,7 @@ export class FilePersistence {
668
672
  });
669
673
  }
670
674
  async listExpiredClaimedRuns(cutoffIso) {
671
- const queueDir = path.join(this.runRoot, "indexes", "queue");
675
+ const queueDir = path.join(this.artifactsRoot(), "indexes", "requests-queue");
672
676
  if (!(await fileExists(queueDir))) {
673
677
  return [];
674
678
  }
@@ -111,7 +111,7 @@ export class SqlitePersistence {
111
111
  }
112
112
  async getClient() {
113
113
  if (!this.client) {
114
- await mkdir(this.runRoot, { recursive: true });
114
+ await mkdir(path.dirname(this.dbPath), { recursive: true });
115
115
  this.client = createClient({ url: toSqliteUrl(this.dbPath) });
116
116
  }
117
117
  return this.client;
@@ -1,6 +1,7 @@
1
1
  import { createCheckpointerForConfig, createStoreForConfig } from "../../support/runtime-factories.js";
2
2
  import { resolveCompiledEmbeddingModel, resolveCompiledEmbeddingModelRef } from "../../support/embedding-models.js";
3
3
  import { resolveCompiledVectorStore, resolveCompiledVectorStoreRef } from "../../support/vector-stores.js";
4
+ import { resolveRuntimeCheckpointerPath } from "../../support/runtime-layout.js";
4
5
  export function resolveStoreFromConfig(stores, storeConfig, runRoot) {
5
6
  const cacheKey = storeConfig ? `${runRoot}:${JSON.stringify(storeConfig)}` : undefined;
6
7
  if (!storeConfig || !cacheKey) {
@@ -42,12 +43,13 @@ export async function resolveVectorStore(workspace, vectorStores, vectorStoreRef
42
43
  return resolved;
43
44
  }
44
45
  export function resolveCheckpointer(checkpointers, binding) {
45
- const key = `${binding.harnessRuntime.runRoot}:${JSON.stringify(binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" })}`;
46
+ const key = `${binding.harnessRuntime.runRoot}:${JSON.stringify(binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: resolveRuntimeCheckpointerPath(binding.harnessRuntime.runRoot, "checkpoints.json") })}`;
46
47
  const existing = checkpointers.get(key);
47
48
  if (existing) {
48
49
  return existing;
49
50
  }
50
- const resolvedConfig = binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" };
51
+ const resolvedConfig = binding.harnessRuntime.checkpointer ??
52
+ { kind: "FileCheckpointer", path: resolveRuntimeCheckpointerPath(binding.harnessRuntime.runRoot, "checkpoints.json") };
51
53
  if (typeof resolvedConfig === "boolean") {
52
54
  checkpointers.set(key, resolvedConfig);
53
55
  return resolvedConfig;
@@ -35,7 +35,7 @@ export function readRuntimeMemoryPolicyConfig(runtimeMemory, workspaceRoot) {
35
35
  maxPromptMemories: asPositiveInteger(retrieval?.maxPromptMemories) ?? 8,
36
36
  },
37
37
  namespaces: {
38
- thread: asString(namespaces?.threads) ?? "memories/threads/{threadId}",
38
+ thread: asString(namespaces?.sessions) ?? "memories/sessions/{sessionId}",
39
39
  workspace: asString(namespaces?.workspaces) ?? `memories/workspaces/${workspaceId}`,
40
40
  agent: asString(namespaces?.agents) ?? "memories/agents/{agentId}",
41
41
  user: asString(namespaces?.users) ?? "memories/users/{userId}",
@@ -440,6 +440,10 @@ export async function persistStructuredMemoryRecords(options) {
440
440
  const evaluated = evaluateDecision(existing, incoming, options.recordedAt);
441
441
  const recordsToWrite = [evaluated.primaryRecord, ...evaluated.additionalRecords];
442
442
  for (const record of recordsToWrite) {
443
+ const priorRecord = existingRecords.find((item) => item.id === record.id);
444
+ if (priorRecord) {
445
+ await deleteRecordIndexes(options.store, priorRecord);
446
+ }
443
447
  await putRecordWithIndexes(options.store, record, options.recordedAt);
444
448
  const existingIndex = existingRecords.findIndex((item) => item.id === record.id);
445
449
  if (existingIndex >= 0) {
@@ -192,10 +192,10 @@ export class RuntimeMemorySync {
192
192
  await this.store.put(this.resolveThreadNamespace(threadId), "durable-summary.md", { content: `${digestMarkdown}\n` });
193
193
  }
194
194
  resolveThreadNamespace(threadId) {
195
- return this.options.resolveThreadNamespace ? this.options.resolveThreadNamespace(threadId) : ["memories", "threads", threadId];
195
+ return this.options.resolveThreadNamespace ? this.options.resolveThreadNamespace(threadId) : ["memories", "sessions", threadId];
196
196
  }
197
197
  resolveRunNamespace(threadId) {
198
- return this.options.resolveRunNamespace ? this.options.resolveRunNamespace(threadId) : ["memories", "runs", threadId];
198
+ return this.options.resolveRunNamespace ? this.options.resolveRunNamespace(threadId) : ["memories", "requests", threadId];
199
199
  }
200
200
  async close() {
201
201
  await Promise.allSettled(Array.from(this.pending));
@@ -47,7 +47,7 @@ function formatOpenApprovalsSection(approvals) {
47
47
  return lines;
48
48
  }
49
49
  function resolveThreadNamespace(threadId, resolver) {
50
- return resolver ? resolver(threadId) : ["memories", "threads", threadId];
50
+ return resolver ? resolver(threadId) : ["memories", "sessions", threadId];
51
51
  }
52
52
  const THREAD_MEMORY_EVENT_TYPES = new Set([
53
53
  "run.state.changed",
@@ -32,6 +32,7 @@ export declare class AgentHarnessRuntime {
32
32
  private readonly mem0SemanticRecall;
33
33
  private readonly runtimeMemoryFormationConfig;
34
34
  private readonly runtimeMemoryManager;
35
+ private readonly knowledgeModule;
35
36
  private readonly runtimeMemoryFormationSync;
36
37
  private readonly unregisterRuntimeMemoryFormationSync;
37
38
  private readonly resolvedRuntimeAdapterOptions;
@@ -136,24 +137,8 @@ export declare class AgentHarnessRuntime {
136
137
  private invokeWithHistory;
137
138
  private resolveMemoryNamespace;
138
139
  private getWorkspaceId;
139
- private summarizeMemoryContent;
140
- private matchesMemoryFilters;
141
- private resolveRecallScopes;
142
- private matchesRecallScope;
143
- private getMemoryScopeBoost;
144
- private memoryFreshnessBoost;
145
- private scoreStructuredRecord;
146
- private normalizeMemoryDedupKey;
147
- private inferMem0MemoryKind;
148
- private inferMem0MemoryScope;
149
- private createMem0MemoryRecord;
150
- private rankRecallCandidates;
151
- private rebuildRuntimeMemoryVectorIndex;
152
- private refreshStructuredMemoryScope;
153
140
  private buildRuntimeMemoryContext;
154
141
  private persistRuntimeMemoryCandidates;
155
- private persistStructuredMemoryCandidates;
156
- private appendMemoryDigest;
157
142
  private resolvePersistedRunPriority;
158
143
  private enqueuePendingRunSlot;
159
144
  private executeQueuedRun;