@botbotgo/agent-harness 0.0.268 → 0.0.269
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/dist/acp.js +2 -2
- package/dist/api.d.ts +6 -11
- package/dist/api.js +20 -23
- package/dist/contracts/runtime.d.ts +38 -70
- package/dist/flow/build-flow-graph.js +29 -45
- package/dist/flow/types.d.ts +0 -6
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.js +24 -17
- package/dist/persistence/sqlite-run-context-store.js +2 -2
- package/dist/persistence/sqlite-store.js +18 -16
- package/dist/protocol/a2a/http.js +48 -46
- package/dist/protocol/ag-ui/http.js +9 -9
- package/dist/runtime/adapter/invocation-result.js +2 -2
- package/dist/runtime/harness/events/listener-runtime.d.ts +2 -2
- package/dist/runtime/harness/events/streaming.d.ts +8 -8
- package/dist/runtime/harness/events/streaming.js +10 -10
- package/dist/runtime/harness/events/timeline.js +4 -4
- package/dist/runtime/harness/run/helpers.js +2 -2
- package/dist/runtime/harness/run/recovery.js +20 -20
- package/dist/runtime/harness/run/resume.js +3 -3
- package/dist/runtime/harness/run/run-lifecycle.js +5 -5
- package/dist/runtime/harness/run/run-operations.d.ts +2 -2
- package/dist/runtime/harness/run/run-operations.js +21 -21
- package/dist/runtime/harness/run/start-run.d.ts +3 -3
- package/dist/runtime/harness/run/start-run.js +3 -3
- package/dist/runtime/harness/run/startup-runtime.js +1 -1
- package/dist/runtime/harness/run/stream-run.js +37 -27
- package/dist/runtime/harness/run/thread-records.js +12 -33
- package/dist/runtime/harness/system/mem0-ingestion-sync.js +2 -2
- package/dist/runtime/harness/system/runtime-memory-manager.js +4 -4
- package/dist/runtime/harness/system/runtime-memory-records.js +6 -6
- package/dist/runtime/harness/system/runtime-memory-sync.js +6 -4
- package/dist/runtime/harness/system/thread-memory-sync.js +7 -5
- package/dist/runtime/harness.d.ts +2 -2
- package/dist/runtime/harness.js +161 -156
- package/dist/runtime/support/harness-support.js +4 -4
- package/package.json +1 -1
|
@@ -197,10 +197,10 @@ export class FilePersistence {
|
|
|
197
197
|
}
|
|
198
198
|
async appendEvent(event) {
|
|
199
199
|
const sequenceId = String(event.sequence).padStart(6, "0");
|
|
200
|
-
const inspectionPath = path.join(this.runDir(event.
|
|
200
|
+
const inspectionPath = path.join(this.runDir(event.sessionId, event.requestId), "inspection.json");
|
|
201
201
|
const inspection = await readJson(inspectionPath);
|
|
202
202
|
await Promise.all([
|
|
203
|
-
writeJson(path.join(this.runDir(event.
|
|
203
|
+
writeJson(path.join(this.runDir(event.sessionId, event.requestId), "events", `${sequenceId}.json`), event),
|
|
204
204
|
writeJson(inspectionPath, {
|
|
205
205
|
...inspection,
|
|
206
206
|
lastActivityAt: event.timestamp,
|
|
@@ -221,8 +221,8 @@ export class FilePersistence {
|
|
|
221
221
|
]);
|
|
222
222
|
return {
|
|
223
223
|
agentId: meta.entryAgentId,
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
sessionId: index.threadId,
|
|
225
|
+
latestRequestId: index.latestRunId,
|
|
226
226
|
createdAt: meta.createdAt,
|
|
227
227
|
updatedAt: index.updatedAt,
|
|
228
228
|
status: index.status,
|
|
@@ -237,9 +237,9 @@ export class FilePersistence {
|
|
|
237
237
|
const sessions = await this.listSessions(filter);
|
|
238
238
|
const summaries = await Promise.all(sessions.map(async (session) => {
|
|
239
239
|
const [meta, messageBundle] = await Promise.all([
|
|
240
|
-
readJson(path.join(this.threadDir(session.
|
|
241
|
-
readJson(path.join(this.threadDir(session.
|
|
242
|
-
.catch(() => ({ threadId: session.
|
|
240
|
+
readJson(path.join(this.threadDir(session.sessionId), "meta.json")),
|
|
241
|
+
readJson(path.join(this.threadDir(session.sessionId), "messages.json"))
|
|
242
|
+
.catch(() => ({ threadId: session.sessionId, items: [] })),
|
|
243
243
|
]);
|
|
244
244
|
const items = messageBundle.items;
|
|
245
245
|
return {
|
|
@@ -268,8 +268,8 @@ export class FilePersistence {
|
|
|
268
268
|
readJson(path.join(runDir, "inspection.json")),
|
|
269
269
|
]);
|
|
270
270
|
return {
|
|
271
|
-
|
|
272
|
-
|
|
271
|
+
requestId: meta.runId,
|
|
272
|
+
sessionId: meta.threadId,
|
|
273
273
|
agentId: meta.agentId,
|
|
274
274
|
...(meta.parentRunId ? { parentRunId: meta.parentRunId } : {}),
|
|
275
275
|
executionMode: meta.executionMode,
|
|
@@ -295,7 +295,7 @@ export class FilePersistence {
|
|
|
295
295
|
if (filter.agentId && run.agentId !== filter.agentId) {
|
|
296
296
|
return false;
|
|
297
297
|
}
|
|
298
|
-
if (filter.threadId && run.
|
|
298
|
+
if (filter.threadId && run.sessionId !== filter.threadId) {
|
|
299
299
|
return false;
|
|
300
300
|
}
|
|
301
301
|
if (filter.state && run.state !== filter.state) {
|
|
@@ -325,8 +325,8 @@ export class FilePersistence {
|
|
|
325
325
|
const runInspection = await readJson(path.join(this.runDir(threadId, index.latestRunId), "inspection.json")).catch(() => null);
|
|
326
326
|
return {
|
|
327
327
|
agentId: meta.entryAgentId,
|
|
328
|
-
threadId,
|
|
329
|
-
|
|
328
|
+
sessionId: threadId,
|
|
329
|
+
latestRequestId: index.latestRunId,
|
|
330
330
|
createdAt: meta.createdAt,
|
|
331
331
|
updatedAt: index.updatedAt,
|
|
332
332
|
status: index.status,
|
|
@@ -370,10 +370,10 @@ export class FilePersistence {
|
|
|
370
370
|
if (filter.status && approval.status !== filter.status) {
|
|
371
371
|
return false;
|
|
372
372
|
}
|
|
373
|
-
if (filter.threadId && approval.
|
|
373
|
+
if (filter.threadId && approval.sessionId !== filter.threadId) {
|
|
374
374
|
return false;
|
|
375
375
|
}
|
|
376
|
-
if (filter.runId && approval.
|
|
376
|
+
if (filter.runId && approval.requestId !== filter.runId) {
|
|
377
377
|
return false;
|
|
378
378
|
}
|
|
379
379
|
return true;
|
|
@@ -460,7 +460,7 @@ export class FilePersistence {
|
|
|
460
460
|
.filter((record) => record.threadId === threadId)
|
|
461
461
|
.map((record) => rm(this.runIndexPath(record.runId), { force: true })),
|
|
462
462
|
...approvals
|
|
463
|
-
.filter((record) => record.
|
|
463
|
+
.filter((record) => record.sessionId === threadId)
|
|
464
464
|
.map((record) => rm(this.approvalIndexPath(record.approvalId), { force: true })),
|
|
465
465
|
...runIndexes
|
|
466
466
|
.filter((record) => record.threadId === threadId)
|
|
@@ -487,9 +487,16 @@ export class FilePersistence {
|
|
|
487
487
|
}
|
|
488
488
|
}
|
|
489
489
|
async createApproval(record) {
|
|
490
|
+
const sessionId = record.sessionId ?? record.threadId ?? "";
|
|
491
|
+
const requestId = record.requestId ?? record.runId ?? "";
|
|
492
|
+
const normalized = {
|
|
493
|
+
...record,
|
|
494
|
+
sessionId,
|
|
495
|
+
requestId,
|
|
496
|
+
};
|
|
490
497
|
await Promise.all([
|
|
491
|
-
writeJson(path.join(this.runDir(
|
|
492
|
-
writeJson(path.join(this.runRoot, "indexes", "approvals", `${record.approvalId}.json`),
|
|
498
|
+
writeJson(path.join(this.runDir(sessionId, requestId), "approvals", `${record.approvalId}.json`), normalized),
|
|
499
|
+
writeJson(path.join(this.runRoot, "indexes", "approvals", `${record.approvalId}.json`), normalized),
|
|
493
500
|
]);
|
|
494
501
|
}
|
|
495
502
|
async resolveApproval(threadId, runId, approvalId, status) {
|
|
@@ -27,7 +27,7 @@ export class SqliteRunContextStore {
|
|
|
27
27
|
async appendThreadMessage(threadId, message) {
|
|
28
28
|
await this.db.execute(`INSERT INTO thread_messages
|
|
29
29
|
(thread_id, role, content_json, run_id, created_at)
|
|
30
|
-
VALUES (?, ?, ?, ?, ?)`, [threadId, message.role, JSON.stringify(message.content), message.runId, message.createdAt]);
|
|
30
|
+
VALUES (?, ?, ?, ?, ?)`, [threadId, message.role, JSON.stringify(message.content), message.requestId ?? message.runId, message.createdAt]);
|
|
31
31
|
}
|
|
32
32
|
async listThreadMessages(threadId, limit = 12) {
|
|
33
33
|
const rows = await this.db.selectAll(`SELECT role, content_json, run_id, created_at
|
|
@@ -42,7 +42,7 @@ export class SqliteRunContextStore {
|
|
|
42
42
|
return rows.map((row) => ({
|
|
43
43
|
role: asString(row.role),
|
|
44
44
|
content: parseJson(row.content_json),
|
|
45
|
-
|
|
45
|
+
requestId: asString(row.run_id),
|
|
46
46
|
createdAt: asString(row.created_at),
|
|
47
47
|
}));
|
|
48
48
|
}
|
|
@@ -413,8 +413,8 @@ export class SqlitePersistence {
|
|
|
413
413
|
mapThreadSummary(row) {
|
|
414
414
|
return {
|
|
415
415
|
agentId: asString(row.entry_agent_id),
|
|
416
|
-
|
|
417
|
-
|
|
416
|
+
sessionId: asString(row.thread_id),
|
|
417
|
+
latestRequestId: asString(row.latest_run_id),
|
|
418
418
|
createdAt: asString(row.created_at),
|
|
419
419
|
updatedAt: asString(row.updated_at),
|
|
420
420
|
status: asString(row.status),
|
|
@@ -424,8 +424,8 @@ export class SqlitePersistence {
|
|
|
424
424
|
mapRunSummary(row) {
|
|
425
425
|
const runtimeSnapshot = row.runtime_snapshot_json ? parseJson(row.runtime_snapshot_json) : null;
|
|
426
426
|
return {
|
|
427
|
-
|
|
428
|
-
|
|
427
|
+
requestId: asString(row.run_id),
|
|
428
|
+
sessionId: asString(row.thread_id),
|
|
429
429
|
agentId: asString(row.agent_id),
|
|
430
430
|
...(asNullableString(row.parent_run_id) ? { parentRunId: asNullableString(row.parent_run_id) } : {}),
|
|
431
431
|
executionMode: asString(row.execution_mode),
|
|
@@ -458,8 +458,8 @@ export class SqlitePersistence {
|
|
|
458
458
|
return {
|
|
459
459
|
approvalId: asString(row.approval_id),
|
|
460
460
|
pendingActionId: asString(row.pending_action_id),
|
|
461
|
-
|
|
462
|
-
|
|
461
|
+
sessionId: asString(row.thread_id),
|
|
462
|
+
requestId: asString(row.run_id),
|
|
463
463
|
toolCallId: asString(row.tool_call_id),
|
|
464
464
|
toolName: asString(row.tool_name),
|
|
465
465
|
status: asString(row.status),
|
|
@@ -612,7 +612,7 @@ export class SqlitePersistence {
|
|
|
612
612
|
input.threadId,
|
|
613
613
|
input.userMessage.role,
|
|
614
614
|
JSON.stringify(input.userMessage.content),
|
|
615
|
-
input.userMessage.runId,
|
|
615
|
+
input.userMessage.requestId ?? input.userMessage.runId,
|
|
616
616
|
input.userMessage.createdAt,
|
|
617
617
|
],
|
|
618
618
|
}, {
|
|
@@ -681,10 +681,10 @@ export class SqlitePersistence {
|
|
|
681
681
|
async appendEvent(event) {
|
|
682
682
|
await this.execute(`INSERT OR REPLACE INTO events
|
|
683
683
|
(thread_id, run_id, sequence, event_json, created_at)
|
|
684
|
-
VALUES (?, ?, ?, ?, ?)`, [event.
|
|
684
|
+
VALUES (?, ?, ?, ?, ?)`, [event.sessionId, event.requestId, event.sequence, JSON.stringify(event), event.timestamp]);
|
|
685
685
|
await this.execute(`UPDATE run_inspection
|
|
686
686
|
SET last_activity_at = ?
|
|
687
|
-
WHERE run_id = ? AND thread_id = ?`, [event.timestamp, event.
|
|
687
|
+
WHERE run_id = ? AND thread_id = ?`, [event.timestamp, event.requestId, event.sessionId]);
|
|
688
688
|
}
|
|
689
689
|
async listSessions(filter = {}) {
|
|
690
690
|
const { clause, args } = buildWhereClause([
|
|
@@ -750,7 +750,7 @@ export class SqlitePersistence {
|
|
|
750
750
|
? {
|
|
751
751
|
role: asString(row.first_message_role),
|
|
752
752
|
content: parseJson(row.first_message_content_json),
|
|
753
|
-
|
|
753
|
+
requestId: asString(row.first_message_run_id),
|
|
754
754
|
createdAt: asString(row.first_message_created_at),
|
|
755
755
|
}
|
|
756
756
|
: undefined,
|
|
@@ -758,7 +758,7 @@ export class SqlitePersistence {
|
|
|
758
758
|
? {
|
|
759
759
|
role: asString(row.last_message_role),
|
|
760
760
|
content: parseJson(row.last_message_content_json),
|
|
761
|
-
|
|
761
|
+
requestId: asString(row.last_message_run_id),
|
|
762
762
|
createdAt: asString(row.last_message_created_at),
|
|
763
763
|
}
|
|
764
764
|
: undefined,
|
|
@@ -972,13 +972,15 @@ export class SqlitePersistence {
|
|
|
972
972
|
await this.runContextStore.clearRunRequest(threadId, runId);
|
|
973
973
|
}
|
|
974
974
|
async createApproval(record) {
|
|
975
|
+
const sessionId = record.sessionId ?? record.threadId ?? "";
|
|
976
|
+
const requestId = record.requestId ?? record.runId ?? "";
|
|
975
977
|
await this.execute(`INSERT OR REPLACE INTO approvals
|
|
976
978
|
(approval_id, pending_action_id, thread_id, run_id, tool_call_id, tool_name, status, requested_at, resolved_at, allowed_decisions_json, input_preview_json, checkpoint_ref, event_refs_json)
|
|
977
979
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
978
980
|
record.approvalId,
|
|
979
981
|
record.pendingActionId,
|
|
980
|
-
|
|
981
|
-
|
|
982
|
+
sessionId,
|
|
983
|
+
requestId,
|
|
982
984
|
record.toolCallId,
|
|
983
985
|
record.toolName,
|
|
984
986
|
record.status,
|
|
@@ -992,7 +994,7 @@ export class SqlitePersistence {
|
|
|
992
994
|
}
|
|
993
995
|
async resolveApproval(threadId, runId, approvalId, status) {
|
|
994
996
|
const current = await this.getApproval(approvalId);
|
|
995
|
-
if (!current || current.
|
|
997
|
+
if (!current || current.sessionId !== threadId || current.requestId !== runId) {
|
|
996
998
|
throw new Error(`Missing approval ${approvalId} for run ${runId}`);
|
|
997
999
|
}
|
|
998
1000
|
const updated = {
|
|
@@ -1018,8 +1020,8 @@ export class SqlitePersistence {
|
|
|
1018
1020
|
WHERE thread_id = ? AND run_id = ?
|
|
1019
1021
|
ORDER BY created_at ASC, artifact_id ASC`, [threadId, runId]);
|
|
1020
1022
|
return {
|
|
1021
|
-
threadId,
|
|
1022
|
-
runId,
|
|
1023
|
+
sessionId: threadId,
|
|
1024
|
+
requestId: runId,
|
|
1023
1025
|
items: rows.map((row) => ({
|
|
1024
1026
|
artifactId: asString(row.artifact_id),
|
|
1025
1027
|
kind: asString(row.kind),
|
|
@@ -356,18 +356,19 @@ function toSessionRecord(session) {
|
|
|
356
356
|
if (!session) {
|
|
357
357
|
return null;
|
|
358
358
|
}
|
|
359
|
+
const typed = session;
|
|
359
360
|
return {
|
|
360
|
-
sessionId:
|
|
361
|
-
entryAgentId:
|
|
362
|
-
currentAgentId:
|
|
363
|
-
currentState:
|
|
364
|
-
latestRequestId:
|
|
365
|
-
createdAt:
|
|
366
|
-
updatedAt:
|
|
367
|
-
messages:
|
|
368
|
-
requests:
|
|
369
|
-
requestId: run.
|
|
370
|
-
sessionId: run.
|
|
361
|
+
sessionId: typed.sessionId ?? typed.threadId ?? "",
|
|
362
|
+
entryAgentId: typed.entryAgentId,
|
|
363
|
+
currentAgentId: typed.currentAgentId,
|
|
364
|
+
currentState: typed.currentState,
|
|
365
|
+
latestRequestId: typed.latestRequestId ?? typed.latestRunId ?? "",
|
|
366
|
+
createdAt: typed.createdAt,
|
|
367
|
+
updatedAt: typed.updatedAt,
|
|
368
|
+
messages: typed.messages,
|
|
369
|
+
requests: (typed.requests ?? typed.runs ?? []).map((run) => ({
|
|
370
|
+
requestId: run.requestId,
|
|
371
|
+
sessionId: run.sessionId,
|
|
371
372
|
agentId: run.agentId,
|
|
372
373
|
executionMode: run.executionMode,
|
|
373
374
|
adapterKind: run.adapterKind,
|
|
@@ -392,25 +393,26 @@ function toRequestRecord(request) {
|
|
|
392
393
|
if (!request) {
|
|
393
394
|
return null;
|
|
394
395
|
}
|
|
396
|
+
const typed = request;
|
|
395
397
|
return {
|
|
396
|
-
requestId:
|
|
397
|
-
sessionId:
|
|
398
|
-
agentId:
|
|
399
|
-
executionMode:
|
|
400
|
-
adapterKind:
|
|
401
|
-
createdAt:
|
|
402
|
-
updatedAt:
|
|
403
|
-
state:
|
|
404
|
-
checkpointRef:
|
|
405
|
-
resumable:
|
|
406
|
-
startedAt:
|
|
407
|
-
endedAt:
|
|
408
|
-
lastActivityAt:
|
|
409
|
-
currentAgentId:
|
|
410
|
-
delegationChain:
|
|
411
|
-
runtimeSnapshot:
|
|
412
|
-
traceItems:
|
|
413
|
-
runtimeTimeline:
|
|
398
|
+
requestId: typed.requestId ?? typed.runId ?? "",
|
|
399
|
+
sessionId: typed.sessionId ?? typed.threadId ?? "",
|
|
400
|
+
agentId: typed.agentId,
|
|
401
|
+
executionMode: typed.executionMode,
|
|
402
|
+
adapterKind: typed.adapterKind,
|
|
403
|
+
createdAt: typed.createdAt,
|
|
404
|
+
updatedAt: typed.updatedAt,
|
|
405
|
+
state: typed.state,
|
|
406
|
+
checkpointRef: typed.checkpointRef,
|
|
407
|
+
resumable: typed.resumable,
|
|
408
|
+
startedAt: typed.startedAt,
|
|
409
|
+
endedAt: typed.endedAt,
|
|
410
|
+
lastActivityAt: typed.lastActivityAt,
|
|
411
|
+
currentAgentId: typed.currentAgentId,
|
|
412
|
+
delegationChain: typed.delegationChain,
|
|
413
|
+
runtimeSnapshot: typed.runtimeSnapshot,
|
|
414
|
+
traceItems: typed.traceItems,
|
|
415
|
+
runtimeTimeline: typed.runtimeTimeline,
|
|
414
416
|
};
|
|
415
417
|
}
|
|
416
418
|
function buildTaskFromSessionAndRequest(session, request, approvals, output, failureMessage) {
|
|
@@ -473,8 +475,8 @@ async function buildTaskFromRuntime(runtime, requestId) {
|
|
|
473
475
|
if (!request) {
|
|
474
476
|
return null;
|
|
475
477
|
}
|
|
476
|
-
const session = await runtime.getThread(request.
|
|
477
|
-
const approvals = await runtime.listApprovals({
|
|
478
|
+
const session = await runtime.getThread(request.sessionId);
|
|
479
|
+
const approvals = await runtime.listApprovals({ sessionId: request.sessionId, requestId: request.requestId });
|
|
478
480
|
return buildTaskFromSessionAndRequest(toSessionRecord(session), toRequestRecord(request), approvals);
|
|
479
481
|
}
|
|
480
482
|
async function hydrateTaskStateFromEvents(runtime, task) {
|
|
@@ -508,7 +510,7 @@ async function listTasksFromRuntime(runtime, params) {
|
|
|
508
510
|
});
|
|
509
511
|
const startIndex = params.cursor ? Number.parseInt(Buffer.from(params.cursor, "base64url").toString("utf8"), 10) || 0 : 0;
|
|
510
512
|
const page = runs.slice(startIndex, startIndex + params.limit);
|
|
511
|
-
const tasks = (await Promise.all(page.map((run) => buildTaskFromRuntime(runtime, run.
|
|
513
|
+
const tasks = (await Promise.all(page.map((run) => buildTaskFromRuntime(runtime, run.requestId)))).filter((task) => Boolean(task));
|
|
512
514
|
const nextIndex = startIndex + page.length;
|
|
513
515
|
const nextPageToken = nextIndex < runs.length ? Buffer.from(String(nextIndex), "utf8").toString("base64url") : "";
|
|
514
516
|
return {
|
|
@@ -718,12 +720,12 @@ async function* streamSendMessageTaskUpdates(runtime, options, method) {
|
|
|
718
720
|
let emittedInitialTask = false;
|
|
719
721
|
for await (const item of runtime.streamEvents(options)) {
|
|
720
722
|
if (item.type === "event") {
|
|
721
|
-
runId = runId ?? item.event.
|
|
723
|
+
runId = runId ?? item.event.requestId;
|
|
722
724
|
if (item.event.eventType === "output.delta" && typeof item.event.payload.content === "string") {
|
|
723
725
|
streamedText += item.event.payload.content;
|
|
724
726
|
}
|
|
725
727
|
if (item.event.eventType === "run.created" || item.event.eventType === "run.state.changed" || item.event.eventType === "output.delta" || item.event.eventType === "approval.requested") {
|
|
726
|
-
const task = withStreamingStatusText(await buildTaskFromRuntime(runtime, item.event.
|
|
728
|
+
const task = withStreamingStatusText(await buildTaskFromRuntime(runtime, item.event.requestId), streamedText || undefined);
|
|
727
729
|
if (task) {
|
|
728
730
|
yield { task, mode: emittedInitialTask ? "status-update" : "task" };
|
|
729
731
|
emittedInitialTask = true;
|
|
@@ -732,8 +734,8 @@ async function* streamSendMessageTaskUpdates(runtime, options, method) {
|
|
|
732
734
|
continue;
|
|
733
735
|
}
|
|
734
736
|
if (item.type === "result") {
|
|
735
|
-
runId = item.result.
|
|
736
|
-
const task = withRunResult(await buildTaskFromRuntime(runtime, item.result.
|
|
737
|
+
runId = item.result.requestId;
|
|
738
|
+
const task = withRunResult(await buildTaskFromRuntime(runtime, item.result.requestId), item.result, streamedText || item.result.output);
|
|
737
739
|
yield { task, mode: emittedInitialTask ? "status-update" : "task" };
|
|
738
740
|
return;
|
|
739
741
|
}
|
|
@@ -810,7 +812,7 @@ async function streamExistingTaskUpdates(runtime, response, id, method, taskId)
|
|
|
810
812
|
}
|
|
811
813
|
};
|
|
812
814
|
const unsubscribe = runtime.subscribe((event) => {
|
|
813
|
-
if (event.
|
|
815
|
+
if (event.requestId !== taskId) {
|
|
814
816
|
return;
|
|
815
817
|
}
|
|
816
818
|
if (event.eventType !== "run.state.changed"
|
|
@@ -893,10 +895,10 @@ export async function serveA2aOverHttp(runtime, options = {}) {
|
|
|
893
895
|
};
|
|
894
896
|
const pushRelevantEventTypes = new Set(["run.state.changed", "approval.requested", "approval.resolved"]);
|
|
895
897
|
const unsubscribePushNotifications = runtime.subscribe((event) => {
|
|
896
|
-
if (!pushRelevantEventTypes.has(event.eventType) || !pushConfigsByTask.has(event.
|
|
898
|
+
if (!pushRelevantEventTypes.has(event.eventType) || !pushConfigsByTask.has(event.requestId)) {
|
|
897
899
|
return;
|
|
898
900
|
}
|
|
899
|
-
void dispatchPushNotificationsForTask(event.
|
|
901
|
+
void dispatchPushNotificationsForTask(event.requestId);
|
|
900
902
|
});
|
|
901
903
|
const httpServer = createServer(async (request, response) => {
|
|
902
904
|
try {
|
|
@@ -934,12 +936,12 @@ export async function serveA2aOverHttp(runtime, options = {}) {
|
|
|
934
936
|
const result = await runtime.run({
|
|
935
937
|
agentId: parsed.agentId ?? options.defaultAgentId,
|
|
936
938
|
input: parsed.input,
|
|
937
|
-
...(parsed.sessionId ? {
|
|
939
|
+
...(parsed.sessionId ? { sessionId: parsed.sessionId } : {}),
|
|
938
940
|
invocation: attachServiceParameters(parsed.invocation, serviceParameters),
|
|
939
941
|
});
|
|
940
|
-
const session = await runtime.getThread(result.
|
|
941
|
-
const requestRecord = await runtime.getRun(result.
|
|
942
|
-
const approvals = await runtime.listApprovals({
|
|
942
|
+
const session = await runtime.getThread(result.sessionId);
|
|
943
|
+
const requestRecord = await runtime.getRun(result.requestId);
|
|
944
|
+
const approvals = await runtime.listApprovals({ sessionId: result.sessionId, requestId: result.requestId });
|
|
943
945
|
const task = buildTaskFromSessionAndRequest(toSessionRecord(session), toRequestRecord(requestRecord), approvals, result.output);
|
|
944
946
|
if (task && parsed.pushNotificationConfig) {
|
|
945
947
|
registerPushNotificationConfig(task.id, parsed.pushNotificationConfig);
|
|
@@ -958,7 +960,7 @@ export async function serveA2aOverHttp(runtime, options = {}) {
|
|
|
958
960
|
const sourceIterator = streamSendMessageTaskUpdates(runtime, {
|
|
959
961
|
agentId: parsed.agentId ?? options.defaultAgentId,
|
|
960
962
|
input: parsed.input,
|
|
961
|
-
...(parsed.sessionId ? {
|
|
963
|
+
...(parsed.sessionId ? { sessionId: parsed.sessionId } : {}),
|
|
962
964
|
invocation: attachServiceParameters(parsed.invocation, serviceParameters),
|
|
963
965
|
}, payload.method);
|
|
964
966
|
const iterator = (async function* () {
|
|
@@ -991,8 +993,8 @@ export async function serveA2aOverHttp(runtime, options = {}) {
|
|
|
991
993
|
}
|
|
992
994
|
if (payload.method === "tasks/cancel" || payload.method === "CancelTask") {
|
|
993
995
|
const { taskId } = parseTaskLocatorParams(payload.params);
|
|
994
|
-
const result = await runtime.cancelRun({
|
|
995
|
-
const task = await buildTaskFromRuntime(runtime, result.
|
|
996
|
+
const result = await runtime.cancelRun({ requestId: taskId, reason: "Cancelled via A2A bridge." });
|
|
997
|
+
const task = await buildTaskFromRuntime(runtime, result.requestId);
|
|
996
998
|
writeJson(response, 200, toSuccess(payload.id ?? null, task));
|
|
997
999
|
return;
|
|
998
1000
|
}
|
|
@@ -51,8 +51,8 @@ function toRunStarted(event, input) {
|
|
|
51
51
|
return {
|
|
52
52
|
type: "RUN_STARTED",
|
|
53
53
|
timestamp: createTimestamp(),
|
|
54
|
-
threadId: event.
|
|
55
|
-
runId: event.
|
|
54
|
+
threadId: event.sessionId,
|
|
55
|
+
runId: event.requestId,
|
|
56
56
|
input,
|
|
57
57
|
};
|
|
58
58
|
}
|
|
@@ -187,19 +187,19 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
187
187
|
const result = await runtime.run({
|
|
188
188
|
agentId: input.agentId,
|
|
189
189
|
input: input.input,
|
|
190
|
-
...(input.sessionId ? {
|
|
190
|
+
...(input.sessionId ? { sessionId: input.sessionId } : {}),
|
|
191
191
|
...(input.invocation ? { invocation: input.invocation } : {}),
|
|
192
192
|
listeners: {
|
|
193
193
|
onEvent: async (event) => {
|
|
194
194
|
if (event.eventType === "run.created") {
|
|
195
|
-
runId = event.
|
|
196
|
-
threadId = event.
|
|
195
|
+
runId = event.requestId;
|
|
196
|
+
threadId = event.sessionId;
|
|
197
197
|
await writeSseEvent(response, toRunStarted(event, input.input));
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
200
|
if (event.eventType === "output.delta") {
|
|
201
|
-
runId = runId ?? event.
|
|
202
|
-
threadId = threadId ?? event.
|
|
201
|
+
runId = runId ?? event.requestId;
|
|
202
|
+
threadId = threadId ?? event.sessionId;
|
|
203
203
|
const delta = typeof event.payload.content === "string" ? event.payload.content : "";
|
|
204
204
|
if (!delta) {
|
|
205
205
|
return;
|
|
@@ -301,8 +301,8 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
301
301
|
},
|
|
302
302
|
},
|
|
303
303
|
});
|
|
304
|
-
runId = runId ?? result.
|
|
305
|
-
threadId = threadId ?? result.
|
|
304
|
+
runId = runId ?? result.requestId;
|
|
305
|
+
threadId = threadId ?? result.sessionId;
|
|
306
306
|
if (!textMessageStarted && result.output) {
|
|
307
307
|
await ensureTextStart();
|
|
308
308
|
await writeSseEvent(response, {
|
|
@@ -20,8 +20,8 @@ export function finalizeInvocationResult(params) {
|
|
|
20
20
|
const stateSnapshot = buildStateSnapshot(result);
|
|
21
21
|
const memoryCandidates = executedToolResults.flatMap((toolResult) => toolResult.memoryCandidates ?? []);
|
|
22
22
|
return {
|
|
23
|
-
threadId,
|
|
24
|
-
runId,
|
|
23
|
+
sessionId: threadId,
|
|
24
|
+
requestId: runId,
|
|
25
25
|
agentId: bindingAgentId,
|
|
26
26
|
state: Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? "waiting_for_approval" : "completed",
|
|
27
27
|
interruptContent,
|
|
@@ -4,10 +4,10 @@ export declare function createListenerDispatchRuntime(input: {
|
|
|
4
4
|
notifyListener: <T>(listener: ((value: T) => void | Promise<void>) | undefined, value: T) => Promise<void>;
|
|
5
5
|
getThread: (threadId: string) => Promise<{
|
|
6
6
|
currentState: RunResult["state"];
|
|
7
|
-
|
|
7
|
+
latestRequestId: string;
|
|
8
8
|
entryAgentId: string;
|
|
9
9
|
currentAgentId?: string;
|
|
10
|
-
|
|
10
|
+
requests: Array<{
|
|
11
11
|
agentId: string;
|
|
12
12
|
}>;
|
|
13
13
|
pendingDecision?: {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { HarnessEvent, HarnessStreamItem, RunListeners, RunResult } from "../../../contracts/types.js";
|
|
2
2
|
export type InternalHarnessStreamItem = HarnessStreamItem | {
|
|
3
3
|
type: "content";
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
sessionId: string;
|
|
5
|
+
requestId: string;
|
|
6
6
|
agentId: string;
|
|
7
7
|
content: string;
|
|
8
8
|
} | {
|
|
9
9
|
type: "content-blocks";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
sessionId: string;
|
|
11
|
+
requestId: string;
|
|
12
12
|
agentId: string;
|
|
13
13
|
contentBlocks: unknown[];
|
|
14
14
|
} | {
|
|
15
15
|
type: "tool-result";
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
sessionId: string;
|
|
17
|
+
requestId: string;
|
|
18
18
|
agentId: string;
|
|
19
19
|
toolName: string;
|
|
20
20
|
output: unknown;
|
|
@@ -27,10 +27,10 @@ export declare function dispatchRunListeners(stream: AsyncGenerator<InternalHarn
|
|
|
27
27
|
notifyListener: <T>(listener: ((value: T) => void | Promise<void>) | undefined, value: T) => Promise<void>;
|
|
28
28
|
getThread: (threadId: string) => Promise<{
|
|
29
29
|
currentState: RunResult["state"];
|
|
30
|
-
|
|
30
|
+
latestRequestId: string;
|
|
31
31
|
entryAgentId: string;
|
|
32
32
|
currentAgentId?: string;
|
|
33
|
-
|
|
33
|
+
requests: Array<{
|
|
34
34
|
agentId: string;
|
|
35
35
|
}>;
|
|
36
36
|
pendingDecision?: {
|
|
@@ -5,8 +5,8 @@ export async function emitOutputDeltaAndCreateItem(emit, threadId, runId, agentI
|
|
|
5
5
|
});
|
|
6
6
|
return {
|
|
7
7
|
type: "content",
|
|
8
|
-
threadId,
|
|
9
|
-
runId,
|
|
8
|
+
sessionId: threadId,
|
|
9
|
+
requestId: runId,
|
|
10
10
|
agentId,
|
|
11
11
|
content,
|
|
12
12
|
};
|
|
@@ -14,8 +14,8 @@ export async function emitOutputDeltaAndCreateItem(emit, threadId, runId, agentI
|
|
|
14
14
|
export function createContentBlocksItem(threadId, runId, agentId, contentBlocks) {
|
|
15
15
|
return {
|
|
16
16
|
type: "content-blocks",
|
|
17
|
-
threadId,
|
|
18
|
-
runId,
|
|
17
|
+
sessionId: threadId,
|
|
18
|
+
requestId: runId,
|
|
19
19
|
agentId,
|
|
20
20
|
contentBlocks,
|
|
21
21
|
};
|
|
@@ -44,8 +44,8 @@ export async function dispatchRunListeners(stream, listeners, options) {
|
|
|
44
44
|
await options.notifyListener(listeners.onUpstreamEvent, item.event);
|
|
45
45
|
if (item.surfaceItem) {
|
|
46
46
|
await options.notifyListener(listeners.onTraceItem, {
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
sessionId: item.sessionId,
|
|
48
|
+
requestId: item.requestId,
|
|
49
49
|
surfaceItem: item.surfaceItem,
|
|
50
50
|
event: item.event,
|
|
51
51
|
});
|
|
@@ -67,16 +67,16 @@ export async function dispatchRunListeners(stream, listeners, options) {
|
|
|
67
67
|
if (latestResult) {
|
|
68
68
|
return mergeRunResultOutput(latestResult, output);
|
|
69
69
|
}
|
|
70
|
-
const thread = await options.getThread(latestEvent.
|
|
70
|
+
const thread = await options.getThread(latestEvent.sessionId);
|
|
71
71
|
if (!thread) {
|
|
72
|
-
throw new Error(`Unknown
|
|
72
|
+
throw new Error(`Unknown session ${latestEvent.sessionId}`);
|
|
73
73
|
}
|
|
74
74
|
return createFallbackRunResultFromLatestEvent({
|
|
75
75
|
latestEvent,
|
|
76
76
|
currentState: thread.currentState,
|
|
77
|
-
latestRunId: thread.
|
|
77
|
+
latestRunId: thread.latestRequestId,
|
|
78
78
|
entryAgentId: thread.entryAgentId,
|
|
79
|
-
latestAgentId: thread.currentAgentId ?? thread.
|
|
79
|
+
latestAgentId: thread.currentAgentId ?? thread.requests[0]?.agentId,
|
|
80
80
|
approvalId: thread.pendingDecision?.approvalId,
|
|
81
81
|
pendingActionId: thread.pendingDecision?.pendingActionId,
|
|
82
82
|
output,
|
|
@@ -19,10 +19,10 @@ function classifyTimelineItem(event) {
|
|
|
19
19
|
}
|
|
20
20
|
export function projectRuntimeTimeline(events, options = {}) {
|
|
21
21
|
const filtered = events.filter((event) => {
|
|
22
|
-
if (options.
|
|
22
|
+
if (options.sessionId && event.sessionId !== options.sessionId) {
|
|
23
23
|
return false;
|
|
24
24
|
}
|
|
25
|
-
if (options.
|
|
25
|
+
if (options.requestId && event.requestId !== options.requestId) {
|
|
26
26
|
return false;
|
|
27
27
|
}
|
|
28
28
|
return true;
|
|
@@ -40,8 +40,8 @@ export function projectRuntimeTimeline(events, options = {}) {
|
|
|
40
40
|
})
|
|
41
41
|
.map((event) => ({
|
|
42
42
|
eventId: event.eventId,
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
sessionId: event.sessionId,
|
|
44
|
+
requestId: event.requestId,
|
|
45
45
|
eventType: event.eventType,
|
|
46
46
|
timestamp: event.timestamp,
|
|
47
47
|
sequence: event.sequence,
|
|
@@ -57,8 +57,8 @@ export function mergeRunResultOutput(result, streamedOutput) {
|
|
|
57
57
|
}
|
|
58
58
|
export function createFallbackRunResultFromLatestEvent(input) {
|
|
59
59
|
return {
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
sessionId: input.latestEvent.sessionId,
|
|
61
|
+
requestId: input.latestRunId,
|
|
62
62
|
agentId: input.latestAgentId ?? input.entryAgentId,
|
|
63
63
|
state: input.currentState,
|
|
64
64
|
output: input.output,
|