@botbotgo/agent-harness 0.0.267 → 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/README.md +8 -0
- package/README.zh.md +7 -0
- 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/dist/workspace/compile.js +6 -5
- package/dist/workspace/object-loader.d.ts +4 -1
- package/dist/workspace/object-loader.js +13 -5
- package/dist/workspace/support/workspace-ref-utils.d.ts +5 -0
- package/dist/workspace/support/workspace-ref-utils.js +9 -0
- package/dist/workspace/tool-hydration.d.ts +2 -1
- package/dist/workspace/tool-hydration.js +4 -4
- package/package.json +1 -1
|
@@ -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,
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { normalizeRunPriority } from "./helpers.js";
|
|
2
2
|
async function failRecovery(context, thread, previousState, error, options = {}) {
|
|
3
|
-
await context.setRunStateAndEmit(thread.
|
|
3
|
+
await context.setRunStateAndEmit(thread.sessionId, thread.latestRequestId, 100, "failed", {
|
|
4
4
|
previousState,
|
|
5
5
|
error,
|
|
6
6
|
});
|
|
7
7
|
if (options.releaseRunClaim) {
|
|
8
|
-
await context.persistence.releaseRunClaim(thread.
|
|
8
|
+
await context.persistence.releaseRunClaim(thread.latestRequestId);
|
|
9
9
|
}
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
12
12
|
async function resolveRecoveryBinding(context, thread) {
|
|
13
|
-
const runMeta = await context.persistence.getRunMeta(thread.
|
|
13
|
+
const runMeta = await context.persistence.getRunMeta(thread.sessionId, thread.latestRequestId);
|
|
14
14
|
const binding = context.getBinding(runMeta.agentId);
|
|
15
15
|
if (!binding) {
|
|
16
16
|
return null;
|
|
@@ -22,12 +22,12 @@ async function resolveRecoveryBinding(context, thread) {
|
|
|
22
22
|
}
|
|
23
23
|
async function executeRecoveredRun(context, input) {
|
|
24
24
|
const { thread, binding, agentId, request, previousState, emitResumeEvent } = input;
|
|
25
|
-
const releaseRunSlot = await context.acquireRunSlot(thread.
|
|
25
|
+
const releaseRunSlot = await context.acquireRunSlot(thread.sessionId, thread.latestRequestId, "running", normalizeRunPriority(request.priority));
|
|
26
26
|
try {
|
|
27
27
|
if (emitResumeEvent) {
|
|
28
|
-
await context.emit(thread.
|
|
28
|
+
await context.emit(thread.sessionId, thread.latestRequestId, emitResumeEvent.sequence, emitResumeEvent.eventType, emitResumeEvent.payload);
|
|
29
29
|
}
|
|
30
|
-
await context.executeQueuedRun(binding, request.input, thread.
|
|
30
|
+
await context.executeQueuedRun(binding, request.input, thread.sessionId, thread.latestRequestId, agentId, {
|
|
31
31
|
context: request.invocation?.context,
|
|
32
32
|
state: request.invocation?.inputs,
|
|
33
33
|
files: request.invocation?.attachments,
|
|
@@ -42,9 +42,9 @@ async function executeRecoveredRun(context, input) {
|
|
|
42
42
|
return true;
|
|
43
43
|
}
|
|
44
44
|
async function failResumingRecovery(context, thread, checkpointRef, error) {
|
|
45
|
-
await context.persistence.setRunState(thread.
|
|
46
|
-
await context.persistence.clearRecoveryIntent(thread.
|
|
47
|
-
await context.emit(thread.
|
|
45
|
+
await context.persistence.setRunState(thread.sessionId, thread.latestRequestId, "failed", checkpointRef);
|
|
46
|
+
await context.persistence.clearRecoveryIntent(thread.sessionId, thread.latestRequestId);
|
|
47
|
+
await context.emit(thread.sessionId, thread.latestRequestId, 101, "run.state.changed", {
|
|
48
48
|
previousState: "resuming",
|
|
49
49
|
state: "failed",
|
|
50
50
|
checkpointRef,
|
|
@@ -60,7 +60,7 @@ export async function recoverQueuedStartupRun(context, thread) {
|
|
|
60
60
|
if (!resolved) {
|
|
61
61
|
return true;
|
|
62
62
|
}
|
|
63
|
-
const request = await context.persistence.getRunRequest(thread.
|
|
63
|
+
const request = await context.persistence.getRunRequest(thread.sessionId, thread.latestRequestId);
|
|
64
64
|
if (!request) {
|
|
65
65
|
return failRecovery(context, thread, "queued", "missing persisted run request for queued run recovery");
|
|
66
66
|
}
|
|
@@ -89,7 +89,7 @@ export async function recoverRunningStartupRun(context, thread) {
|
|
|
89
89
|
releaseRunClaim: true,
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
|
-
const request = await context.persistence.getRunRequest(thread.
|
|
92
|
+
const request = await context.persistence.getRunRequest(thread.sessionId, thread.latestRequestId);
|
|
93
93
|
if (!request) {
|
|
94
94
|
return failRecovery(context, thread, "running", "missing persisted run request for stale running run recovery", {
|
|
95
95
|
releaseRunClaim: true,
|
|
@@ -119,31 +119,31 @@ export async function recoverResumingStartupRun(context, thread) {
|
|
|
119
119
|
if (!binding) {
|
|
120
120
|
return true;
|
|
121
121
|
}
|
|
122
|
-
const recoveryIntent = await context.persistence.getRecoveryIntent(thread.
|
|
122
|
+
const recoveryIntent = await context.persistence.getRecoveryIntent(thread.sessionId, thread.latestRequestId);
|
|
123
123
|
if (!recoveryIntent || recoveryIntent.kind !== "approval-decision") {
|
|
124
124
|
return true;
|
|
125
125
|
}
|
|
126
126
|
if (recoveryIntent.attempts >= context.recoveryConfig.maxRecoveryAttempts) {
|
|
127
127
|
return failResumingRecovery(context, thread, recoveryIntent.checkpointRef, "recovery attempts exhausted");
|
|
128
128
|
}
|
|
129
|
-
await context.persistence.saveRecoveryIntent(thread.
|
|
129
|
+
await context.persistence.saveRecoveryIntent(thread.sessionId, thread.latestRequestId, {
|
|
130
130
|
...recoveryIntent,
|
|
131
131
|
attempts: recoveryIntent.attempts + 1,
|
|
132
132
|
});
|
|
133
|
-
await context.emit(thread.
|
|
133
|
+
await context.emit(thread.sessionId, thread.latestRequestId, 100, "run.resumed", {
|
|
134
134
|
resumeKind: "startup-recovery",
|
|
135
135
|
checkpointRef: recoveryIntent.checkpointRef,
|
|
136
136
|
state: "resuming",
|
|
137
137
|
});
|
|
138
|
-
const history = await context.persistence.listThreadMessages(thread.
|
|
139
|
-
const priorHistory = history.filter((message) => message.
|
|
140
|
-
const runInput = await context.loadRunInput(thread.
|
|
138
|
+
const history = await context.persistence.listThreadMessages(thread.sessionId);
|
|
139
|
+
const priorHistory = history.filter((message) => message.requestId !== thread.latestRequestId);
|
|
140
|
+
const runInput = await context.loadRunInput(thread.sessionId, thread.latestRequestId);
|
|
141
141
|
const startedAt = Date.now();
|
|
142
142
|
try {
|
|
143
|
-
const actual = await context.runtimeAdapter.invoke(binding, "", thread.
|
|
143
|
+
const actual = await context.runtimeAdapter.invoke(binding, "", thread.sessionId, thread.latestRequestId, recoveryIntent.resumePayload, priorHistory);
|
|
144
144
|
context.recordLlmSuccess(startedAt);
|
|
145
|
-
await context.persistence.clearRecoveryIntent(thread.
|
|
146
|
-
await context.finalizeContinuedRun(binding, thread.
|
|
145
|
+
await context.persistence.clearRecoveryIntent(thread.sessionId, thread.latestRequestId);
|
|
146
|
+
await context.finalizeContinuedRun(binding, thread.sessionId, thread.latestRequestId, runInput, actual, {
|
|
147
147
|
previousState: "resuming",
|
|
148
148
|
stateSequence: 101,
|
|
149
149
|
approvalSequence: 102,
|
|
@@ -7,13 +7,13 @@ export async function resolveApprovalRecord(persistence, options, thread) {
|
|
|
7
7
|
}
|
|
8
8
|
return approval;
|
|
9
9
|
}
|
|
10
|
-
const
|
|
11
|
-
const approvals = await persistence.getRunApprovals(options.
|
|
10
|
+
const requestId = options.requestId ?? thread.latestRequestId;
|
|
11
|
+
const approvals = await persistence.getRunApprovals(options.sessionId ?? thread.sessionId, requestId);
|
|
12
12
|
const approval = approvals
|
|
13
13
|
.filter((candidate) => candidate.status === "pending")
|
|
14
14
|
.sort((left, right) => right.requestedAt.localeCompare(left.requestedAt))[0];
|
|
15
15
|
if (!approval) {
|
|
16
|
-
throw new Error(`No pending approval for run ${
|
|
16
|
+
throw new Error(`No pending approval for run ${requestId}`);
|
|
17
17
|
}
|
|
18
18
|
return approval;
|
|
19
19
|
}
|
|
@@ -5,7 +5,7 @@ export async function appendAssistantMessage(persistence, threadId, runId, conte
|
|
|
5
5
|
await persistence.appendThreadMessage(threadId, {
|
|
6
6
|
role: "assistant",
|
|
7
7
|
content,
|
|
8
|
-
runId,
|
|
8
|
+
requestId: runId,
|
|
9
9
|
createdAt: new Date().toISOString(),
|
|
10
10
|
});
|
|
11
11
|
}
|
|
@@ -38,8 +38,8 @@ export async function finalizeCancelledRun(runtime, threadId, runId, previousSta
|
|
|
38
38
|
});
|
|
39
39
|
const runMeta = await runtime.persistence.getRunMeta(threadId, runId);
|
|
40
40
|
return {
|
|
41
|
-
threadId,
|
|
42
|
-
runId,
|
|
41
|
+
sessionId: threadId,
|
|
42
|
+
requestId: runId,
|
|
43
43
|
agentId: runMeta.agentId,
|
|
44
44
|
state: "cancelled",
|
|
45
45
|
output: reason ? `cancelled: ${reason}` : "cancelled",
|
|
@@ -58,8 +58,8 @@ export async function finalizeContinuedRun(runtime, binding, threadId, runId, in
|
|
|
58
58
|
}
|
|
59
59
|
return {
|
|
60
60
|
...actual,
|
|
61
|
-
threadId,
|
|
62
|
-
runId,
|
|
61
|
+
sessionId: threadId,
|
|
62
|
+
requestId: runId,
|
|
63
63
|
approvalId: approval?.approvalId ?? actual.approvalId,
|
|
64
64
|
pendingActionId: approval?.pendingActionId ?? actual.pendingActionId,
|
|
65
65
|
};
|
|
@@ -31,8 +31,8 @@ type ResumeOperationRuntime = {
|
|
|
31
31
|
};
|
|
32
32
|
type CancelOperationRuntime = {
|
|
33
33
|
getRun: (runId: string) => Promise<{
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
sessionId: string;
|
|
35
|
+
requestId: string;
|
|
36
36
|
agentId: string;
|
|
37
37
|
state: RunResult["state"];
|
|
38
38
|
} | null>;
|