@botbotgo/agent-harness 0.0.250 → 0.0.252
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 +13 -14
- package/README.zh.md +11 -12
- package/dist/api.d.ts +13 -6
- package/dist/api.js +70 -6
- package/dist/config/agents/direct.yaml +3 -3
- package/dist/config/agents/orchestra.yaml +3 -3
- package/dist/config/catalogs/stores.yaml +3 -9
- package/dist/config/runtime/workspace.yaml +1 -2
- package/dist/contracts/runtime.d.ts +9 -14
- package/dist/flow/build-flow-graph.js +198 -67
- package/dist/flow/export-mermaid.js +314 -4
- package/dist/flow/export-sequence-mermaid.js +149 -2
- package/dist/flow/types.d.ts +11 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +3 -2
- package/dist/persistence/file-store.js +34 -8
- package/dist/persistence/sqlite-store.d.ts +2 -2
- package/dist/persistence/sqlite-store.js +64 -11
- package/dist/persistence/types.d.ts +3 -3
- package/dist/protocol/a2a/http.js +2 -4
- package/dist/resource/isolation.js +30 -2
- package/dist/resource/resource-impl.js +1 -4
- package/dist/runtime/harness/events/streaming.js +8 -8
- package/dist/runtime/harness/run/inspection.d.ts +2 -0
- package/dist/runtime/harness/run/inspection.js +91 -46
- package/dist/runtime/harness/run/stream-run.d.ts +2 -2
- package/dist/runtime/harness/run/stream-run.js +34 -23
- package/dist/runtime/harness/run/surface-semantics.d.ts +14 -0
- package/dist/runtime/harness/run/surface-semantics.js +106 -0
- package/dist/runtime/harness/run/thread-records.js +2 -34
- package/dist/runtime/harness/system/store.d.ts +6 -4
- package/dist/runtime/harness/system/store.js +76 -42
- package/dist/runtime/harness.js +7 -7
- package/dist/runtime/maintenance/checkpoint-maintenance.js +4 -119
- package/dist/runtime/maintenance/index.d.ts +0 -1
- package/dist/runtime/maintenance/index.js +0 -1
- package/dist/runtime/support/runtime-env.d.ts +1 -0
- package/dist/runtime/support/runtime-env.js +5 -0
- package/dist/runtime/support/runtime-factories.js +2 -42
- package/dist/upstream-events.js +14 -0
- package/package.json +1 -3
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +0 -9
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +0 -39
- package/dist/runtime/support/sqlite-drivers.d.ts +0 -12
- package/dist/runtime/support/sqlite-drivers.js +0 -24
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { rm } from "node:fs/promises";
|
|
3
|
-
import { readdir } from "node:fs/promises";
|
|
2
|
+
import { appendFile, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
4
3
|
import { ensureDir, fileExists, readJson, writeJson } from "../utils/fs.js";
|
|
5
4
|
function nowIso() {
|
|
6
5
|
return new Date(Date.now()).toISOString();
|
|
@@ -25,6 +24,9 @@ export class FilePersistence {
|
|
|
25
24
|
runControlPath(runId) {
|
|
26
25
|
return path.join(this.runRoot, "indexes", "run-control", `${runId}.json`);
|
|
27
26
|
}
|
|
27
|
+
traceItemsPath(threadId, runId) {
|
|
28
|
+
return path.join(this.runDir(threadId, runId), "trace-items.ndjson");
|
|
29
|
+
}
|
|
28
30
|
async initialize() {
|
|
29
31
|
await Promise.all([
|
|
30
32
|
"indexes/threads",
|
|
@@ -93,12 +95,13 @@ export class FilePersistence {
|
|
|
93
95
|
currentAgentId: input.currentAgentId ?? input.agentId,
|
|
94
96
|
delegationChain: input.delegationChain ?? [input.currentAgentId ?? input.agentId],
|
|
95
97
|
runtimeSnapshot: input.runtimeSnapshot ?? null,
|
|
96
|
-
|
|
98
|
+
traceItems: [],
|
|
97
99
|
};
|
|
98
100
|
await Promise.all([
|
|
99
101
|
writeJson(path.join(runDir, "meta.json"), meta),
|
|
100
102
|
writeJson(path.join(runDir, "lifecycle.json"), lifecycle),
|
|
101
103
|
writeJson(path.join(runDir, "inspection.json"), inspection),
|
|
104
|
+
writeFile(this.traceItemsPath(input.threadId, input.runId), "", "utf8"),
|
|
102
105
|
writeJson(path.join(runDir, "checkpoint-ref.json"), {
|
|
103
106
|
threadId: input.threadId,
|
|
104
107
|
runId: input.runId,
|
|
@@ -401,14 +404,17 @@ export class FilePersistence {
|
|
|
401
404
|
const inspection = await readJson(path.join(this.runDir(threadId, runId), "inspection.json"));
|
|
402
405
|
return {
|
|
403
406
|
...inspection,
|
|
404
|
-
|
|
407
|
+
traceItems: (await this.listRunTraceItems(threadId, runId))
|
|
408
|
+
?? (Array.isArray(inspection.traceItems)
|
|
409
|
+
? inspection.traceItems
|
|
410
|
+
: Array.isArray(inspection.upstreamEvents)
|
|
411
|
+
? inspection.upstreamEvents
|
|
412
|
+
: []),
|
|
405
413
|
};
|
|
406
414
|
}
|
|
407
415
|
async updateRunInspection(threadId, runId, patch) {
|
|
408
416
|
const inspectionPath = path.join(this.runDir(threadId, runId), "inspection.json");
|
|
409
|
-
const current = await
|
|
410
|
-
const nextUpstreamEvents = patch.upstreamEvents
|
|
411
|
-
?? (patch.appendUpstreamEvent === undefined ? current.upstreamEvents : [...current.upstreamEvents, patch.appendUpstreamEvent]);
|
|
417
|
+
const current = await readJson(inspectionPath);
|
|
412
418
|
await writeJson(inspectionPath, {
|
|
413
419
|
...current,
|
|
414
420
|
...(patch.endedAt !== undefined ? { endedAt: patch.endedAt } : {}),
|
|
@@ -416,9 +422,29 @@ export class FilePersistence {
|
|
|
416
422
|
...(patch.currentAgentId !== undefined ? { currentAgentId: patch.currentAgentId } : {}),
|
|
417
423
|
...(patch.delegationChain ? { delegationChain: patch.delegationChain } : {}),
|
|
418
424
|
...(patch.runtimeSnapshot !== undefined ? { runtimeSnapshot: patch.runtimeSnapshot } : {}),
|
|
419
|
-
|
|
425
|
+
traceItems: Array.isArray(current.traceItems) ? current.traceItems : [],
|
|
420
426
|
});
|
|
421
427
|
}
|
|
428
|
+
async appendRunTraceItem(threadId, runId, item) {
|
|
429
|
+
await appendFile(this.traceItemsPath(threadId, runId), `${JSON.stringify(item)}\n`, "utf8");
|
|
430
|
+
}
|
|
431
|
+
async listRunTraceItems(threadId, runId) {
|
|
432
|
+
const traceItemsPath = this.traceItemsPath(threadId, runId);
|
|
433
|
+
if (await fileExists(traceItemsPath)) {
|
|
434
|
+
const contents = await readFile(traceItemsPath, "utf8");
|
|
435
|
+
return contents
|
|
436
|
+
.split("\n")
|
|
437
|
+
.map((line) => line.trim())
|
|
438
|
+
.filter((line) => line.length > 0)
|
|
439
|
+
.map((line) => JSON.parse(line));
|
|
440
|
+
}
|
|
441
|
+
const inspection = await readJson(path.join(this.runDir(threadId, runId), "inspection.json"));
|
|
442
|
+
return Array.isArray(inspection.traceItems)
|
|
443
|
+
? inspection.traceItems
|
|
444
|
+
: Array.isArray(inspection.upstreamEvents)
|
|
445
|
+
? inspection.upstreamEvents
|
|
446
|
+
: [];
|
|
447
|
+
}
|
|
422
448
|
async deleteThread(threadId) {
|
|
423
449
|
const threadDir = this.threadDir(threadId);
|
|
424
450
|
const threadIndexPath = this.threadIndexPath(threadId);
|
|
@@ -82,9 +82,9 @@ export declare class SqlitePersistence implements RuntimePersistence {
|
|
|
82
82
|
currentAgentId?: string | null;
|
|
83
83
|
delegationChain?: string[];
|
|
84
84
|
runtimeSnapshot?: RunSummary["runtimeSnapshot"] | null;
|
|
85
|
-
upstreamEvents?: unknown[];
|
|
86
|
-
appendUpstreamEvent?: unknown;
|
|
87
85
|
}): Promise<void>;
|
|
86
|
+
appendRunTraceItem(threadId: string, runId: string, item: unknown): Promise<void>;
|
|
87
|
+
listRunTraceItems(threadId: string, runId: string): Promise<unknown[]>;
|
|
88
88
|
deleteThread(threadId: string): Promise<boolean>;
|
|
89
89
|
saveRunRequest(threadId: string, runId: string, request: PersistedRunRequest): Promise<void>;
|
|
90
90
|
getRunRequest(threadId: string, runId: string): Promise<PersistedRunRequest | null>;
|
|
@@ -4,7 +4,7 @@ import { createClient } from "@libsql/client";
|
|
|
4
4
|
import { fileExists, readJson, writeJson } from "../utils/fs.js";
|
|
5
5
|
import { SqliteRunContextStore } from "./sqlite-run-context-store.js";
|
|
6
6
|
import { SqliteRunQueueStore } from "./sqlite-run-queue-store.js";
|
|
7
|
-
const RUNTIME_SQLITE_SCHEMA_VERSION =
|
|
7
|
+
const RUNTIME_SQLITE_SCHEMA_VERSION = 6;
|
|
8
8
|
const RUNTIME_SQLITE_SCHEMA_FAMILY = "agent-harness-runtime";
|
|
9
9
|
function asRow(value) {
|
|
10
10
|
return value;
|
|
@@ -196,11 +196,24 @@ export class SqlitePersistence {
|
|
|
196
196
|
FOREIGN KEY (thread_id) REFERENCES threads(thread_id),
|
|
197
197
|
FOREIGN KEY (run_id) REFERENCES runs(run_id)
|
|
198
198
|
)
|
|
199
|
+
`);
|
|
200
|
+
await this.rawExecute(`
|
|
201
|
+
CREATE TABLE IF NOT EXISTS run_trace_items (
|
|
202
|
+
trace_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
203
|
+
run_id TEXT NOT NULL,
|
|
204
|
+
thread_id TEXT NOT NULL,
|
|
205
|
+
item_json TEXT NOT NULL,
|
|
206
|
+
created_at TEXT NOT NULL,
|
|
207
|
+
FOREIGN KEY (thread_id) REFERENCES threads(thread_id),
|
|
208
|
+
FOREIGN KEY (run_id) REFERENCES runs(run_id)
|
|
209
|
+
)
|
|
199
210
|
`);
|
|
200
211
|
await this.rawExecute("CREATE INDEX IF NOT EXISTS runs_thread_updated_idx ON runs(thread_id, updated_at DESC)");
|
|
212
|
+
await this.rawExecute("CREATE INDEX IF NOT EXISTS runs_thread_created_idx ON runs(thread_id, created_at DESC)");
|
|
201
213
|
await this.rawExecute("CREATE INDEX IF NOT EXISTS runs_state_updated_idx ON runs(state, updated_at DESC)");
|
|
202
214
|
await this.rawExecute("CREATE INDEX IF NOT EXISTS runs_agent_updated_idx ON runs(agent_id, updated_at DESC)");
|
|
203
215
|
await this.rawExecute("CREATE INDEX IF NOT EXISTS run_inspection_thread_activity_idx ON run_inspection(thread_id, last_activity_at DESC)");
|
|
216
|
+
await this.rawExecute("CREATE INDEX IF NOT EXISTS run_trace_items_thread_run_trace_idx ON run_trace_items(thread_id, run_id, trace_id)");
|
|
204
217
|
await this.rawExecute(`
|
|
205
218
|
CREATE TABLE IF NOT EXISTS thread_messages (
|
|
206
219
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -491,6 +504,23 @@ export class SqlitePersistence {
|
|
|
491
504
|
await this.rawExecute("INSERT OR REPLACE INTO runtime_metadata (key, value) VALUES (?, ?)", ["schema_version", String(RUNTIME_SQLITE_SCHEMA_VERSION)]);
|
|
492
505
|
return;
|
|
493
506
|
}
|
|
507
|
+
if (version === "5") {
|
|
508
|
+
await this.rawExecute(`
|
|
509
|
+
CREATE TABLE IF NOT EXISTS run_trace_items (
|
|
510
|
+
trace_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
511
|
+
run_id TEXT NOT NULL,
|
|
512
|
+
thread_id TEXT NOT NULL,
|
|
513
|
+
item_json TEXT NOT NULL,
|
|
514
|
+
created_at TEXT NOT NULL,
|
|
515
|
+
FOREIGN KEY (thread_id) REFERENCES threads(thread_id),
|
|
516
|
+
FOREIGN KEY (run_id) REFERENCES runs(run_id)
|
|
517
|
+
)
|
|
518
|
+
`);
|
|
519
|
+
await this.rawExecute("CREATE INDEX IF NOT EXISTS runs_thread_created_idx ON runs(thread_id, created_at DESC)");
|
|
520
|
+
await this.rawExecute("CREATE INDEX IF NOT EXISTS run_trace_items_thread_run_trace_idx ON run_trace_items(thread_id, run_id, trace_id)");
|
|
521
|
+
await this.rawExecute("INSERT OR REPLACE INTO runtime_metadata (key, value) VALUES (?, ?)", ["schema_version", String(RUNTIME_SQLITE_SCHEMA_VERSION)]);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
494
524
|
if (version !== String(RUNTIME_SQLITE_SCHEMA_VERSION)) {
|
|
495
525
|
throw new Error(`Unsupported runtime sqlite schema version ${JSON.stringify(version)} in ${this.dbPath}. Expected ${RUNTIME_SQLITE_SCHEMA_VERSION}.`);
|
|
496
526
|
}
|
|
@@ -830,26 +860,48 @@ export class SqlitePersistence {
|
|
|
830
860
|
currentAgentId: asNullableString(row.current_agent_id),
|
|
831
861
|
delegationChain: parseJson(row.delegation_chain_json),
|
|
832
862
|
runtimeSnapshot: row.runtime_snapshot_json ? parseJson(row.runtime_snapshot_json) : null,
|
|
833
|
-
|
|
863
|
+
traceItems: await this.listRunTraceItems(threadId, runId),
|
|
834
864
|
};
|
|
835
865
|
}
|
|
836
866
|
async updateRunInspection(threadId, runId, patch) {
|
|
837
|
-
const
|
|
838
|
-
|
|
839
|
-
|
|
867
|
+
const row = await this.selectOne(`SELECT ended_at, last_activity_at, current_agent_id, delegation_chain_json, runtime_snapshot_json
|
|
868
|
+
FROM run_inspection
|
|
869
|
+
WHERE run_id = ? AND thread_id = ?`, [runId, threadId]);
|
|
870
|
+
if (!row) {
|
|
871
|
+
throw new Error(`Missing run inspection ${runId} for thread ${threadId}`);
|
|
872
|
+
}
|
|
840
873
|
await this.execute(`UPDATE run_inspection
|
|
841
874
|
SET ended_at = ?, last_activity_at = ?, current_agent_id = ?, delegation_chain_json = ?, runtime_snapshot_json = ?, upstream_events_json = ?
|
|
842
875
|
WHERE run_id = ? AND thread_id = ?`, [
|
|
843
|
-
patch.endedAt === undefined ?
|
|
844
|
-
patch.lastActivityAt ??
|
|
845
|
-
patch.currentAgentId === undefined ?
|
|
846
|
-
JSON.stringify(patch.delegationChain ??
|
|
847
|
-
JSON.stringify(patch.runtimeSnapshot === undefined
|
|
848
|
-
|
|
876
|
+
patch.endedAt === undefined ? asNullableString(row.ended_at) : patch.endedAt,
|
|
877
|
+
patch.lastActivityAt ?? asString(row.last_activity_at),
|
|
878
|
+
patch.currentAgentId === undefined ? asNullableString(row.current_agent_id) : patch.currentAgentId,
|
|
879
|
+
JSON.stringify(patch.delegationChain ?? parseJson(row.delegation_chain_json)),
|
|
880
|
+
JSON.stringify(patch.runtimeSnapshot === undefined
|
|
881
|
+
? (row.runtime_snapshot_json ? parseJson(row.runtime_snapshot_json) : null)
|
|
882
|
+
: patch.runtimeSnapshot),
|
|
883
|
+
"[]",
|
|
849
884
|
runId,
|
|
850
885
|
threadId,
|
|
851
886
|
]);
|
|
852
887
|
}
|
|
888
|
+
async appendRunTraceItem(threadId, runId, item) {
|
|
889
|
+
await this.execute(`INSERT INTO run_trace_items (run_id, thread_id, item_json, created_at)
|
|
890
|
+
VALUES (?, ?, ?, ?)`, [runId, threadId, JSON.stringify(item), nowIso()]);
|
|
891
|
+
}
|
|
892
|
+
async listRunTraceItems(threadId, runId) {
|
|
893
|
+
const rows = await this.selectAll(`SELECT item_json
|
|
894
|
+
FROM run_trace_items
|
|
895
|
+
WHERE thread_id = ? AND run_id = ?
|
|
896
|
+
ORDER BY trace_id ASC`, [threadId, runId]);
|
|
897
|
+
if (rows.length > 0) {
|
|
898
|
+
return rows.map((row) => parseJson(row.item_json));
|
|
899
|
+
}
|
|
900
|
+
const row = await this.selectOne(`SELECT upstream_events_json
|
|
901
|
+
FROM run_inspection
|
|
902
|
+
WHERE thread_id = ? AND run_id = ?`, [threadId, runId]);
|
|
903
|
+
return row?.upstream_events_json ? parseJson(row.upstream_events_json) : [];
|
|
904
|
+
}
|
|
853
905
|
async deleteThread(threadId) {
|
|
854
906
|
const exists = await this.getSession(threadId);
|
|
855
907
|
if (!exists) {
|
|
@@ -858,6 +910,7 @@ export class SqlitePersistence {
|
|
|
858
910
|
await this.execute("DELETE FROM artifacts WHERE thread_id = ?", [threadId]);
|
|
859
911
|
await this.execute("DELETE FROM approvals WHERE thread_id = ?", [threadId]);
|
|
860
912
|
await this.execute("DELETE FROM events WHERE thread_id = ?", [threadId]);
|
|
913
|
+
await this.execute("DELETE FROM run_trace_items WHERE thread_id = ?", [threadId]);
|
|
861
914
|
await this.execute("DELETE FROM run_inspection WHERE thread_id = ?", [threadId]);
|
|
862
915
|
await this.execute("DELETE FROM run_queue WHERE thread_id = ?", [threadId]);
|
|
863
916
|
await this.execute("DELETE FROM run_requests WHERE thread_id = ?", [threadId]);
|
|
@@ -33,7 +33,7 @@ export type PersistedRunInspection = {
|
|
|
33
33
|
currentAgentId: string | null;
|
|
34
34
|
delegationChain: string[];
|
|
35
35
|
runtimeSnapshot: RuntimeSnapshot | null;
|
|
36
|
-
|
|
36
|
+
traceItems: unknown[];
|
|
37
37
|
};
|
|
38
38
|
export type PersistedRunRequest = {
|
|
39
39
|
input: MessageContent;
|
|
@@ -142,15 +142,15 @@ export interface RuntimePersistence {
|
|
|
142
142
|
getRunMeta(threadId: string, runId: string): Promise<PersistenceRunMeta>;
|
|
143
143
|
getRunLifecycle(threadId: string, runId: string): Promise<PersistenceLifecycle>;
|
|
144
144
|
getRunInspection(threadId: string, runId: string): Promise<PersistedRunInspection>;
|
|
145
|
+
listRunTraceItems(threadId: string, runId: string): Promise<unknown[]>;
|
|
145
146
|
updateRunInspection(threadId: string, runId: string, patch: {
|
|
146
147
|
endedAt?: string | null;
|
|
147
148
|
lastActivityAt?: string;
|
|
148
149
|
currentAgentId?: string | null;
|
|
149
150
|
delegationChain?: string[];
|
|
150
151
|
runtimeSnapshot?: RuntimeSnapshot | null;
|
|
151
|
-
upstreamEvents?: unknown[];
|
|
152
|
-
appendUpstreamEvent?: unknown;
|
|
153
152
|
}): Promise<void>;
|
|
153
|
+
appendRunTraceItem(threadId: string, runId: string, item: unknown): Promise<void>;
|
|
154
154
|
deleteThread(threadId: string): Promise<boolean>;
|
|
155
155
|
saveRunRequest(threadId: string, runId: string, request: PersistedRunRequest): Promise<void>;
|
|
156
156
|
getRunRequest(threadId: string, runId: string): Promise<PersistedRunRequest | null>;
|
|
@@ -382,8 +382,7 @@ function toSessionRecord(session) {
|
|
|
382
382
|
currentAgentId: run.currentAgentId,
|
|
383
383
|
delegationChain: run.delegationChain,
|
|
384
384
|
runtimeSnapshot: run.runtimeSnapshot,
|
|
385
|
-
|
|
386
|
-
history: run.history,
|
|
385
|
+
traceItems: run.traceItems,
|
|
387
386
|
runtimeTimeline: run.runtimeTimeline,
|
|
388
387
|
})),
|
|
389
388
|
pendingDecision: session.pendingDecision,
|
|
@@ -410,8 +409,7 @@ function toRequestRecord(request) {
|
|
|
410
409
|
currentAgentId: request.currentAgentId,
|
|
411
410
|
delegationChain: request.delegationChain,
|
|
412
411
|
runtimeSnapshot: request.runtimeSnapshot,
|
|
413
|
-
|
|
414
|
-
history: request.history,
|
|
412
|
+
traceItems: request.traceItems,
|
|
415
413
|
runtimeTimeline: request.runtimeTimeline,
|
|
416
414
|
};
|
|
417
415
|
}
|
|
@@ -29,11 +29,39 @@ function dependencyLinkPath(isolatedRoot, dependencyName) {
|
|
|
29
29
|
function dependencyPackageRoot(packageJsonPath) {
|
|
30
30
|
return path.dirname(packageJsonPath);
|
|
31
31
|
}
|
|
32
|
-
function
|
|
32
|
+
function declaredDependencySpec(manifest, dependencyName) {
|
|
33
|
+
return manifest.dependencies?.[dependencyName]
|
|
34
|
+
?? manifest.optionalDependencies?.[dependencyName]
|
|
35
|
+
?? manifest.peerDependencies?.[dependencyName]
|
|
36
|
+
?? null;
|
|
37
|
+
}
|
|
38
|
+
function resolveDeclaredFileDependency(packageRoot, spec) {
|
|
39
|
+
if (!spec.startsWith("file:")) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const relativePath = spec.slice("file:".length).trim();
|
|
43
|
+
if (!relativePath) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const resolvedPath = path.resolve(packageRoot, relativePath);
|
|
47
|
+
const packageJsonPath = resolvedPath.endsWith("package.json")
|
|
48
|
+
? resolvedPath
|
|
49
|
+
: path.join(resolvedPath, "package.json");
|
|
50
|
+
if (!existsSync(packageJsonPath)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return dependencyPackageRoot(packageJsonPath);
|
|
54
|
+
}
|
|
55
|
+
function resolveDeclaredDependency(packageRoot, manifest, dependencyName) {
|
|
33
56
|
const localPath = path.join(packageRoot, "node_modules", ...dependencyName.split("/"), "package.json");
|
|
34
57
|
if (existsSync(localPath)) {
|
|
35
58
|
return dependencyPackageRoot(localPath);
|
|
36
59
|
}
|
|
60
|
+
const declaredSpec = declaredDependencySpec(manifest, dependencyName);
|
|
61
|
+
const localFileDependency = declaredSpec ? resolveDeclaredFileDependency(packageRoot, declaredSpec) : null;
|
|
62
|
+
if (localFileDependency) {
|
|
63
|
+
return localFileDependency;
|
|
64
|
+
}
|
|
37
65
|
try {
|
|
38
66
|
const requireFromPackage = createRequire(path.join(packageRoot, "package.json"));
|
|
39
67
|
return dependencyPackageRoot(requireFromPackage.resolve(`${dependencyName}/package.json`));
|
|
@@ -44,7 +72,7 @@ function resolveDeclaredDependency(packageRoot, dependencyName) {
|
|
|
44
72
|
}
|
|
45
73
|
async function linkDeclaredDependencies(isolatedRoot, packageRoot, manifest) {
|
|
46
74
|
for (const dependencyName of declaredDependencyNames(manifest)) {
|
|
47
|
-
const resolved = resolveDeclaredDependency(packageRoot, dependencyName);
|
|
75
|
+
const resolved = resolveDeclaredDependency(packageRoot, manifest, dependencyName);
|
|
48
76
|
if (!resolved) {
|
|
49
77
|
continue;
|
|
50
78
|
}
|
|
@@ -418,10 +418,7 @@ async function runFunctionToolInSubprocess(config, input, context) {
|
|
|
418
418
|
return await new Promise((resolve, reject) => {
|
|
419
419
|
const child = spawn(config.command, config.args, {
|
|
420
420
|
cwd: config.cwd,
|
|
421
|
-
env:
|
|
422
|
-
...process.env,
|
|
423
|
-
...(config.env ?? {}),
|
|
424
|
-
},
|
|
421
|
+
env: createRuntimeEnv(config.env, process.env),
|
|
425
422
|
stdio: ["pipe", "pipe", "pipe"],
|
|
426
423
|
});
|
|
427
424
|
let stdout = "";
|
|
@@ -42,14 +42,14 @@ export async function dispatchRunListeners(stream, listeners, options) {
|
|
|
42
42
|
}
|
|
43
43
|
if (item.type === "upstream-event") {
|
|
44
44
|
await options.notifyListener(listeners.onUpstreamEvent, item.event);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
45
|
+
if (item.surfaceItem) {
|
|
46
|
+
await options.notifyListener(listeners.onTraceItem, {
|
|
47
|
+
threadId: item.threadId,
|
|
48
|
+
runId: item.runId,
|
|
49
|
+
surfaceItem: item.surfaceItem,
|
|
50
|
+
event: item.event,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
55
|
if (item.type === "result") {
|
|
@@ -21,9 +21,11 @@ export declare function projectRuntimeSurfaceFromSingleUpstreamEvent(input: {
|
|
|
21
21
|
binding?: CompiledAgentBinding;
|
|
22
22
|
currentAgentId: string;
|
|
23
23
|
currentAgentName?: string;
|
|
24
|
+
delegationChain?: string[];
|
|
24
25
|
sourceEventId: string;
|
|
25
26
|
}): {
|
|
26
27
|
currentAgentId: string;
|
|
27
28
|
currentAgentName: string;
|
|
29
|
+
delegationChain: string[];
|
|
28
30
|
items: RuntimeSurfaceItem[];
|
|
29
31
|
};
|
|
@@ -3,37 +3,19 @@ import { createUpstreamTimelineReducer } from "../../../upstream-events.js";
|
|
|
3
3
|
import { formatAgentName } from "../../../utils/agent-display.js";
|
|
4
4
|
import { getBindingMemorySources, getBindingPrimaryModel, getBindingPrimaryTools, getBindingSkills, getBindingSubagents, } from "../../support/compiled-binding.js";
|
|
5
5
|
import { buildRuntimeGovernanceBundles } from "./governance.js";
|
|
6
|
+
import { buildSurfaceId, resolveSurfaceAction, resolveSurfaceDisplayName, } from "./surface-semantics.js";
|
|
6
7
|
function asObject(value) {
|
|
7
8
|
return typeof value === "object" && value !== null ? value : null;
|
|
8
9
|
}
|
|
9
10
|
function readStringArray(value) {
|
|
10
11
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
19
|
-
.replace(/^-+|-+$/g, "")
|
|
20
|
-
.slice(0, 80) || "item";
|
|
21
|
-
}
|
|
22
|
-
function stripStepPrefix(label) {
|
|
23
|
-
return normalizeLabel(label)
|
|
24
|
-
.replace(/^Calling LLM\s+/i, "")
|
|
25
|
-
.replace(/^Completed LLM\s+/i, "")
|
|
26
|
-
.replace(/^Calling tool\s+/i, "")
|
|
27
|
-
.replace(/^Completed tool\s+/i, "")
|
|
28
|
-
.replace(/^Tool\s+/i, "")
|
|
29
|
-
.replace(/\s+failed$/i, "")
|
|
30
|
-
.replace(/^Calling skill\s+/i, "")
|
|
31
|
-
.replace(/^Completed skill\s+/i, "")
|
|
32
|
-
.replace(/^Accessing memory\s+/i, "")
|
|
33
|
-
.replace(/^Completed memory\s+/i, "");
|
|
34
|
-
}
|
|
35
|
-
function buildSurfaceId(kind, value) {
|
|
36
|
-
return `${kind}:${slugify(value)}`;
|
|
13
|
+
function isTaskDelegationCompletionEvent(event) {
|
|
14
|
+
const eventName = typeof event.event === "string" ? event.event : "";
|
|
15
|
+
const name = typeof event.name === "string" ? event.name : "";
|
|
16
|
+
const runType = typeof event.run_type === "string" ? event.run_type : "";
|
|
17
|
+
return ((eventName === "on_tool_end" && name === "task")
|
|
18
|
+
|| (eventName === "on_chain_end" && runType === "tool" && name === "task"));
|
|
37
19
|
}
|
|
38
20
|
function readTracingConfig(binding) {
|
|
39
21
|
const deepAgentTracing = asObject(binding.harnessRuntime?.deepagent?.passthrough)?.tracing;
|
|
@@ -216,16 +198,19 @@ export function projectRuntimeSurfaceFromUpstreamEvents(input) {
|
|
|
216
198
|
const items = [];
|
|
217
199
|
let currentAgentId = input.initialAgentId;
|
|
218
200
|
let currentAgentName = formatAgentName(currentAgentId);
|
|
201
|
+
let delegationChain = [input.initialAgentId];
|
|
219
202
|
for (const [index, rawEvent] of input.upstreamEvents.entries()) {
|
|
220
203
|
const projected = projectRuntimeSurfaceFromSingleUpstreamEvent({
|
|
221
204
|
event: rawEvent,
|
|
222
205
|
binding: input.binding,
|
|
223
206
|
currentAgentId,
|
|
224
207
|
currentAgentName,
|
|
208
|
+
delegationChain,
|
|
225
209
|
sourceEventId: `upstream:${index + 1}`,
|
|
226
210
|
});
|
|
227
211
|
currentAgentId = projected.currentAgentId;
|
|
228
212
|
currentAgentName = projected.currentAgentName;
|
|
213
|
+
delegationChain = projected.delegationChain;
|
|
229
214
|
items.push(...projected.items);
|
|
230
215
|
}
|
|
231
216
|
return items;
|
|
@@ -235,49 +220,93 @@ export function projectRuntimeSurfaceFromSingleUpstreamEvent(input) {
|
|
|
235
220
|
const items = [];
|
|
236
221
|
let currentAgentId = input.currentAgentId;
|
|
237
222
|
let currentAgentName = input.currentAgentName ?? formatAgentName(currentAgentId);
|
|
223
|
+
let delegationChain = input.delegationChain ?? [input.currentAgentId];
|
|
238
224
|
const unwrapped = unwrapUpstreamEvent(input.event);
|
|
239
225
|
if (unwrapped.agentId) {
|
|
240
|
-
|
|
241
|
-
|
|
226
|
+
currentAgentId = unwrapped.agentId;
|
|
227
|
+
currentAgentName = unwrapped.agentName ?? formatAgentName(currentAgentId);
|
|
228
|
+
if (unwrapped.agentId !== input.currentAgentId) {
|
|
242
229
|
items.push({
|
|
243
230
|
kind: "agent",
|
|
244
231
|
id: buildSurfaceId("agent", unwrapped.agentId),
|
|
245
|
-
name:
|
|
246
|
-
|
|
247
|
-
status: "
|
|
248
|
-
|
|
249
|
-
|
|
232
|
+
name: currentAgentName,
|
|
233
|
+
action: "handoff",
|
|
234
|
+
status: "started",
|
|
235
|
+
agentId: unwrapped.agentId,
|
|
236
|
+
agentName: currentAgentName,
|
|
237
|
+
ownerAgentId: input.currentAgentId,
|
|
238
|
+
ownerAgentName: input.currentAgentName ?? formatAgentName(input.currentAgentId),
|
|
250
239
|
sourceEventId: input.sourceEventId,
|
|
240
|
+
detail: {
|
|
241
|
+
fromAgentId: input.currentAgentId,
|
|
242
|
+
fromAgentName: input.currentAgentName ?? formatAgentName(input.currentAgentId),
|
|
243
|
+
toAgentId: unwrapped.agentId,
|
|
244
|
+
toAgentName: currentAgentName,
|
|
245
|
+
},
|
|
251
246
|
});
|
|
252
247
|
}
|
|
253
|
-
currentAgentId = unwrapped.agentId;
|
|
254
|
-
currentAgentName = unwrapped.agentName ?? formatAgentName(currentAgentId);
|
|
255
248
|
}
|
|
256
249
|
else if (unwrapped.agentName) {
|
|
257
250
|
currentAgentName = unwrapped.agentName;
|
|
258
251
|
}
|
|
259
252
|
const typed = asObject(unwrapped.event);
|
|
260
253
|
if (typed && input.binding) {
|
|
254
|
+
const previousAgentId = currentAgentId;
|
|
255
|
+
const previousDelegationChain = delegationChain;
|
|
261
256
|
const next = consumeRunInspectionUpstreamEvent({
|
|
262
257
|
event: typed,
|
|
263
258
|
currentAgentId,
|
|
264
|
-
delegationChain
|
|
259
|
+
delegationChain,
|
|
265
260
|
binding: input.binding,
|
|
266
261
|
});
|
|
267
|
-
if (next.
|
|
268
|
-
|
|
269
|
-
|
|
262
|
+
if (next.delegationChain.length > previousDelegationChain.length) {
|
|
263
|
+
const delegatedAgentName = formatAgentName(next.currentAgentId);
|
|
264
|
+
const ownerAgentId = previousDelegationChain.at(-1) ?? previousAgentId;
|
|
270
265
|
items.push({
|
|
271
266
|
kind: "agent",
|
|
272
|
-
id: buildSurfaceId("agent", currentAgentId),
|
|
273
|
-
name:
|
|
274
|
-
|
|
267
|
+
id: buildSurfaceId("agent", next.currentAgentId),
|
|
268
|
+
name: delegatedAgentName,
|
|
269
|
+
action: "handoff",
|
|
270
|
+
status: "started",
|
|
271
|
+
agentId: next.currentAgentId,
|
|
272
|
+
agentName: delegatedAgentName,
|
|
273
|
+
ownerAgentId,
|
|
274
|
+
ownerAgentName: formatAgentName(ownerAgentId),
|
|
275
|
+
sourceEventId: input.sourceEventId,
|
|
276
|
+
detail: {
|
|
277
|
+
fromAgentId: ownerAgentId,
|
|
278
|
+
fromAgentName: formatAgentName(ownerAgentId),
|
|
279
|
+
toAgentId: next.currentAgentId,
|
|
280
|
+
toAgentName: delegatedAgentName,
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
if (isTaskDelegationCompletionEvent(typed) && previousDelegationChain.length > 1) {
|
|
285
|
+
const delegatedAgentId = previousDelegationChain.at(-1);
|
|
286
|
+
const ownerAgentId = previousDelegationChain.at(-2);
|
|
287
|
+
const delegatedAgentName = formatAgentName(delegatedAgentId);
|
|
288
|
+
items.push({
|
|
289
|
+
kind: "agent",
|
|
290
|
+
id: buildSurfaceId("agent", delegatedAgentId),
|
|
291
|
+
name: delegatedAgentName,
|
|
292
|
+
action: "handoff",
|
|
275
293
|
status: "completed",
|
|
276
|
-
|
|
277
|
-
|
|
294
|
+
agentId: delegatedAgentId,
|
|
295
|
+
agentName: delegatedAgentName,
|
|
296
|
+
...(ownerAgentId ? { ownerAgentId, ownerAgentName: formatAgentName(ownerAgentId) } : {}),
|
|
278
297
|
sourceEventId: input.sourceEventId,
|
|
298
|
+
detail: {
|
|
299
|
+
...(ownerAgentId
|
|
300
|
+
? { fromAgentId: ownerAgentId, fromAgentName: formatAgentName(ownerAgentId) }
|
|
301
|
+
: {}),
|
|
302
|
+
toAgentId: delegatedAgentId,
|
|
303
|
+
toAgentName: delegatedAgentName,
|
|
304
|
+
},
|
|
279
305
|
});
|
|
280
306
|
}
|
|
307
|
+
currentAgentId = next.currentAgentId;
|
|
308
|
+
currentAgentName = formatAgentName(currentAgentId);
|
|
309
|
+
delegationChain = next.delegationChain;
|
|
281
310
|
}
|
|
282
311
|
for (const projection of reducer.consume(unwrapped.event)) {
|
|
283
312
|
if (projection.type !== "step") {
|
|
@@ -287,20 +316,36 @@ export function projectRuntimeSurfaceFromSingleUpstreamEvent(input) {
|
|
|
287
316
|
if (!kind) {
|
|
288
317
|
continue;
|
|
289
318
|
}
|
|
319
|
+
const displayName = resolveSurfaceDisplayName({
|
|
320
|
+
kind,
|
|
321
|
+
step: projection.step,
|
|
322
|
+
binding: input.binding,
|
|
323
|
+
});
|
|
290
324
|
items.push({
|
|
291
325
|
kind,
|
|
292
|
-
id: buildSurfaceId(kind,
|
|
293
|
-
name:
|
|
294
|
-
|
|
326
|
+
id: buildSurfaceId(kind, displayName || projection.step),
|
|
327
|
+
name: displayName,
|
|
328
|
+
action: resolveSurfaceAction({
|
|
329
|
+
kind,
|
|
330
|
+
step: projection.step,
|
|
331
|
+
event: unwrapped.event,
|
|
332
|
+
}),
|
|
295
333
|
status: projection.status,
|
|
334
|
+
agentId: currentAgentId,
|
|
335
|
+
agentName: currentAgentName,
|
|
296
336
|
ownerAgentId: currentAgentId,
|
|
297
337
|
ownerAgentName: currentAgentName,
|
|
298
338
|
sourceEventId: input.sourceEventId,
|
|
339
|
+
detail: {
|
|
340
|
+
step: projection.step,
|
|
341
|
+
category: projection.category,
|
|
342
|
+
},
|
|
299
343
|
});
|
|
300
344
|
}
|
|
301
345
|
return {
|
|
302
346
|
currentAgentId,
|
|
303
347
|
currentAgentName,
|
|
348
|
+
delegationChain,
|
|
304
349
|
items,
|
|
305
350
|
};
|
|
306
351
|
}
|
|
@@ -10,6 +10,7 @@ type RuntimeStreamChunk = string | {
|
|
|
10
10
|
};
|
|
11
11
|
type StreamRunOptions = {
|
|
12
12
|
binding: CompiledAgentBinding;
|
|
13
|
+
getBinding: (agentId: string) => CompiledAgentBinding | undefined;
|
|
13
14
|
input: MessageContent;
|
|
14
15
|
invocation: {
|
|
15
16
|
context?: Record<string, unknown>;
|
|
@@ -53,9 +54,8 @@ type StreamRunOptions = {
|
|
|
53
54
|
currentAgentId?: string | null;
|
|
54
55
|
delegationChain?: string[];
|
|
55
56
|
runtimeSnapshot?: RuntimeSnapshot | null;
|
|
56
|
-
upstreamEvents?: unknown[];
|
|
57
|
-
appendUpstreamEvent?: unknown;
|
|
58
57
|
}) => Promise<void>;
|
|
58
|
+
appendRunTraceItem: (threadId: string, runId: string, item: unknown) => Promise<void>;
|
|
59
59
|
emitSyntheticFallback: (threadId: string, runId: string, selectedAgentId: string, error: unknown) => Promise<void>;
|
|
60
60
|
};
|
|
61
61
|
export declare function streamHarnessRun(options: StreamRunOptions): AsyncGenerator<InternalHarnessStreamItem>;
|