@botbotgo/agent-harness 0.0.282 → 0.0.284
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 +2 -2
- package/README.zh.md +2 -2
- package/dist/config/agents/direct.yaml +0 -3
- package/dist/config/agents/orchestra.yaml +0 -3
- package/dist/config/catalogs/stores.yaml +2 -2
- package/dist/config/catalogs/vector-stores.yaml +1 -1
- package/dist/config/knowledge/knowledge-runtime.yaml +3 -3
- package/dist/config/runtime/runtime-memory.yaml +3 -3
- package/dist/config/runtime/workspace.yaml +16 -9
- package/dist/contracts/workspace.d.ts +6 -0
- package/dist/init-project.js +11 -9
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +1 -0
- package/dist/persistence/file-store.js +29 -25
- package/dist/persistence/sqlite-store.js +6 -3
- package/dist/runtime/harness/run/resources.js +4 -2
- package/dist/runtime/harness/system/mem0-ingestion-sync.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-manager.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-policy.js +1 -1
- package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
- package/dist/runtime/harness/system/thread-memory-sync.js +1 -1
- package/dist/runtime/harness.js +12 -11
- package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -1
- package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -1
- package/dist/runtime/support/llamaindex.d.ts +1 -1
- package/dist/runtime/support/llamaindex.js +2 -2
- package/dist/runtime/support/runtime-factories.js +6 -3
- package/dist/runtime/support/runtime-layout.d.ts +7 -0
- package/dist/runtime/support/runtime-layout.js +22 -0
- package/dist/runtime/support/vector-stores.js +4 -3
- package/dist/workspace/agent-binding-compiler.js +8 -6
- package/dist/workspace/compile.js +6 -1
- package/dist/workspace/object-loader.js +3 -0
- package/dist/workspace/support/workspace-ref-utils.d.ts +6 -0
- package/dist/workspace/support/workspace-ref-utils.js +25 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -524,7 +524,7 @@ Use `normalizeUserChatInput(...)` when a product already has chat-style user mes
|
|
|
524
524
|
import { memorize, recall } from "@botbotgo/agent-harness";
|
|
525
525
|
|
|
526
526
|
await memorize(runtime, {
|
|
527
|
-
|
|
527
|
+
sessionId: "session-123",
|
|
528
528
|
records: [
|
|
529
529
|
{
|
|
530
530
|
content: "The release checklist requires a smoke test before publish.",
|
|
@@ -972,7 +972,7 @@ spec:
|
|
|
972
972
|
maxFileSizeMb: 10
|
|
973
973
|
sessionStorage:
|
|
974
974
|
enabled: true
|
|
975
|
-
rootDir: "{runRoot}/
|
|
975
|
+
rootDir: "{runRoot}/sessions/{sessionId}/filesystem"
|
|
976
976
|
middleware: []
|
|
977
977
|
systemPrompt: Answer simple requests directly.
|
|
978
978
|
```
|
package/README.zh.md
CHANGED
|
@@ -495,7 +495,7 @@ const result = await request(runtime, {
|
|
|
495
495
|
import { memorize, recall } from "@botbotgo/agent-harness";
|
|
496
496
|
|
|
497
497
|
await memorize(runtime, {
|
|
498
|
-
|
|
498
|
+
sessionId: "session-123",
|
|
499
499
|
records: [
|
|
500
500
|
{
|
|
501
501
|
content: "The release checklist requires a smoke test before publish.",
|
|
@@ -929,7 +929,7 @@ spec:
|
|
|
929
929
|
maxFileSizeMb: 10
|
|
930
930
|
sessionStorage:
|
|
931
931
|
enabled: true
|
|
932
|
-
rootDir: "{runRoot}/
|
|
932
|
+
rootDir: "{runRoot}/sessions/{sessionId}/filesystem"
|
|
933
933
|
middleware: []
|
|
934
934
|
systemPrompt: Answer simple requests directly.
|
|
935
935
|
```
|
|
@@ -10,9 +10,6 @@ metadata:
|
|
|
10
10
|
description: Manual low-latency host for direct answers and lightweight inventory lookup. Do not use it as the default executor for tool-heavy or delegation-heavy tasks.
|
|
11
11
|
spec:
|
|
12
12
|
runtime:
|
|
13
|
-
# agent-harness feature: host-level run data placement override.
|
|
14
|
-
# This matches the workspace default and keeps the default config shape explicit.
|
|
15
|
-
runRoot: ./.agent
|
|
16
13
|
# agent-harness feature: workspace-level durable long-term memory defaults for this host profile.
|
|
17
14
|
runtimeMemory: default
|
|
18
15
|
# =====================
|
|
@@ -10,9 +10,6 @@ metadata:
|
|
|
10
10
|
description: Default execution host. Answer directly when possible, use local tools and skills first, and delegate only when a subagent is a better fit. Not a reflex delegation-only orchestrator.
|
|
11
11
|
spec:
|
|
12
12
|
runtime:
|
|
13
|
-
# agent-harness feature: host-level run data placement override.
|
|
14
|
-
# This matches the workspace default and keeps the default config shape explicit.
|
|
15
|
-
runRoot: ./.agent
|
|
16
13
|
# agent-harness feature: workspace-level durable long-term memory defaults for this host profile.
|
|
17
14
|
runtimeMemory: default
|
|
18
15
|
# =====================
|
|
@@ -8,11 +8,11 @@ spec:
|
|
|
8
8
|
name: default
|
|
9
9
|
description: Default sqlite-backed store preset for runtime-managed agent state and durable memory.
|
|
10
10
|
storeKind: SqliteStore
|
|
11
|
-
path:
|
|
11
|
+
path: knowledge/records.sqlite
|
|
12
12
|
|
|
13
13
|
# agent-harness feature: reusable checkpointer preset for resumable execution state.
|
|
14
14
|
- kind: Checkpointer
|
|
15
15
|
name: default
|
|
16
16
|
description: Default file-backed checkpointer preset for durable local graph state without native sqlite bindings.
|
|
17
17
|
checkpointerKind: FileCheckpointer
|
|
18
|
-
path: checkpoints.json
|
|
18
|
+
path: runtime/checkpoints.json
|
|
@@ -13,7 +13,7 @@ spec:
|
|
|
13
13
|
storeKind: LibSQLVectorStore
|
|
14
14
|
# LangChain aligned feature: libSQL connection URL.
|
|
15
15
|
# Local SQLite files use the `file:` prefix.
|
|
16
|
-
url: file
|
|
16
|
+
url: file:knowledge/vectors.sqlite
|
|
17
17
|
# LangChain aligned feature: target table and embedding column.
|
|
18
18
|
table: rag_chunks
|
|
19
19
|
column: embedding
|
|
@@ -22,7 +22,7 @@ spec:
|
|
|
22
22
|
## agent-harness feature: stable namespace roots shared with runtime memory policy.
|
|
23
23
|
users: memories/users/{userId}
|
|
24
24
|
projects: memories/projects/{projectId}
|
|
25
|
-
|
|
25
|
+
sessions: memories/sessions/{sessionId}
|
|
26
26
|
agents: memories/agents/{agentId}
|
|
27
27
|
workspaces: memories/workspaces/{workspaceId}
|
|
28
28
|
retrieval:
|
|
@@ -47,7 +47,7 @@ spec:
|
|
|
47
47
|
enabled: true
|
|
48
48
|
scopes:
|
|
49
49
|
- thread
|
|
50
|
-
stateStorePath:
|
|
50
|
+
stateStorePath: knowledge/formation-state.json
|
|
51
51
|
maxMessagesPerRun: 40
|
|
52
52
|
writeOnApprovalResolution: true
|
|
53
53
|
writeOnRunCompletion: true
|
|
@@ -56,5 +56,5 @@ spec:
|
|
|
56
56
|
enabled: false
|
|
57
57
|
apiKeyEnv: MEM0_API_KEY
|
|
58
58
|
appId: agent-harness
|
|
59
|
-
stateStorePath: mem0-sync-state.json
|
|
59
|
+
stateStorePath: knowledge/mem0-sync-state.json
|
|
60
60
|
maxMessagesPerRun: 200
|
|
@@ -30,7 +30,7 @@ spec:
|
|
|
30
30
|
namespaces:
|
|
31
31
|
users: memories/users/{userId}
|
|
32
32
|
projects: memories/projects/{projectId}
|
|
33
|
-
|
|
33
|
+
sessions: memories/sessions/{sessionId}
|
|
34
34
|
agents: memories/agents/{agentId}
|
|
35
35
|
workspaces: memories/workspaces/{workspaceId}
|
|
36
36
|
|
|
@@ -78,7 +78,7 @@ spec:
|
|
|
78
78
|
enabled: true
|
|
79
79
|
scopes:
|
|
80
80
|
- thread
|
|
81
|
-
stateStorePath:
|
|
81
|
+
stateStorePath: knowledge/formation-state.json
|
|
82
82
|
maxMessagesPerRun: 40
|
|
83
83
|
writeOnApprovalResolution: true
|
|
84
84
|
writeOnRunCompletion: true
|
|
@@ -92,5 +92,5 @@ spec:
|
|
|
92
92
|
enabled: false
|
|
93
93
|
apiKeyEnv: MEM0_API_KEY
|
|
94
94
|
appId: agent-harness
|
|
95
|
-
stateStorePath: mem0-sync-state.json
|
|
95
|
+
stateStorePath: knowledge/mem0-sync-state.json
|
|
96
96
|
maxMessagesPerRun: 200
|
|
@@ -12,15 +12,22 @@ spec:
|
|
|
12
12
|
# ======================
|
|
13
13
|
# agent-harness Features
|
|
14
14
|
# ======================
|
|
15
|
-
# agent-harness feature:
|
|
16
|
-
# This
|
|
17
|
-
# -
|
|
18
|
-
# -
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
|
|
15
|
+
# agent-harness feature: read-only application folder that contains the shared workspace assembly.
|
|
16
|
+
# This is where the runtime loads config catalogs and packaged resources such as:
|
|
17
|
+
# - config/
|
|
18
|
+
# - resources/
|
|
19
|
+
# Downstream applications can point multiple runtime profiles at the same application folder.
|
|
20
|
+
applicationRoot: .
|
|
21
|
+
|
|
22
|
+
# agent-harness feature: writable data folder for one runtime profile.
|
|
23
|
+
# Runtime-owned persistence stays under this root, split by function:
|
|
24
|
+
# - runtime/ for requests, approvals, checkpoints, and artifacts
|
|
25
|
+
# - knowledge/ for durable knowledge and vector indexes
|
|
26
|
+
# Different runtime profiles can use different data folders while sharing the same application folder.
|
|
27
|
+
dataRoot: ./.agent
|
|
28
|
+
|
|
29
|
+
# agent-harness feature: stable runtime profile identifier for this data folder.
|
|
30
|
+
profile: default
|
|
24
31
|
|
|
25
32
|
# agent-harness feature: runtime-level task queue and maximum number of concurrent runs.
|
|
26
33
|
# Additional runs wait in the harness queue until a slot becomes available.
|
|
@@ -7,6 +7,9 @@ export type ParsedAgentObject = {
|
|
|
7
7
|
description: string;
|
|
8
8
|
modelRef: string;
|
|
9
9
|
runRoot?: string;
|
|
10
|
+
applicationRoot?: string;
|
|
11
|
+
dataRoot?: string;
|
|
12
|
+
runtimeProfile?: string;
|
|
10
13
|
toolRefs: string[];
|
|
11
14
|
toolBindings?: ParsedAgentToolBinding[];
|
|
12
15
|
inlineTools?: ParsedToolObject[];
|
|
@@ -260,6 +263,9 @@ export type CompiledAgentBinding = {
|
|
|
260
263
|
*/
|
|
261
264
|
deepAgentParams?: LegacyDeepAgentParams;
|
|
262
265
|
harnessRuntime: {
|
|
266
|
+
applicationRoot?: string;
|
|
267
|
+
dataRoot?: string;
|
|
268
|
+
runtimeProfile?: string;
|
|
263
269
|
runRoot: string;
|
|
264
270
|
workspaceRoot?: string;
|
|
265
271
|
capabilities?: RuntimeCapabilities;
|
package/dist/init-project.js
CHANGED
|
@@ -93,7 +93,9 @@ kind: Runtime
|
|
|
93
93
|
metadata:
|
|
94
94
|
name: default
|
|
95
95
|
spec:
|
|
96
|
-
|
|
96
|
+
applicationRoot: .
|
|
97
|
+
dataRoot: ./.agent
|
|
98
|
+
profile: default
|
|
97
99
|
`;
|
|
98
100
|
}
|
|
99
101
|
function renderAgentContext(options) {
|
|
@@ -143,11 +145,11 @@ spec:
|
|
|
143
145
|
enabled: true
|
|
144
146
|
store:
|
|
145
147
|
kind: SqliteStore
|
|
146
|
-
path:
|
|
148
|
+
path: knowledge/records.sqlite
|
|
147
149
|
namespaces:
|
|
148
150
|
users: memories/users/{userId}
|
|
149
151
|
projects: memories/projects/{projectId}
|
|
150
|
-
|
|
152
|
+
sessions: memories/sessions/{sessionId}
|
|
151
153
|
agents: memories/agents/{agentId}
|
|
152
154
|
workspaces: memories/workspaces/{workspaceId}
|
|
153
155
|
retrieval:
|
|
@@ -179,7 +181,7 @@ spec:
|
|
|
179
181
|
enabled: true
|
|
180
182
|
scopes:
|
|
181
183
|
- thread
|
|
182
|
-
stateStorePath:
|
|
184
|
+
stateStorePath: knowledge/formation-state.json
|
|
183
185
|
maxMessagesPerRun: 40
|
|
184
186
|
writeOnApprovalResolution: true
|
|
185
187
|
writeOnRunCompletion: true
|
|
@@ -189,7 +191,7 @@ spec:
|
|
|
189
191
|
enabled: false
|
|
190
192
|
apiKeyEnv: MEM0_API_KEY
|
|
191
193
|
appId: ${projectSlug}
|
|
192
|
-
stateStorePath: mem0-sync-state.json
|
|
194
|
+
stateStorePath: knowledge/mem0-sync-state.json
|
|
193
195
|
maxMessagesPerRun: 200
|
|
194
196
|
`;
|
|
195
197
|
}
|
|
@@ -202,11 +204,11 @@ spec:
|
|
|
202
204
|
enabled: true
|
|
203
205
|
store:
|
|
204
206
|
kind: SqliteStore
|
|
205
|
-
path:
|
|
207
|
+
path: knowledge/records.sqlite
|
|
206
208
|
namespaces:
|
|
207
209
|
users: memories/users/{userId}
|
|
208
210
|
projects: memories/projects/{projectId}
|
|
209
|
-
|
|
211
|
+
sessions: memories/sessions/{sessionId}
|
|
210
212
|
agents: memories/agents/{agentId}
|
|
211
213
|
workspaces: memories/workspaces/{workspaceId}
|
|
212
214
|
retrieval:
|
|
@@ -223,7 +225,7 @@ spec:
|
|
|
223
225
|
enabled: true
|
|
224
226
|
scopes:
|
|
225
227
|
- thread
|
|
226
|
-
stateStorePath:
|
|
228
|
+
stateStorePath: knowledge/formation-state.json
|
|
227
229
|
maxMessagesPerRun: 40
|
|
228
230
|
writeOnApprovalResolution: true
|
|
229
231
|
writeOnRunCompletion: true
|
|
@@ -231,7 +233,7 @@ spec:
|
|
|
231
233
|
enabled: false
|
|
232
234
|
apiKeyEnv: MEM0_API_KEY
|
|
233
235
|
appId: ${projectSlug}
|
|
234
|
-
stateStorePath: mem0-sync-state.json
|
|
236
|
+
stateStorePath: knowledge/mem0-sync-state.json
|
|
235
237
|
maxMessagesPerRun: 200
|
|
236
238
|
`;
|
|
237
239
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.283";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.283";
|
|
@@ -10,6 +10,7 @@ type RunIndexRecord = {
|
|
|
10
10
|
export declare class FilePersistence implements RuntimePersistence {
|
|
11
11
|
private readonly runRoot;
|
|
12
12
|
constructor(runRoot: string);
|
|
13
|
+
private artifactsRoot;
|
|
13
14
|
private threadIndexPath;
|
|
14
15
|
private runIndexPath;
|
|
15
16
|
private approvalIndexPath;
|
|
@@ -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.
|
|
17
|
+
return path.join(this.artifactsRoot(), "indexes", "sessions", `${threadId}.json`);
|
|
14
18
|
}
|
|
15
19
|
runIndexPath(runId) {
|
|
16
|
-
return path.join(this.
|
|
20
|
+
return path.join(this.artifactsRoot(), "indexes", "requests", `${runId}.json`);
|
|
17
21
|
}
|
|
18
22
|
approvalIndexPath(approvalId) {
|
|
19
|
-
return path.join(this.
|
|
23
|
+
return path.join(this.artifactsRoot(), "indexes", "approvals", `${approvalId}.json`);
|
|
20
24
|
}
|
|
21
25
|
runQueuePath(runId) {
|
|
22
|
-
return path.join(this.
|
|
26
|
+
return path.join(this.artifactsRoot(), "indexes", "requests-queue", `${runId}.json`);
|
|
23
27
|
}
|
|
24
28
|
runControlPath(runId) {
|
|
25
|
-
return path.join(this.
|
|
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/
|
|
33
|
-
"indexes/
|
|
36
|
+
"indexes/sessions",
|
|
37
|
+
"indexes/requests",
|
|
34
38
|
"indexes/approvals",
|
|
35
|
-
"indexes/queue",
|
|
36
|
-
"indexes/
|
|
37
|
-
"
|
|
38
|
-
].map((segment) => ensureDir(path.join(this.
|
|
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.
|
|
45
|
+
return path.join(this.artifactsRoot(), "sessions", threadId);
|
|
42
46
|
}
|
|
43
47
|
runDir(threadId, runId) {
|
|
44
|
-
return path.join(this.threadDir(threadId), "
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
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.
|
|
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 =
|
|
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.
|
|
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 =
|
|
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(
|
|
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(
|
|
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.
|
|
675
|
+
const queueDir = path.join(this.artifactsRoot(), "indexes", "requests-queue");
|
|
672
676
|
if (!(await fileExists(queueDir))) {
|
|
673
677
|
return [];
|
|
674
678
|
}
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { mkdir, rm } from "node:fs/promises";
|
|
3
3
|
import { createClient } from "@libsql/client";
|
|
4
4
|
import { fileExists, readJson, writeJson } from "../utils/fs.js";
|
|
5
|
+
import { resolveRuntimeRoot, resolveRuntimeSqlitePath } from "../runtime/support/runtime-layout.js";
|
|
5
6
|
import { SqliteRunContextStore } from "./sqlite-run-context-store.js";
|
|
6
7
|
import { SqliteRunQueueStore } from "./sqlite-run-queue-store.js";
|
|
7
8
|
const RUNTIME_SQLITE_SCHEMA_VERSION = 6;
|
|
@@ -97,7 +98,9 @@ export class SqlitePersistence {
|
|
|
97
98
|
initialization = null;
|
|
98
99
|
constructor(runRoot, dbFile = "runtime.sqlite") {
|
|
99
100
|
this.runRoot = runRoot;
|
|
100
|
-
this.dbPath =
|
|
101
|
+
this.dbPath = dbFile === "runtime.sqlite"
|
|
102
|
+
? resolveRuntimeSqlitePath(runRoot)
|
|
103
|
+
: path.join(resolveRuntimeRoot(runRoot), dbFile);
|
|
101
104
|
this.runContextStore = new SqliteRunContextStore({
|
|
102
105
|
execute: (sql, args) => this.execute(sql, args),
|
|
103
106
|
selectOne: (sql, args) => this.selectOne(sql, args),
|
|
@@ -111,7 +114,7 @@ export class SqlitePersistence {
|
|
|
111
114
|
}
|
|
112
115
|
async getClient() {
|
|
113
116
|
if (!this.client) {
|
|
114
|
-
await mkdir(this.
|
|
117
|
+
await mkdir(path.dirname(this.dbPath), { recursive: true });
|
|
115
118
|
this.client = createClient({ url: toSqliteUrl(this.dbPath) });
|
|
116
119
|
}
|
|
117
120
|
return this.client;
|
|
@@ -148,7 +151,7 @@ export class SqlitePersistence {
|
|
|
148
151
|
return;
|
|
149
152
|
}
|
|
150
153
|
this.initialization = (async () => {
|
|
151
|
-
await mkdir(this.runRoot, { recursive: true });
|
|
154
|
+
await mkdir(resolveRuntimeRoot(this.runRoot), { recursive: true });
|
|
152
155
|
await this.getClient();
|
|
153
156
|
await this.rawExecute("PRAGMA journal_mode=WAL");
|
|
154
157
|
await this.rawExecute("PRAGMA foreign_keys=ON");
|
|
@@ -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 ??
|
|
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;
|
|
@@ -62,7 +62,7 @@ export function readMem0RuntimeConfig(runtimeMemory, workspaceRoot) {
|
|
|
62
62
|
projectId: asNonEmptyString(mem0.projectId),
|
|
63
63
|
appId: asNonEmptyString(mem0.appId) ?? workspaceBaseName,
|
|
64
64
|
userIdPrefix: asNonEmptyString(mem0.userIdPrefix),
|
|
65
|
-
stateStorePath: asNonEmptyString(mem0.stateStorePath) ?? "mem0-sync-state.json",
|
|
65
|
+
stateStorePath: asNonEmptyString(mem0.stateStorePath) ?? "knowledge/mem0-sync-state.json",
|
|
66
66
|
maxMessagesPerRun: asPositiveInteger(mem0.maxMessagesPerRun) ?? 200,
|
|
67
67
|
writeOnApprovalResolution: asBoolean(mem0.writeOnApprovalResolution) ?? asBoolean(ingestion?.writeOnApprovalResolution) ?? true,
|
|
68
68
|
writeOnRunCompletion: asBoolean(mem0.writeOnRunCompletion) ?? asBoolean(ingestion?.writeOnRunCompletion) ?? true,
|
|
@@ -57,7 +57,7 @@ export function readRuntimeMemoryFormationConfig(runtimeMemory, workspaceRoot) {
|
|
|
57
57
|
enabled: asBoolean(background?.enabled) ?? true,
|
|
58
58
|
maxMessagesPerRun: asPositiveInteger(background?.maxMessagesPerRun) ?? asPositiveInteger(ingestion?.maxMessagesPerRun) ?? 40,
|
|
59
59
|
scopes: normalizeScopeList(asMemoryScopes(background?.scopes) ?? ["thread"]),
|
|
60
|
-
stateStorePath: asNonEmptyString(background?.stateStorePath) ??
|
|
60
|
+
stateStorePath: asNonEmptyString(background?.stateStorePath) ?? `knowledge/${workspaceBaseName}-memory-formation-state.json`,
|
|
61
61
|
writeOnApprovalResolution: asBoolean(background?.writeOnApprovalResolution) ?? asBoolean(ingestion?.writeOnApprovalResolution) ?? true,
|
|
62
62
|
writeOnRunCompletion: asBoolean(background?.writeOnRunCompletion) ?? asBoolean(ingestion?.writeOnRunCompletion) ?? true,
|
|
63
63
|
},
|
|
@@ -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?.
|
|
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}",
|
|
@@ -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", "
|
|
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", "
|
|
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", "
|
|
50
|
+
return resolver ? resolver(threadId) : ["memories", "sessions", threadId];
|
|
51
51
|
}
|
|
52
52
|
const THREAD_MEMORY_EVENT_TYPES = new Set([
|
|
53
53
|
"run.state.changed",
|
package/dist/runtime/harness.js
CHANGED
|
@@ -10,7 +10,7 @@ import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getR
|
|
|
10
10
|
import { createHarnessEvent, inferRoutingBindings, renderRuntimeFailure, } from "./support/harness-support.js";
|
|
11
11
|
import { ThreadMemorySync } from "./harness/system/thread-memory-sync.js";
|
|
12
12
|
import { RuntimeMemorySync, readRuntimeMemorySyncConfig } from "./harness/system/runtime-memory-sync.js";
|
|
13
|
-
import {
|
|
13
|
+
import { SqliteBackedStore } from "./harness/system/store.js";
|
|
14
14
|
import { HealthMonitor, readHealthMonitorConfig, } from "./harness/system/health-monitor.js";
|
|
15
15
|
import { normalizeInvocationEnvelope, normalizeRunPriority, resolveRunListeners, } from "./harness/run/helpers.js";
|
|
16
16
|
import { emitHarnessEvent, } from "./harness/events/events.js";
|
|
@@ -34,6 +34,7 @@ import { Mem0IngestionSync, Mem0SemanticRecall, readMem0RuntimeConfig, } from ".
|
|
|
34
34
|
import { createRuntimeMemoryManager, RuntimeMemoryFormationSync, readRuntimeMemoryFormationConfig, } from "./harness/system/runtime-memory-manager.js";
|
|
35
35
|
import { readRuntimeMemoryMaintenanceConfig, readRuntimeMemoryPolicyConfig, resolveMemoryNamespace, } from "./harness/system/runtime-memory-policy.js";
|
|
36
36
|
import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.js";
|
|
37
|
+
import { resolveKnowledgeStorePath } from "./support/runtime-layout.js";
|
|
37
38
|
import { initializeHarnessRuntime, reclaimExpiredClaimedRuns as reclaimHarnessExpiredClaimedRuns, recoverStartupRuns as recoverHarnessStartupRuns, isStaleRunningRun as isHarnessStaleRunningRun, } from "./harness/run/startup-runtime.js";
|
|
38
39
|
import { traceStartupStage } from "./startup-tracing.js";
|
|
39
40
|
import { normalizeProcessExecutablePath } from "./support/runtime-env.js";
|
|
@@ -256,11 +257,11 @@ export class AgentHarnessRuntime {
|
|
|
256
257
|
normalizeProcessExecutablePath();
|
|
257
258
|
this.runtimeEntryBindings = inferRoutingBindings(this.workspace).runtimeEntryBindings;
|
|
258
259
|
this.defaultRuntimeEntryBinding = this.runtimeEntryBindings[0];
|
|
259
|
-
this.defaultRunRootValue = this.defaultRuntimeEntryBinding?.harnessRuntime.runRoot ?? `${this.workspace.workspaceRoot}
|
|
260
|
+
this.defaultRunRootValue = this.defaultRuntimeEntryBinding?.harnessRuntime.runRoot ?? `${this.workspace.workspaceRoot}/.agent`;
|
|
260
261
|
const runRoot = this.defaultRunRoot();
|
|
261
262
|
this.persistence = new SqlitePersistence(runRoot);
|
|
262
263
|
const defaultStoreConfig = this.defaultRuntimeEntryBinding?.harnessRuntime.store;
|
|
263
|
-
this.defaultStore = resolveStoreFromConfig(this.stores, defaultStoreConfig, runRoot) ?? new
|
|
264
|
+
this.defaultStore = resolveStoreFromConfig(this.stores, defaultStoreConfig, runRoot) ?? new SqliteBackedStore(resolveKnowledgeStorePath(runRoot));
|
|
264
265
|
const runtimeMemoryStoreConfig = typeof this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeMemory?.store === "object" &&
|
|
265
266
|
this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeMemory?.store
|
|
266
267
|
? this.defaultRuntimeEntryBinding.harnessRuntime.runtimeMemory.store
|
|
@@ -291,12 +292,12 @@ export class AgentHarnessRuntime {
|
|
|
291
292
|
this.routingDefaultAgentId = getRoutingDefaultAgentId(workspace.refs);
|
|
292
293
|
if (isThreadMemorySyncEnabled(workspace)) {
|
|
293
294
|
this.threadMemorySync = new ThreadMemorySync(this.persistence, this.runtimeMemoryStore, {
|
|
294
|
-
resolveThreadNamespace: (
|
|
295
|
+
resolveThreadNamespace: (sessionId) => {
|
|
295
296
|
const binding = this.defaultRuntimeEntryBinding;
|
|
296
297
|
if (!binding) {
|
|
297
|
-
return ["memories", "
|
|
298
|
+
return ["memories", "sessions", sessionId];
|
|
298
299
|
}
|
|
299
|
-
return this.resolveMemoryNamespace("thread", binding, {
|
|
300
|
+
return this.resolveMemoryNamespace("thread", binding, { sessionId });
|
|
300
301
|
},
|
|
301
302
|
});
|
|
302
303
|
this.unregisterThreadMemorySync = this.eventBus.registerProjection(this.threadMemorySync);
|
|
@@ -308,12 +309,12 @@ export class AgentHarnessRuntime {
|
|
|
308
309
|
const runtimeMemorySyncConfig = readRuntimeMemorySyncConfig(this.defaultRuntimeEntryBinding?.harnessRuntime.runtimeMemory);
|
|
309
310
|
if (runtimeMemorySyncConfig) {
|
|
310
311
|
this.runtimeMemorySync = new RuntimeMemorySync(this.persistence, this.runtimeMemoryStore, runtimeMemorySyncConfig, {
|
|
311
|
-
resolveThreadNamespace: (
|
|
312
|
+
resolveThreadNamespace: (sessionId) => {
|
|
312
313
|
const binding = this.defaultRuntimeEntryBinding;
|
|
313
314
|
if (!binding) {
|
|
314
|
-
return ["memories", "
|
|
315
|
+
return ["memories", "sessions", sessionId];
|
|
315
316
|
}
|
|
316
|
-
return this.resolveMemoryNamespace("thread", binding, {
|
|
317
|
+
return this.resolveMemoryNamespace("thread", binding, { sessionId });
|
|
317
318
|
},
|
|
318
319
|
});
|
|
319
320
|
this.unregisterRuntimeMemorySync = this.eventBus.registerProjection(this.runtimeMemorySync);
|
|
@@ -363,7 +364,7 @@ export class AgentHarnessRuntime {
|
|
|
363
364
|
return ["memories", `${scope}s`, identifier ?? "default"];
|
|
364
365
|
}
|
|
365
366
|
return this.resolveMemoryNamespace(scope, binding, {
|
|
366
|
-
|
|
367
|
+
sessionId: context.sessionId,
|
|
367
368
|
agentId: context.agentId,
|
|
368
369
|
userId: context.userId,
|
|
369
370
|
projectId: context.projectId,
|
|
@@ -937,7 +938,7 @@ export class AgentHarnessRuntime {
|
|
|
937
938
|
const workspaceId = this.getWorkspaceId(binding);
|
|
938
939
|
const template = this.runtimeMemoryPolicy?.namespaces[scope] ?? `memories/${scope}s/{${scope}Id}`;
|
|
939
940
|
return resolveMemoryNamespace(template, {
|
|
940
|
-
|
|
941
|
+
sessionId: options.sessionId,
|
|
941
942
|
agentId: options.agentId ?? binding.agent.id,
|
|
942
943
|
workspaceId,
|
|
943
944
|
userId: options.userId ?? "default",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileExists } from "../../utils/fs.js";
|
|
3
|
+
import { resolveRuntimeCheckpointerPath } from "../support/runtime-layout.js";
|
|
3
4
|
import { getRuntimeDefaults } from "../../workspace/support/workspace-ref-utils.js";
|
|
4
5
|
function asObject(value) {
|
|
5
6
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
@@ -52,7 +53,7 @@ function resolveSqliteCheckpointPath(binding) {
|
|
|
52
53
|
if (kind !== "SqliteSaver") {
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
55
|
-
const configuredPath = typeof config.path === "string" ? String(config.path) : "checkpoints.sqlite";
|
|
56
|
+
const configuredPath = typeof config.path === "string" ? String(config.path) : resolveRuntimeCheckpointerPath(binding.harnessRuntime.runRoot, "checkpoints.sqlite");
|
|
56
57
|
return path.isAbsolute(configuredPath) ? configuredPath : path.join(binding.harnessRuntime.runRoot, configuredPath);
|
|
57
58
|
}
|
|
58
59
|
export function discoverCheckpointMaintenanceTargets(workspace) {
|
|
@@ -2,6 +2,7 @@ import path from "node:path";
|
|
|
2
2
|
import { rm } from "node:fs/promises";
|
|
3
3
|
import { createClient } from "@libsql/client";
|
|
4
4
|
import { fileExists } from "../../utils/fs.js";
|
|
5
|
+
import { resolveRuntimeSqlitePath } from "../support/runtime-layout.js";
|
|
5
6
|
import { getRuntimeDefaults } from "../../workspace/support/workspace-ref-utils.js";
|
|
6
7
|
function asObject(value) {
|
|
7
8
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
|
|
@@ -50,7 +51,7 @@ export function discoverRuntimeRecordMaintenanceTargets(workspace) {
|
|
|
50
51
|
runRoots.add(binding.harnessRuntime.runRoot);
|
|
51
52
|
}
|
|
52
53
|
return Array.from(runRoots.values()).map((runRoot) => ({
|
|
53
|
-
dbPath:
|
|
54
|
+
dbPath: resolveRuntimeSqlitePath(runRoot),
|
|
54
55
|
}));
|
|
55
56
|
}
|
|
56
57
|
export async function maintainSqliteRuntimeRecords(dbPath, config, nowMs = Date.now()) {
|
|
@@ -21,4 +21,4 @@ export type VectorStoreRuntimeLike = {
|
|
|
21
21
|
}) => Promise<void>;
|
|
22
22
|
};
|
|
23
23
|
export declare function createLlamaIndexEmbeddingModel(embeddingModel: CompiledEmbeddingModel): EmbeddingRuntimeLike;
|
|
24
|
-
export declare function createLlamaIndexVectorStore(
|
|
24
|
+
export declare function createLlamaIndexVectorStore(dataRoot: string, vectorStore: CompiledVectorStore, embeddings: EmbeddingRuntimeLike): Promise<VectorStoreRuntimeLike>;
|
|
@@ -41,8 +41,8 @@ export function createLlamaIndexEmbeddingModel(embeddingModel) {
|
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
-
export async function createLlamaIndexVectorStore(
|
|
45
|
-
const persistPath = resolveFilePath(vectorStore.url ?? "
|
|
44
|
+
export async function createLlamaIndexVectorStore(dataRoot, vectorStore, embeddings) {
|
|
45
|
+
const persistPath = resolveFilePath(vectorStore.url ?? "knowledge/vectors.json", dataRoot);
|
|
46
46
|
await mkdir(path.dirname(persistPath), { recursive: true });
|
|
47
47
|
const emptyStore = () => SimpleVectorStore.fromDict({
|
|
48
48
|
embeddingDict: {},
|
|
@@ -2,15 +2,16 @@ import path from "node:path";
|
|
|
2
2
|
import { MemorySaver } from "@langchain/langgraph";
|
|
3
3
|
import { FileCheckpointSaver } from "../maintenance/file-checkpoint-saver.js";
|
|
4
4
|
import { createInMemoryStore, FileBackedStore, SqliteBackedStore } from "../harness/system/store.js";
|
|
5
|
+
import { resolveKnowledgeFileStorePath, resolveKnowledgeStorePath, resolveRuntimeCheckpointerPath, } from "./runtime-layout.js";
|
|
5
6
|
export function createStoreForConfig(storeConfig, runRoot) {
|
|
6
7
|
const kind = typeof storeConfig.kind === "string" ? storeConfig.kind : "FileStore";
|
|
7
8
|
switch (kind) {
|
|
8
9
|
case "FileStore": {
|
|
9
|
-
const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : "
|
|
10
|
+
const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeFileStorePath(runRoot, "records.json");
|
|
10
11
|
return new FileBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
|
|
11
12
|
}
|
|
12
13
|
case "SqliteStore": {
|
|
13
|
-
const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : "
|
|
14
|
+
const configuredPath = typeof storeConfig.path === "string" ? storeConfig.path : resolveKnowledgeStorePath(runRoot, "records.sqlite");
|
|
14
15
|
return new SqliteBackedStore(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
|
|
15
16
|
}
|
|
16
17
|
case "InMemoryStore":
|
|
@@ -34,7 +35,9 @@ export function createCheckpointerForConfig(checkpointerConfig, runRoot) {
|
|
|
34
35
|
case "SqliteSaver":
|
|
35
36
|
throw new Error("Checkpointer kind SqliteSaver is not supported in this runtime right now");
|
|
36
37
|
case "FileCheckpointer": {
|
|
37
|
-
const configuredPath = typeof checkpointerConfig.path === "string"
|
|
38
|
+
const configuredPath = typeof checkpointerConfig.path === "string"
|
|
39
|
+
? String(checkpointerConfig.path)
|
|
40
|
+
: resolveRuntimeCheckpointerPath(runRoot, "checkpoints.json");
|
|
38
41
|
return new FileCheckpointSaver(path.isAbsolute(configuredPath) ? configuredPath : path.join(runRoot, configuredPath));
|
|
39
42
|
}
|
|
40
43
|
default:
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function resolveRuntimeRoot(dataRoot: string): string;
|
|
2
|
+
export declare function resolveRuntimeArtifactsRoot(dataRoot: string): string;
|
|
3
|
+
export declare function resolveRuntimeSqlitePath(dataRoot: string): string;
|
|
4
|
+
export declare function resolveRuntimeCheckpointerPath(dataRoot: string, fileName?: string): string;
|
|
5
|
+
export declare function resolveKnowledgeRoot(dataRoot: string): string;
|
|
6
|
+
export declare function resolveKnowledgeStorePath(dataRoot: string, fileName?: string): string;
|
|
7
|
+
export declare function resolveKnowledgeFileStorePath(dataRoot: string, fileName?: string): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function resolveRuntimeRoot(dataRoot) {
|
|
3
|
+
return path.join(dataRoot, "runtime");
|
|
4
|
+
}
|
|
5
|
+
export function resolveRuntimeArtifactsRoot(dataRoot) {
|
|
6
|
+
return path.join(resolveRuntimeRoot(dataRoot), "artifacts");
|
|
7
|
+
}
|
|
8
|
+
export function resolveRuntimeSqlitePath(dataRoot) {
|
|
9
|
+
return path.join(resolveRuntimeRoot(dataRoot), "runtime.sqlite");
|
|
10
|
+
}
|
|
11
|
+
export function resolveRuntimeCheckpointerPath(dataRoot, fileName = "checkpoints.json") {
|
|
12
|
+
return path.join(resolveRuntimeRoot(dataRoot), fileName);
|
|
13
|
+
}
|
|
14
|
+
export function resolveKnowledgeRoot(dataRoot) {
|
|
15
|
+
return path.join(dataRoot, "knowledge");
|
|
16
|
+
}
|
|
17
|
+
export function resolveKnowledgeStorePath(dataRoot, fileName = "records.sqlite") {
|
|
18
|
+
return path.join(resolveKnowledgeRoot(dataRoot), fileName);
|
|
19
|
+
}
|
|
20
|
+
export function resolveKnowledgeFileStorePath(dataRoot, fileName = "records.json") {
|
|
21
|
+
return path.join(resolveKnowledgeRoot(dataRoot), fileName);
|
|
22
|
+
}
|
|
@@ -5,7 +5,7 @@ import { createClient } from "@libsql/client";
|
|
|
5
5
|
import { LibSQLVectorStore } from "@langchain/community/vectorstores/libsql";
|
|
6
6
|
import { QdrantClient } from "@qdrant/js-client-rest";
|
|
7
7
|
import { compileVectorStore } from "../../workspace/resource-compilers.js";
|
|
8
|
-
import { resolveRefId } from "../../workspace/support/workspace-ref-utils.js";
|
|
8
|
+
import { getRuntimeStorageRoots, resolveRefId } from "../../workspace/support/workspace-ref-utils.js";
|
|
9
9
|
import { resolveCompiledEmbeddingModel, resolveCompiledEmbeddingModelRef } from "./embedding-models.js";
|
|
10
10
|
import { createLlamaIndexVectorStore } from "./llamaindex.js";
|
|
11
11
|
function resolveFileUrl(rawUrl, workspaceRoot) {
|
|
@@ -92,10 +92,11 @@ export async function resolveCompiledVectorStore(workspace, vectorStore, options
|
|
|
92
92
|
if (options.vectorStoreResolver) {
|
|
93
93
|
return options.vectorStoreResolver(vectorStore.id);
|
|
94
94
|
}
|
|
95
|
+
const { dataRoot } = getRuntimeStorageRoots(workspace.refs, workspace.workspaceRoot);
|
|
95
96
|
if (vectorStore.kind === "LlamaIndexSimpleVectorStore") {
|
|
96
97
|
const embeddingModel = resolveCompiledEmbeddingModelRef(workspace, vectorStore.embeddingModelRef);
|
|
97
98
|
const embeddings = await resolveCompiledEmbeddingModel(embeddingModel, options.embeddingModelResolver);
|
|
98
|
-
return createLlamaIndexVectorStore(
|
|
99
|
+
return createLlamaIndexVectorStore(dataRoot, vectorStore, embeddings);
|
|
99
100
|
}
|
|
100
101
|
if (vectorStore.kind === "QdrantVectorStore") {
|
|
101
102
|
const embeddingModel = resolveCompiledEmbeddingModelRef(workspace, vectorStore.embeddingModelRef);
|
|
@@ -178,7 +179,7 @@ export async function resolveCompiledVectorStore(workspace, vectorStore, options
|
|
|
178
179
|
const embeddingModel = resolveCompiledEmbeddingModelRef(workspace, vectorStore.embeddingModelRef);
|
|
179
180
|
const embeddings = await resolveCompiledEmbeddingModel(embeddingModel, options.embeddingModelResolver);
|
|
180
181
|
const db = createClient({
|
|
181
|
-
url: await ensureFileUrlDirectory(vectorStore.url ?? "",
|
|
182
|
+
url: await ensureFileUrlDirectory(vectorStore.url ?? "", dataRoot),
|
|
182
183
|
...(vectorStore.authToken ? { authToken: vectorStore.authToken } : {}),
|
|
183
184
|
});
|
|
184
185
|
const table = vectorStore.table ?? "vectors";
|
|
@@ -5,7 +5,7 @@ import { compileModel, compileTool } from "./resource-compilers.js";
|
|
|
5
5
|
import { inferAgentCapabilities } from "./support/agent-capabilities.js";
|
|
6
6
|
import { getAgentExecutionConfigValue, getAgentExecutionObject, getAgentExecutionString } from "./support/agent-execution-config.js";
|
|
7
7
|
import { discoverSkillPaths } from "./support/discovery.js";
|
|
8
|
-
import { compileAgentMemories, getResilienceConfig, getRuntimeDefaults, getRuntimeMemoryDefaults, getWorkspaceObject, resolvePromptValue, resolveRefId } from "./support/workspace-ref-utils.js";
|
|
8
|
+
import { compileAgentMemories, getResilienceConfig, getRuntimeDefaults, getRuntimeMemoryDefaults, getRuntimeStorageRoots, getWorkspaceObject, resolvePromptValue, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
9
9
|
const WORKSPACE_BOUNDARY_GUIDANCE = "Keep repository and file exploration bounded to the current workspace root unless the user explicitly asks for broader host or filesystem access. " +
|
|
10
10
|
"Do not inspect absolute paths outside the workspace, system directories, or unrelated repos by default. " +
|
|
11
11
|
"Prefer workspace-local tools, relative paths, and the current repository checkout when analyzing code.";
|
|
@@ -339,6 +339,7 @@ function resolveRuntimeMemoryConfig(agent, refs) {
|
|
|
339
339
|
export function compileBinding(workspaceRoot, agent, agents, referencedSubagentIds, refs, models, tools) {
|
|
340
340
|
const internalSubagent = referencedSubagentIds.has(agent.id);
|
|
341
341
|
const runtimeDefaults = getRuntimeDefaults(refs);
|
|
342
|
+
const runtimeStorage = getRuntimeStorageRoots(refs, workspaceRoot);
|
|
342
343
|
const resilience = getResilienceConfig(refs);
|
|
343
344
|
const compiledAgentSkills = compileAgentSkills(workspaceRoot, agent);
|
|
344
345
|
const compiledAgentMemory = compileAgentMemories(workspaceRoot, agent.memorySources);
|
|
@@ -361,15 +362,16 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
361
362
|
? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
|
|
362
363
|
: undefined;
|
|
363
364
|
const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
|
|
364
|
-
? path.resolve(
|
|
365
|
-
:
|
|
366
|
-
? path.resolve(workspaceRoot, runtimeDefaults.runRoot)
|
|
367
|
-
: path.join(workspaceRoot, "run-data");
|
|
365
|
+
? (path.isAbsolute(agent.runRoot) ? agent.runRoot : path.resolve(runtimeStorage.dataRoot, agent.runRoot))
|
|
366
|
+
: runtimeStorage.dataRoot;
|
|
368
367
|
const base = {
|
|
369
368
|
agent,
|
|
370
369
|
harnessRuntime: {
|
|
370
|
+
applicationRoot: runtimeStorage.applicationRoot,
|
|
371
|
+
dataRoot: runtimeStorage.dataRoot,
|
|
372
|
+
runtimeProfile: runtimeStorage.runtimeProfile,
|
|
371
373
|
runRoot,
|
|
372
|
-
workspaceRoot,
|
|
374
|
+
workspaceRoot: runtimeStorage.applicationRoot,
|
|
373
375
|
capabilities: inferAgentCapabilities(agent),
|
|
374
376
|
resilience,
|
|
375
377
|
...(runtimeGovernanceDefaults ? { governance: runtimeGovernanceDefaults } : {}),
|
|
@@ -10,7 +10,7 @@ import { validateAgent, validateTopology } from "./validate.js";
|
|
|
10
10
|
import { compileBinding } from "./agent-binding-compiler.js";
|
|
11
11
|
import { discoverSubagents, ensureDiscoverySources } from "./support/discovery.js";
|
|
12
12
|
import { collectAgentDiscoverySourceRefs, collectToolSourceRefs } from "./support/source-collectors.js";
|
|
13
|
-
import { getRoutingDefaultAgentId, getRuntimeResources, getToolModuleDiscoveryConfig, getRoutingRules, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
13
|
+
import { getRoutingDefaultAgentId, getRuntimeResources, getRuntimeStorageRoots, getToolModuleDiscoveryConfig, getRoutingRules, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
14
14
|
import { hydrateAgentMcpTools, hydrateResourceAndExternalTools } from "./tool-hydration.js";
|
|
15
15
|
import { traceStartupStage } from "../runtime/startup-tracing.js";
|
|
16
16
|
import { shouldSkipScanDirectory } from "../utils/fs.js";
|
|
@@ -209,6 +209,11 @@ export async function loadWorkspace(workspaceRoot, options = {}) {
|
|
|
209
209
|
const loaded = await traceStartupStage("workspace.load.objects", () => loadWorkspaceObjects(workspaceRoot, options), {
|
|
210
210
|
workspaceRoot,
|
|
211
211
|
});
|
|
212
|
+
const runtimeStorage = getRuntimeStorageRoots(loaded.refs, workspaceRoot);
|
|
213
|
+
if (path.resolve(runtimeStorage.applicationRoot) !== path.resolve(workspaceRoot)) {
|
|
214
|
+
throw new Error(`Runtime applicationRoot ${runtimeStorage.applicationRoot} must resolve to the loaded workspace root ${workspaceRoot}. ` +
|
|
215
|
+
"Load the shared application folder as the workspace root and use Runtime.dataRoot for writable profile data.");
|
|
216
|
+
}
|
|
212
217
|
loaded.agents = await traceStartupStage("workspace.discover.subagents", () => discoverSubagents(loaded.agents, workspaceRoot), {
|
|
213
218
|
workspaceRoot,
|
|
214
219
|
});
|
|
@@ -516,6 +516,9 @@ export function parseAgentItem(item, sourcePath) {
|
|
|
516
516
|
description: String(normalizedItem.description ?? ""),
|
|
517
517
|
modelRef: readExecutionValue(normalizedItem, "modelRef", readSingleRef) ?? "",
|
|
518
518
|
runRoot: typeof runtime?.runRoot === "string" ? runtime.runRoot : undefined,
|
|
519
|
+
applicationRoot: typeof runtime?.applicationRoot === "string" ? runtime.applicationRoot : undefined,
|
|
520
|
+
dataRoot: typeof runtime?.dataRoot === "string" ? runtime.dataRoot : undefined,
|
|
521
|
+
runtimeProfile: typeof runtime?.profile === "string" ? runtime.profile : undefined,
|
|
519
522
|
toolRefs: toolBindings.map((binding) => binding.ref),
|
|
520
523
|
toolBindings,
|
|
521
524
|
inlineTools: undefined,
|
|
@@ -37,6 +37,12 @@ export type ToolModuleDiscoveryConfig = {
|
|
|
37
37
|
};
|
|
38
38
|
export declare function getWorkspaceObject(refs: Map<string, WorkspaceObject | ParsedAgentObject>, ref: string | undefined): WorkspaceObject | undefined;
|
|
39
39
|
export declare function getRuntimeDefaults(refs: Map<string, WorkspaceObject | ParsedAgentObject>): Record<string, unknown> | undefined;
|
|
40
|
+
export type RuntimeStorageRoots = {
|
|
41
|
+
applicationRoot: string;
|
|
42
|
+
dataRoot: string;
|
|
43
|
+
runtimeProfile: string;
|
|
44
|
+
};
|
|
45
|
+
export declare function getRuntimeStorageRoots(refs: Map<string, WorkspaceObject | ParsedAgentObject>, workspaceRoot: string): RuntimeStorageRoots;
|
|
40
46
|
export declare function getRuntimeResources(refs: Map<string, WorkspaceObject | ParsedAgentObject>): string[];
|
|
41
47
|
export declare function getToolModuleDiscoveryConfig(refs: Map<string, WorkspaceObject | ParsedAgentObject>): ToolModuleDiscoveryConfig;
|
|
42
48
|
export declare function getRuntimeMemoryDefaults(refs: Map<string, WorkspaceObject | ParsedAgentObject>): Record<string, unknown> | undefined;
|
|
@@ -26,6 +26,31 @@ export function getRuntimeDefaults(refs) {
|
|
|
26
26
|
}
|
|
27
27
|
return runtimes[0].value;
|
|
28
28
|
}
|
|
29
|
+
function asNonEmptyString(value) {
|
|
30
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
31
|
+
}
|
|
32
|
+
export function getRuntimeStorageRoots(refs, workspaceRoot) {
|
|
33
|
+
const runtimeDefaults = getRuntimeDefaults(refs);
|
|
34
|
+
const configuredApplicationRoot = asNonEmptyString(runtimeDefaults?.applicationRoot);
|
|
35
|
+
const configuredDataRoot = asNonEmptyString(runtimeDefaults?.dataRoot);
|
|
36
|
+
const configuredProfile = asNonEmptyString(runtimeDefaults?.profile);
|
|
37
|
+
const applicationRoot = configuredApplicationRoot
|
|
38
|
+
? (path.isAbsolute(configuredApplicationRoot)
|
|
39
|
+
? configuredApplicationRoot
|
|
40
|
+
: path.resolve(workspaceRoot, configuredApplicationRoot))
|
|
41
|
+
: workspaceRoot;
|
|
42
|
+
const dataRoot = configuredDataRoot
|
|
43
|
+
? (path.isAbsolute(configuredDataRoot)
|
|
44
|
+
? configuredDataRoot
|
|
45
|
+
: path.resolve(applicationRoot, configuredDataRoot))
|
|
46
|
+
: path.join(applicationRoot, ".agent");
|
|
47
|
+
const runtimeProfile = configuredProfile ?? "default";
|
|
48
|
+
return {
|
|
49
|
+
applicationRoot,
|
|
50
|
+
dataRoot,
|
|
51
|
+
runtimeProfile,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
29
54
|
export function getRuntimeResources(refs) {
|
|
30
55
|
const runtimeDefaults = getRuntimeDefaults(refs);
|
|
31
56
|
if (!Array.isArray(runtimeDefaults?.resources)) {
|