@botbotgo/agent-harness 0.0.185 → 0.0.187
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 +1 -1
- package/README.zh.md +1 -1
- package/dist/api.d.ts +8 -7
- package/dist/api.js +7 -61
- package/dist/contracts/runtime.d.ts +38 -22
- package/dist/mcp.d.ts +12 -12
- package/dist/mcp.js +7 -7
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/protocol/ag-ui/http.d.ts +41 -0
- package/dist/protocol/ag-ui/http.js +181 -7
- package/dist/runtime/harness/run/thread-records.d.ts +10 -1
- package/dist/runtime/harness/run/thread-records.js +97 -15
- package/dist/runtime/harness.d.ts +16 -1
- package/dist/runtime/harness.js +216 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -954,7 +954,7 @@ ACP transport notes:
|
|
|
954
954
|
- `serveAcpStdio(runtime)` exposes newline-delimited JSON-RPC over stdio for local IDE, CLI, or subprocess clients.
|
|
955
955
|
- `serveAcpHttp(runtime)` exposes JSON-RPC over HTTP plus SSE runtime events so remote operator surfaces can connect without importing the runtime in-process.
|
|
956
956
|
- `serveA2aHttp(runtime)` exposes a minimal A2A-compatible HTTP JSON-RPC bridge plus agent card discovery, mapping `message/send`, `tasks/get`, and `tasks/cancel` onto the existing session/request runtime surface.
|
|
957
|
-
- `serveAgUiHttp(runtime)` exposes
|
|
957
|
+
- `serveAgUiHttp(runtime)` exposes an AG-UI-compatible HTTP SSE bridge that projects runtime lifecycle, text output, upstream thinking, step progress, and tool calls onto `RUN_*`, `TEXT_MESSAGE_*`, `THINKING_TEXT_MESSAGE_*`, `STEP_*`, and `TOOL_CALL_*` events for UI clients.
|
|
958
958
|
- `createRuntimeMcpServer(runtime)` and `serveRuntimeMcpOverStdio(runtime)` expose the persisted runtime control surface itself as MCP tools, including sessions, requests, approvals, artifacts, events, and package export helpers.
|
|
959
959
|
- `listRequestEvents(...)` and `exportRequestPackage(...)` are the request-first inspection helpers.
|
|
960
960
|
- `exportRequestPackage(...)` and `exportSessionPackage(...)` package stable runtime records, transcript, approvals, events, and artifacts for operator tooling without reaching into persistence internals.
|
package/README.zh.md
CHANGED
|
@@ -913,7 +913,7 @@ ACP transport 说明:
|
|
|
913
913
|
- `serveAcpStdio(runtime)` 提供基于 stdio 的 newline-delimited JSON-RPC,适合本地 IDE、CLI 或子进程客户端。
|
|
914
914
|
- `serveAcpHttp(runtime)` 提供基于 HTTP 的 JSON-RPC 与 SSE runtime events,适合远程 operator surface 或独立控制面接入。
|
|
915
915
|
- `serveA2aHttp(runtime)` 提供最小可用的 A2A HTTP JSON-RPC bridge 与 agent card discovery,把 `message/send`、`tasks/get`、`tasks/cancel` 映射到现有 session/request runtime surface。
|
|
916
|
-
- `serveAgUiHttp(runtime)`
|
|
916
|
+
- `serveAgUiHttp(runtime)` 提供 AG-UI HTTP SSE bridge,把 runtime 生命周期、文本输出、upstream thinking、step 进度与 tool call 投影成 `RUN_*`、`TEXT_MESSAGE_*`、`THINKING_TEXT_MESSAGE_*`、`STEP_*` 与 `TOOL_CALL_*` 事件,便于 UI 客户端直接接入。
|
|
917
917
|
- `createRuntimeMcpServer(runtime)` 与 `serveRuntimeMcpOverStdio(runtime)` 会把持久化 runtime 控制面本身暴露成 MCP tools,包括 sessions、requests、approvals、artifacts、events 与 package export helpers。
|
|
918
918
|
- `listRequestEvents(...)` 与 `exportRequestPackage(...)` 是 request-first 的检查 helper。
|
|
919
919
|
- `exportRequestPackage(...)` 与 `exportSessionPackage(...)` 可把稳定 runtime 记录、transcript、approvals、events 和 artifacts 打包给 operator tooling,而不必直接访问 persistence 内部实现。
|
package/dist/api.d.ts
CHANGED
|
@@ -77,21 +77,22 @@ type PublicApprovalFilter = {
|
|
|
77
77
|
sessionId?: string;
|
|
78
78
|
requestId?: string;
|
|
79
79
|
};
|
|
80
|
-
type
|
|
80
|
+
type PublicRequestStartOptions = Omit<RunStartOptions, "threadId" | "listeners"> & {
|
|
81
81
|
sessionId?: string;
|
|
82
82
|
listeners?: PublicRunListeners;
|
|
83
83
|
};
|
|
84
|
-
type
|
|
84
|
+
type PublicRequestDecisionOptions = Omit<RunDecisionOptions, "threadId" | "runId" | "listeners"> & {
|
|
85
85
|
sessionId: string;
|
|
86
86
|
requestId?: string;
|
|
87
87
|
listeners?: PublicRunListeners;
|
|
88
88
|
};
|
|
89
|
-
type
|
|
90
|
-
type
|
|
89
|
+
type PublicRequestOptions = PublicRequestStartOptions | PublicRequestDecisionOptions;
|
|
90
|
+
type PublicRequestResult = Omit<RunResult, "threadId" | "runId"> & {
|
|
91
91
|
sessionId: string;
|
|
92
92
|
requestId: string;
|
|
93
93
|
};
|
|
94
|
-
|
|
94
|
+
type PublicRunResult = PublicRequestResult;
|
|
95
|
+
export type RequestResult = PublicRequestResult;
|
|
95
96
|
export type UserChatMessage = {
|
|
96
97
|
role: "user";
|
|
97
98
|
content: MessageContent;
|
|
@@ -111,14 +112,14 @@ type CreateAgentHarnessOptions = {
|
|
|
111
112
|
export declare function createAgentHarness(): Promise<AgentHarnessRuntime>;
|
|
112
113
|
export declare function createAgentHarness(workspaceRoot: string, options?: CreateAgentHarnessOptions): Promise<AgentHarnessRuntime>;
|
|
113
114
|
export declare function normalizeUserChatInput(input: UserChatInput, options?: NormalizeUserChatInputOptions): Pick<RunStartOptions, "input" | "invocation">;
|
|
114
|
-
export declare function request(runtime: AgentHarnessRuntime, options:
|
|
115
|
+
export declare function request(runtime: AgentHarnessRuntime, options: PublicRequestOptions): Promise<PublicRequestResult>;
|
|
115
116
|
export declare function memorize(runtime: AgentHarnessRuntime, input: MemorizeInput): Promise<MemorizeResult>;
|
|
116
117
|
export declare function recall(runtime: AgentHarnessRuntime, input: RecallInput): Promise<RecallResult>;
|
|
117
118
|
export declare function listMemories(runtime: AgentHarnessRuntime, input?: ListMemoriesInput): Promise<ListMemoriesResult>;
|
|
118
119
|
export declare function updateMemory(runtime: AgentHarnessRuntime, input: UpdateMemoryInput): Promise<MemoryRecord>;
|
|
119
120
|
export declare function removeMemory(runtime: AgentHarnessRuntime, input: RemoveMemoryInput): Promise<MemoryRecord>;
|
|
120
121
|
export declare function subscribe(runtime: AgentHarnessRuntime, listener: (event: RequestEvent) => void | Promise<void>): () => void;
|
|
121
|
-
export declare function listSessions(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["
|
|
122
|
+
export declare function listSessions(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listSessions"]>[0]): Promise<SessionSummary[]>;
|
|
122
123
|
export declare function listRequests(runtime: AgentHarnessRuntime, filter?: {
|
|
123
124
|
agentId?: string;
|
|
124
125
|
sessionId?: string;
|
package/dist/api.js
CHANGED
|
@@ -9,54 +9,6 @@ export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
|
|
|
9
9
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
10
10
|
export { buildFlowGraph, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid } from "./flow/index.js";
|
|
11
11
|
export { createUpstreamTimelineReducer } from "./upstream-events.js";
|
|
12
|
-
function toSessionSummary(summary) {
|
|
13
|
-
return {
|
|
14
|
-
agentId: summary.agentId,
|
|
15
|
-
sessionId: summary.threadId,
|
|
16
|
-
latestRequestId: summary.latestRunId,
|
|
17
|
-
createdAt: summary.createdAt,
|
|
18
|
-
updatedAt: summary.updatedAt,
|
|
19
|
-
status: summary.status,
|
|
20
|
-
currentAgentId: summary.currentAgentId,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function toRequestSummary(summary) {
|
|
24
|
-
return {
|
|
25
|
-
requestId: summary.runId,
|
|
26
|
-
sessionId: summary.threadId,
|
|
27
|
-
agentId: summary.agentId,
|
|
28
|
-
executionMode: summary.executionMode,
|
|
29
|
-
adapterKind: summary.adapterKind,
|
|
30
|
-
createdAt: summary.createdAt,
|
|
31
|
-
updatedAt: summary.updatedAt,
|
|
32
|
-
state: summary.state,
|
|
33
|
-
checkpointRef: summary.checkpointRef,
|
|
34
|
-
resumable: summary.resumable,
|
|
35
|
-
startedAt: summary.startedAt,
|
|
36
|
-
endedAt: summary.endedAt,
|
|
37
|
-
lastActivityAt: summary.lastActivityAt,
|
|
38
|
-
currentAgentId: summary.currentAgentId,
|
|
39
|
-
delegationChain: summary.delegationChain,
|
|
40
|
-
runtimeSnapshot: summary.runtimeSnapshot,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
function toSessionRecord(record) {
|
|
44
|
-
return {
|
|
45
|
-
sessionId: record.threadId,
|
|
46
|
-
entryAgentId: record.entryAgentId,
|
|
47
|
-
currentAgentId: record.currentAgentId,
|
|
48
|
-
currentState: record.currentState,
|
|
49
|
-
latestRequestId: record.latestRunId,
|
|
50
|
-
createdAt: record.createdAt,
|
|
51
|
-
updatedAt: record.updatedAt,
|
|
52
|
-
messages: record.messages,
|
|
53
|
-
requests: record.runs.map(toRequestSummary),
|
|
54
|
-
pendingDecision: record.pendingDecision,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function toRequestRecord(record) {
|
|
58
|
-
return toRequestSummary(record);
|
|
59
|
-
}
|
|
60
12
|
function toApprovalRecord(record) {
|
|
61
13
|
return {
|
|
62
14
|
approvalId: record.approvalId,
|
|
@@ -218,25 +170,19 @@ export function subscribe(runtime, listener) {
|
|
|
218
170
|
});
|
|
219
171
|
}
|
|
220
172
|
export async function listSessions(runtime, filter) {
|
|
221
|
-
return
|
|
173
|
+
return runtime.listSessions(filter);
|
|
222
174
|
}
|
|
223
175
|
export async function listRequests(runtime, filter) {
|
|
224
|
-
return
|
|
225
|
-
agentId: filter?.agentId,
|
|
226
|
-
state: filter?.state,
|
|
227
|
-
threadId: filter?.sessionId,
|
|
228
|
-
})).map(toRequestSummary);
|
|
176
|
+
return runtime.listRequests(filter);
|
|
229
177
|
}
|
|
230
178
|
export async function getSession(runtime, sessionId) {
|
|
231
|
-
|
|
232
|
-
return record ? toSessionRecord(record) : null;
|
|
179
|
+
return runtime.getSessionRecord(sessionId);
|
|
233
180
|
}
|
|
234
181
|
export async function getRequest(runtime, requestId) {
|
|
235
|
-
|
|
236
|
-
return record ? toRequestRecord(record) : null;
|
|
182
|
+
return runtime.getRequest(requestId);
|
|
237
183
|
}
|
|
238
184
|
export async function deleteSession(runtime, sessionId) {
|
|
239
|
-
return runtime.
|
|
185
|
+
return runtime.deleteSession(sessionId);
|
|
240
186
|
}
|
|
241
187
|
export async function listApprovals(runtime, filter) {
|
|
242
188
|
return (await runtime.listApprovals({
|
|
@@ -256,13 +202,13 @@ export async function getArtifact(runtime, input) {
|
|
|
256
202
|
return runtime.readArtifact(input.sessionId, input.requestId, input.artifactPath);
|
|
257
203
|
}
|
|
258
204
|
export async function listRequestEvents(runtime, input) {
|
|
259
|
-
return (await runtime.
|
|
205
|
+
return (await runtime.listRequestEvents(input.sessionId, input.requestId)).map(toPublicEvent);
|
|
260
206
|
}
|
|
261
207
|
export async function getHealth(runtime) {
|
|
262
208
|
return runtime.getHealth();
|
|
263
209
|
}
|
|
264
210
|
export async function exportRequestPackage(runtime, input) {
|
|
265
|
-
return toRequestPackage(await runtime.
|
|
211
|
+
return toRequestPackage(await runtime.exportRequestPackage(input));
|
|
266
212
|
}
|
|
267
213
|
export async function exportSessionPackage(runtime, input) {
|
|
268
214
|
return runtime.exportSessionPackage(input);
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import type { RunState } from "./core.js";
|
|
2
2
|
import type { CompiledAgentBinding, CompiledModel, CompiledTool, ParsedAgentObject, ParsedToolObject, WorkspaceBundle } from "./workspace.js";
|
|
3
3
|
/**
|
|
4
|
-
* Persisted runtime summary for an inspectable conversation
|
|
5
|
-
* This
|
|
6
|
-
* inspection surface.
|
|
4
|
+
* Persisted runtime summary for an inspectable conversation session.
|
|
5
|
+
* This is the canonical runtime-facing conversation record.
|
|
7
6
|
*/
|
|
8
|
-
export type
|
|
7
|
+
export type SessionSummary = {
|
|
9
8
|
agentId: string;
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
sessionId: string;
|
|
10
|
+
latestRequestId: string;
|
|
12
11
|
createdAt: string;
|
|
13
12
|
updatedAt: string;
|
|
14
13
|
status: RunState;
|
|
15
14
|
currentAgentId?: string;
|
|
16
15
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Backward-compatible alias for older thread/run terminology.
|
|
18
|
+
*/
|
|
19
|
+
export type ThreadSummary = Omit<SessionSummary, "sessionId" | "latestRequestId"> & {
|
|
20
|
+
threadId: string;
|
|
21
|
+
latestRunId: string;
|
|
20
22
|
};
|
|
21
23
|
export type KnownHarnessEventType = "run.created" | "run.queued" | "run.dequeued" | "run.state.changed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "runtime.health.changed" | "runtime.synthetic_fallback";
|
|
22
24
|
export type HarnessEventType = KnownHarnessEventType | (string & {});
|
|
@@ -192,6 +194,8 @@ export type MemorizeInputRecord = {
|
|
|
192
194
|
};
|
|
193
195
|
export type MemorizeInput = {
|
|
194
196
|
records: MemorizeInputRecord[];
|
|
197
|
+
sessionId?: string;
|
|
198
|
+
requestId?: string;
|
|
195
199
|
threadId?: string;
|
|
196
200
|
runId?: string;
|
|
197
201
|
agentId?: string;
|
|
@@ -209,6 +213,7 @@ export type RecallInput = {
|
|
|
209
213
|
kinds?: MemoryKind[];
|
|
210
214
|
topK?: number;
|
|
211
215
|
includeStale?: boolean;
|
|
216
|
+
sessionId?: string;
|
|
212
217
|
threadId?: string;
|
|
213
218
|
agentId?: string;
|
|
214
219
|
workspaceId?: string;
|
|
@@ -222,6 +227,7 @@ export type ListMemoriesInput = {
|
|
|
222
227
|
scopes?: MemoryScope[];
|
|
223
228
|
kinds?: MemoryKind[];
|
|
224
229
|
status?: MemoryRecordStatus[];
|
|
230
|
+
sessionId?: string;
|
|
225
231
|
threadId?: string;
|
|
226
232
|
agentId?: string;
|
|
227
233
|
workspaceId?: string;
|
|
@@ -418,29 +424,36 @@ export type ThreadRunRecord = {
|
|
|
418
424
|
runtimeSnapshot?: RuntimeSnapshot;
|
|
419
425
|
};
|
|
420
426
|
/**
|
|
421
|
-
* Persisted
|
|
427
|
+
* Persisted request summary projected from upstream execution state plus runtime lifecycle metadata.
|
|
428
|
+
* This is the canonical runtime-facing execution record.
|
|
422
429
|
*/
|
|
423
|
-
export type
|
|
424
|
-
export type RunRecord = RunSummary;
|
|
425
|
-
export type RequestSummary = Omit<RunSummary, "threadId" | "runId"> & {
|
|
430
|
+
export type RequestSummary = Omit<ThreadRunRecord, "threadId" | "runId"> & {
|
|
426
431
|
sessionId: string;
|
|
427
432
|
requestId: string;
|
|
428
433
|
};
|
|
429
434
|
export type RequestRecord = RequestSummary;
|
|
430
435
|
/**
|
|
431
|
-
*
|
|
432
|
-
* This is an inspectable projection, not a second thread semantic model.
|
|
436
|
+
* Backward-compatible alias for older thread/run terminology.
|
|
433
437
|
*/
|
|
434
|
-
export type
|
|
438
|
+
export type RunSummary = Omit<RequestSummary, "sessionId" | "requestId"> & {
|
|
435
439
|
threadId: string;
|
|
440
|
+
runId: string;
|
|
441
|
+
};
|
|
442
|
+
export type RunRecord = RunSummary;
|
|
443
|
+
/**
|
|
444
|
+
* Persisted session inspection record assembled from runtime records.
|
|
445
|
+
* This is an inspectable projection, not a second session semantic model.
|
|
446
|
+
*/
|
|
447
|
+
export type SessionRecord = {
|
|
448
|
+
sessionId: string;
|
|
436
449
|
entryAgentId: string;
|
|
437
450
|
currentAgentId?: string;
|
|
438
451
|
currentState: RunState;
|
|
439
|
-
|
|
452
|
+
latestRequestId: string;
|
|
440
453
|
createdAt: string;
|
|
441
454
|
updatedAt: string;
|
|
442
455
|
messages: TranscriptMessage[];
|
|
443
|
-
|
|
456
|
+
requests: RequestSummary[];
|
|
444
457
|
pendingDecision?: {
|
|
445
458
|
approvalId: string;
|
|
446
459
|
pendingActionId: string;
|
|
@@ -449,10 +462,13 @@ export type ThreadRecord = {
|
|
|
449
462
|
requestedAt: string;
|
|
450
463
|
};
|
|
451
464
|
};
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
465
|
+
/**
|
|
466
|
+
* Backward-compatible alias for older thread/run terminology.
|
|
467
|
+
*/
|
|
468
|
+
export type ThreadRecord = Omit<SessionRecord, "sessionId" | "latestRequestId" | "requests"> & {
|
|
469
|
+
threadId: string;
|
|
470
|
+
latestRunId: string;
|
|
471
|
+
runs: RunSummary[];
|
|
456
472
|
};
|
|
457
473
|
export type ResumeOptions = {
|
|
458
474
|
threadId?: string;
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type { ApprovalRecord, ArtifactListing, CompiledTool, HarnessEvent, ParsedToolObject, RunResult, RunState,
|
|
2
|
+
import type { ApprovalRecord, ArtifactListing, CompiledTool, HarnessEvent, ParsedToolObject, RequestRecord, RunResult, RunState, RequestSummary, RuntimeSessionPackage, RuntimeSessionPackageInput, SessionRecord, SessionSummary } from "./contracts/types.js";
|
|
3
3
|
export type ToolMcpServerOptions = {
|
|
4
4
|
agentId: string;
|
|
5
5
|
serverInfo?: {
|
|
@@ -20,16 +20,16 @@ export type RuntimeMcpServerOptions = {
|
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
type RuntimeMcpRuntime = {
|
|
23
|
-
|
|
23
|
+
listSessions: (filter?: {
|
|
24
24
|
agentId?: string;
|
|
25
|
-
}) => Promise<
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
}) => Promise<SessionSummary[]>;
|
|
26
|
+
getSessionRecord: (sessionId: string) => Promise<SessionRecord | null>;
|
|
27
|
+
listRequests: (filter?: {
|
|
28
28
|
agentId?: string;
|
|
29
|
-
|
|
29
|
+
sessionId?: string;
|
|
30
30
|
state?: RunState;
|
|
31
|
-
}) => Promise<
|
|
32
|
-
|
|
31
|
+
}) => Promise<RequestSummary[]>;
|
|
32
|
+
getRequest: (requestId: string) => Promise<RequestRecord | null>;
|
|
33
33
|
listApprovals: (filter?: {
|
|
34
34
|
status?: ApprovalRecord["status"];
|
|
35
35
|
threadId?: string;
|
|
@@ -43,10 +43,10 @@ type RuntimeMcpRuntime = {
|
|
|
43
43
|
decision?: "approve" | "edit" | "reject";
|
|
44
44
|
editedInput?: Record<string, unknown>;
|
|
45
45
|
}) => Promise<RunResult>;
|
|
46
|
-
listArtifacts: (
|
|
47
|
-
readArtifact: (
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
listArtifacts: (sessionId: string, requestId: string) => Promise<ArtifactListing>;
|
|
47
|
+
readArtifact: (sessionId: string, requestId: string, artifactPath: string) => Promise<unknown>;
|
|
48
|
+
listRequestEvents: (sessionId: string, requestId: string) => Promise<HarnessEvent[]>;
|
|
49
|
+
exportRequestPackage: (input: {
|
|
50
50
|
sessionId: string;
|
|
51
51
|
requestId: string;
|
|
52
52
|
includeArtifacts?: boolean;
|
package/dist/mcp.js
CHANGED
|
@@ -120,7 +120,7 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
120
120
|
}, async (input) => ({
|
|
121
121
|
content: [{
|
|
122
122
|
type: "text",
|
|
123
|
-
text: renderToolOutput(await runtime.
|
|
123
|
+
text: renderToolOutput(await runtime.listSessions(input.agentId ? { agentId: input.agentId } : undefined)),
|
|
124
124
|
}],
|
|
125
125
|
}));
|
|
126
126
|
server.tool("get_session", "Get one persisted runtime session by id.", {
|
|
@@ -128,7 +128,7 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
128
128
|
}, async (input) => ({
|
|
129
129
|
content: [{
|
|
130
130
|
type: "text",
|
|
131
|
-
text: renderToolOutput(await runtime.
|
|
131
|
+
text: renderToolOutput(await runtime.getSessionRecord(input.sessionId)),
|
|
132
132
|
}],
|
|
133
133
|
}));
|
|
134
134
|
server.tool("list_requests", "List persisted runtime requests.", {
|
|
@@ -138,9 +138,9 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
138
138
|
}, async (input) => ({
|
|
139
139
|
content: [{
|
|
140
140
|
type: "text",
|
|
141
|
-
text: renderToolOutput(await runtime.
|
|
141
|
+
text: renderToolOutput(await runtime.listRequests({
|
|
142
142
|
...(input.agentId ? { agentId: input.agentId } : {}),
|
|
143
|
-
...(input.sessionId ? {
|
|
143
|
+
...(input.sessionId ? { sessionId: input.sessionId } : {}),
|
|
144
144
|
...(input.state ? { state: input.state } : {}),
|
|
145
145
|
})),
|
|
146
146
|
}],
|
|
@@ -150,7 +150,7 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
150
150
|
}, async (input) => ({
|
|
151
151
|
content: [{
|
|
152
152
|
type: "text",
|
|
153
|
-
text: renderToolOutput(await runtime.
|
|
153
|
+
text: renderToolOutput(await runtime.getRequest(input.requestId)),
|
|
154
154
|
}],
|
|
155
155
|
}));
|
|
156
156
|
server.tool("list_approvals", "List runtime approvals.", {
|
|
@@ -218,7 +218,7 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
218
218
|
}, async (input) => ({
|
|
219
219
|
content: [{
|
|
220
220
|
type: "text",
|
|
221
|
-
text: renderToolOutput(await runtime.
|
|
221
|
+
text: renderToolOutput(await runtime.listRequestEvents(input.sessionId, input.requestId)),
|
|
222
222
|
}],
|
|
223
223
|
}));
|
|
224
224
|
server.tool("export_request_package", "Export a stable runtime request package for one request.", {
|
|
@@ -230,7 +230,7 @@ export async function createRuntimeMcpServer(runtime, options = {}) {
|
|
|
230
230
|
}, async (input) => ({
|
|
231
231
|
content: [{
|
|
232
232
|
type: "text",
|
|
233
|
-
text: renderToolOutput(await runtime.
|
|
233
|
+
text: renderToolOutput(await runtime.exportRequestPackage(input)),
|
|
234
234
|
}],
|
|
235
235
|
}));
|
|
236
236
|
server.tool("export_session_package", "Export a stable runtime session package.", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.186";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.186";
|
|
@@ -20,6 +20,28 @@ export type AgUiEvent = (AgUiBaseEvent & {
|
|
|
20
20
|
threadId: string;
|
|
21
21
|
runId: string;
|
|
22
22
|
input?: MessageContent;
|
|
23
|
+
}) | (AgUiBaseEvent & {
|
|
24
|
+
type: "STEP_STARTED";
|
|
25
|
+
stepId: string;
|
|
26
|
+
title: string;
|
|
27
|
+
category: "llm" | "tool" | "skill" | "memory" | "chain" | "approval";
|
|
28
|
+
}) | (AgUiBaseEvent & {
|
|
29
|
+
type: "STEP_FINISHED";
|
|
30
|
+
stepId: string;
|
|
31
|
+
title: string;
|
|
32
|
+
category: "llm" | "tool" | "skill" | "memory" | "chain" | "approval";
|
|
33
|
+
status: "completed" | "failed";
|
|
34
|
+
}) | (AgUiBaseEvent & {
|
|
35
|
+
type: "THINKING_TEXT_MESSAGE_START";
|
|
36
|
+
messageId: string;
|
|
37
|
+
role: "assistant";
|
|
38
|
+
}) | (AgUiBaseEvent & {
|
|
39
|
+
type: "THINKING_TEXT_MESSAGE_CONTENT";
|
|
40
|
+
messageId: string;
|
|
41
|
+
delta: string;
|
|
42
|
+
}) | (AgUiBaseEvent & {
|
|
43
|
+
type: "THINKING_TEXT_MESSAGE_END";
|
|
44
|
+
messageId: string;
|
|
23
45
|
}) | (AgUiBaseEvent & {
|
|
24
46
|
type: "TEXT_MESSAGE_START";
|
|
25
47
|
messageId: string;
|
|
@@ -31,6 +53,25 @@ export type AgUiEvent = (AgUiBaseEvent & {
|
|
|
31
53
|
}) | (AgUiBaseEvent & {
|
|
32
54
|
type: "TEXT_MESSAGE_END";
|
|
33
55
|
messageId: string;
|
|
56
|
+
}) | (AgUiBaseEvent & {
|
|
57
|
+
type: "TOOL_CALL_START";
|
|
58
|
+
toolCallId: string;
|
|
59
|
+
toolName: string;
|
|
60
|
+
}) | (AgUiBaseEvent & {
|
|
61
|
+
type: "TOOL_CALL_ARGS";
|
|
62
|
+
toolCallId: string;
|
|
63
|
+
toolName: string;
|
|
64
|
+
args: unknown;
|
|
65
|
+
}) | (AgUiBaseEvent & {
|
|
66
|
+
type: "TOOL_CALL_RESULT";
|
|
67
|
+
toolCallId: string;
|
|
68
|
+
toolName: string;
|
|
69
|
+
result: unknown;
|
|
70
|
+
isError?: boolean;
|
|
71
|
+
}) | (AgUiBaseEvent & {
|
|
72
|
+
type: "TOOL_CALL_END";
|
|
73
|
+
toolCallId: string;
|
|
74
|
+
toolName: string;
|
|
34
75
|
}) | (AgUiBaseEvent & {
|
|
35
76
|
type: "RUN_FINISHED";
|
|
36
77
|
threadId: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
2
|
import { createPersistentId } from "../../utils/id.js";
|
|
3
|
+
import { createUpstreamTimelineReducer } from "../../upstream-events.js";
|
|
3
4
|
function normalizePath(value, fallback) {
|
|
4
5
|
const source = typeof value === "string" && value.trim().length > 0 ? value.trim() : fallback;
|
|
5
6
|
return source.startsWith("/") ? source : `/${source}`;
|
|
@@ -55,6 +56,63 @@ function toRunStarted(event, input) {
|
|
|
55
56
|
input,
|
|
56
57
|
};
|
|
57
58
|
}
|
|
59
|
+
function asObject(value) {
|
|
60
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
61
|
+
}
|
|
62
|
+
function readUpstreamEventName(event) {
|
|
63
|
+
return typeof asObject(event)?.event === "string" ? String(asObject(event)?.event) : "";
|
|
64
|
+
}
|
|
65
|
+
function readUpstreamToolName(event) {
|
|
66
|
+
return typeof asObject(event)?.name === "string" ? String(asObject(event)?.name) : "";
|
|
67
|
+
}
|
|
68
|
+
function readUpstreamRunType(event) {
|
|
69
|
+
return typeof asObject(event)?.run_type === "string" ? String(asObject(event)?.run_type) : "";
|
|
70
|
+
}
|
|
71
|
+
function isToolStartEvent(event) {
|
|
72
|
+
const eventName = readUpstreamEventName(event);
|
|
73
|
+
return eventName === "on_tool_start" || (eventName === "on_chain_start" && readUpstreamRunType(event) === "tool");
|
|
74
|
+
}
|
|
75
|
+
function isToolTerminalEvent(event) {
|
|
76
|
+
const eventName = readUpstreamEventName(event);
|
|
77
|
+
return eventName === "on_tool_end"
|
|
78
|
+
|| eventName === "on_tool_error"
|
|
79
|
+
|| ((eventName === "on_chain_end" || eventName === "on_chain_error") && readUpstreamRunType(event) === "tool");
|
|
80
|
+
}
|
|
81
|
+
function readToolArgs(event) {
|
|
82
|
+
const typed = asObject(event);
|
|
83
|
+
const data = asObject(typed?.data);
|
|
84
|
+
if (!data || !("input" in data)) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
return data.input;
|
|
88
|
+
}
|
|
89
|
+
function createToolCallState() {
|
|
90
|
+
const activeToolCallIds = new Map();
|
|
91
|
+
return {
|
|
92
|
+
start(toolName) {
|
|
93
|
+
const toolCallId = `tool-${createPersistentId()}`;
|
|
94
|
+
const activeIds = activeToolCallIds.get(toolName) ?? [];
|
|
95
|
+
activeIds.push(toolCallId);
|
|
96
|
+
activeToolCallIds.set(toolName, activeIds);
|
|
97
|
+
return toolCallId;
|
|
98
|
+
},
|
|
99
|
+
peek(toolName) {
|
|
100
|
+
const activeIds = activeToolCallIds.get(toolName);
|
|
101
|
+
return activeIds?.at(-1);
|
|
102
|
+
},
|
|
103
|
+
finish(toolName) {
|
|
104
|
+
const activeIds = activeToolCallIds.get(toolName);
|
|
105
|
+
if (!activeIds || activeIds.length === 0) {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
const toolCallId = activeIds.pop();
|
|
109
|
+
if (!activeIds.length) {
|
|
110
|
+
activeToolCallIds.delete(toolName);
|
|
111
|
+
}
|
|
112
|
+
return toolCallId;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
58
116
|
export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
59
117
|
const hostname = options.hostname?.trim() || "127.0.0.1";
|
|
60
118
|
const port = typeof options.port === "number" && Number.isFinite(options.port) ? options.port : 0;
|
|
@@ -74,7 +132,11 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
74
132
|
let runId;
|
|
75
133
|
let threadId;
|
|
76
134
|
let messageId;
|
|
135
|
+
let thinkingMessageId;
|
|
77
136
|
let textMessageStarted = false;
|
|
137
|
+
let thinkingMessageStarted = false;
|
|
138
|
+
const toolCalls = createToolCallState();
|
|
139
|
+
const upstreamReducer = createUpstreamTimelineReducer();
|
|
78
140
|
const ensureTextStart = async () => {
|
|
79
141
|
if (textMessageStarted) {
|
|
80
142
|
return;
|
|
@@ -88,6 +150,37 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
88
150
|
role: "assistant",
|
|
89
151
|
});
|
|
90
152
|
};
|
|
153
|
+
const ensureThinkingTextStart = async () => {
|
|
154
|
+
if (thinkingMessageStarted) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
thinkingMessageId = thinkingMessageId ?? `thinking-${createPersistentId()}`;
|
|
158
|
+
thinkingMessageStarted = true;
|
|
159
|
+
await writeSseEvent(response, {
|
|
160
|
+
type: "THINKING_TEXT_MESSAGE_START",
|
|
161
|
+
timestamp: createTimestamp(),
|
|
162
|
+
messageId: thinkingMessageId,
|
|
163
|
+
role: "assistant",
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
const closeOpenMessages = async () => {
|
|
167
|
+
if (thinkingMessageStarted) {
|
|
168
|
+
await writeSseEvent(response, {
|
|
169
|
+
type: "THINKING_TEXT_MESSAGE_END",
|
|
170
|
+
timestamp: createTimestamp(),
|
|
171
|
+
messageId: thinkingMessageId,
|
|
172
|
+
});
|
|
173
|
+
thinkingMessageStarted = false;
|
|
174
|
+
}
|
|
175
|
+
if (textMessageStarted) {
|
|
176
|
+
await writeSseEvent(response, {
|
|
177
|
+
type: "TEXT_MESSAGE_END",
|
|
178
|
+
timestamp: createTimestamp(),
|
|
179
|
+
messageId: messageId,
|
|
180
|
+
});
|
|
181
|
+
textMessageStarted = false;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
91
184
|
try {
|
|
92
185
|
const body = await readRequestBody(request);
|
|
93
186
|
const input = parseRunInput(JSON.parse(body));
|
|
@@ -120,6 +213,92 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
120
213
|
});
|
|
121
214
|
}
|
|
122
215
|
},
|
|
216
|
+
onUpstreamEvent: async (event) => {
|
|
217
|
+
const eventName = readUpstreamEventName(event);
|
|
218
|
+
const toolName = readUpstreamToolName(event);
|
|
219
|
+
if (isToolStartEvent(event) && toolName) {
|
|
220
|
+
const toolCallId = toolCalls.start(toolName);
|
|
221
|
+
await writeSseEvent(response, {
|
|
222
|
+
type: "TOOL_CALL_START",
|
|
223
|
+
timestamp: createTimestamp(),
|
|
224
|
+
toolCallId,
|
|
225
|
+
toolName,
|
|
226
|
+
});
|
|
227
|
+
const args = readToolArgs(event);
|
|
228
|
+
if (args !== undefined) {
|
|
229
|
+
await writeSseEvent(response, {
|
|
230
|
+
type: "TOOL_CALL_ARGS",
|
|
231
|
+
timestamp: createTimestamp(),
|
|
232
|
+
toolCallId,
|
|
233
|
+
toolName,
|
|
234
|
+
args,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const projections = upstreamReducer.consume(event);
|
|
239
|
+
for (const projection of projections) {
|
|
240
|
+
if (projection.type === "thinking") {
|
|
241
|
+
if (!projection.text) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
await ensureThinkingTextStart();
|
|
245
|
+
await writeSseEvent(response, {
|
|
246
|
+
type: "THINKING_TEXT_MESSAGE_CONTENT",
|
|
247
|
+
timestamp: createTimestamp(),
|
|
248
|
+
messageId: thinkingMessageId,
|
|
249
|
+
delta: projection.text,
|
|
250
|
+
});
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (projection.type === "step") {
|
|
254
|
+
if (projection.status === "started") {
|
|
255
|
+
await writeSseEvent(response, {
|
|
256
|
+
type: "STEP_STARTED",
|
|
257
|
+
timestamp: createTimestamp(),
|
|
258
|
+
stepId: projection.key,
|
|
259
|
+
title: projection.step,
|
|
260
|
+
category: projection.category,
|
|
261
|
+
});
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
await writeSseEvent(response, {
|
|
265
|
+
type: "STEP_FINISHED",
|
|
266
|
+
timestamp: createTimestamp(),
|
|
267
|
+
stepId: projection.key,
|
|
268
|
+
title: projection.step,
|
|
269
|
+
category: projection.category,
|
|
270
|
+
status: projection.status,
|
|
271
|
+
});
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const toolCallId = toolCalls.peek(projection.toolName) ?? toolCalls.start(projection.toolName);
|
|
275
|
+
await writeSseEvent(response, {
|
|
276
|
+
type: "TOOL_CALL_RESULT",
|
|
277
|
+
timestamp: createTimestamp(),
|
|
278
|
+
toolCallId,
|
|
279
|
+
toolName: projection.toolName,
|
|
280
|
+
result: projection.output,
|
|
281
|
+
...(projection.isError !== undefined ? { isError: projection.isError } : {}),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
if (isToolTerminalEvent(event) && toolName) {
|
|
285
|
+
const toolCallId = toolCalls.finish(toolName) ?? `tool-${createPersistentId()}`;
|
|
286
|
+
await writeSseEvent(response, {
|
|
287
|
+
type: "TOOL_CALL_END",
|
|
288
|
+
timestamp: createTimestamp(),
|
|
289
|
+
toolCallId,
|
|
290
|
+
toolName,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
if (eventName === "on_chat_model_end" && thinkingMessageStarted) {
|
|
294
|
+
await writeSseEvent(response, {
|
|
295
|
+
type: "THINKING_TEXT_MESSAGE_END",
|
|
296
|
+
timestamp: createTimestamp(),
|
|
297
|
+
messageId: thinkingMessageId,
|
|
298
|
+
});
|
|
299
|
+
thinkingMessageStarted = false;
|
|
300
|
+
}
|
|
301
|
+
},
|
|
123
302
|
},
|
|
124
303
|
});
|
|
125
304
|
runId = runId ?? result.runId;
|
|
@@ -133,13 +312,7 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
133
312
|
delta: result.output,
|
|
134
313
|
});
|
|
135
314
|
}
|
|
136
|
-
|
|
137
|
-
await writeSseEvent(response, {
|
|
138
|
-
type: "TEXT_MESSAGE_END",
|
|
139
|
-
timestamp: createTimestamp(),
|
|
140
|
-
messageId: messageId,
|
|
141
|
-
});
|
|
142
|
-
}
|
|
315
|
+
await closeOpenMessages();
|
|
143
316
|
await writeSseEvent(response, {
|
|
144
317
|
type: "RUN_FINISHED",
|
|
145
318
|
timestamp: createTimestamp(),
|
|
@@ -151,6 +324,7 @@ export async function serveAgUiOverHttp(runtime, options = {}) {
|
|
|
151
324
|
});
|
|
152
325
|
}
|
|
153
326
|
catch (error) {
|
|
327
|
+
await closeOpenMessages();
|
|
154
328
|
await writeSseEvent(response, {
|
|
155
329
|
type: "RUN_ERROR",
|
|
156
330
|
timestamp: createTimestamp(),
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import type { ApprovalRecord, ThreadRecord, ThreadSummary } from "../../../contracts/types.js";
|
|
1
|
+
import type { ApprovalRecord, SessionRecord, SessionSummary, ThreadRecord, ThreadSummary } from "../../../contracts/types.js";
|
|
2
2
|
import type { RuntimePersistence } from "../../../persistence/types.js";
|
|
3
|
+
export declare function buildSessionInspectionRecord(input: {
|
|
4
|
+
persistence: RuntimePersistence;
|
|
5
|
+
getSession: (sessionId: string) => Promise<SessionSummary | null>;
|
|
6
|
+
}, sessionId: string): Promise<SessionRecord | null>;
|
|
3
7
|
export declare function buildThreadInspectionRecord(input: {
|
|
4
8
|
persistence: RuntimePersistence;
|
|
5
9
|
getSession: (threadId: string) => Promise<ThreadSummary | null>;
|
|
@@ -19,3 +23,8 @@ export declare function deleteThreadRecord(input: {
|
|
|
19
23
|
deleteThread: (threadId: string) => Promise<boolean>;
|
|
20
24
|
deleteThreadCheckpoints: (threadId: string) => Promise<void>;
|
|
21
25
|
}, threadId: string): Promise<boolean>;
|
|
26
|
+
export declare function deleteSessionRecord(input: {
|
|
27
|
+
getSession: (sessionId: string) => Promise<SessionRecord | null>;
|
|
28
|
+
deleteSession: (sessionId: string) => Promise<boolean>;
|
|
29
|
+
deleteSessionCheckpoints: (sessionId: string) => Promise<void>;
|
|
30
|
+
}, sessionId: string): Promise<boolean>;
|
|
@@ -4,29 +4,46 @@ function selectLatestPendingApproval(approvals) {
|
|
|
4
4
|
.filter((approval) => approval.status === "pending")
|
|
5
5
|
.sort((left, right) => right.requestedAt.localeCompare(left.requestedAt))[0];
|
|
6
6
|
}
|
|
7
|
-
export async function
|
|
8
|
-
const [
|
|
9
|
-
input.getSession(
|
|
10
|
-
input.persistence.getThreadMeta(
|
|
11
|
-
input.persistence.listThreadMessages(
|
|
12
|
-
input.persistence.listThreadRuns(
|
|
7
|
+
export async function buildSessionInspectionRecord(input, sessionId) {
|
|
8
|
+
const [sessionSummary, meta, messages, requests] = await Promise.all([
|
|
9
|
+
input.getSession(sessionId),
|
|
10
|
+
input.persistence.getThreadMeta(sessionId),
|
|
11
|
+
input.persistence.listThreadMessages(sessionId, 200),
|
|
12
|
+
input.persistence.listThreadRuns(sessionId),
|
|
13
13
|
]);
|
|
14
|
-
if (!
|
|
14
|
+
if (!sessionSummary || !meta) {
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
|
-
const
|
|
18
|
-
const latestApprovals = await input.persistence.getRunApprovals(
|
|
17
|
+
const latestRequestId = sessionSummary.latestRequestId;
|
|
18
|
+
const latestApprovals = await input.persistence.getRunApprovals(sessionId, latestRequestId);
|
|
19
19
|
const pendingApproval = selectLatestPendingApproval(latestApprovals);
|
|
20
20
|
return {
|
|
21
|
-
|
|
21
|
+
sessionId,
|
|
22
22
|
entryAgentId: meta.entryAgentId,
|
|
23
|
-
currentAgentId:
|
|
24
|
-
currentState:
|
|
25
|
-
|
|
23
|
+
currentAgentId: sessionSummary.currentAgentId,
|
|
24
|
+
currentState: sessionSummary.status,
|
|
25
|
+
latestRequestId,
|
|
26
26
|
createdAt: meta.createdAt,
|
|
27
|
-
updatedAt:
|
|
27
|
+
updatedAt: sessionSummary.updatedAt,
|
|
28
28
|
messages,
|
|
29
|
-
|
|
29
|
+
requests: requests.map((request) => ({
|
|
30
|
+
requestId: request.runId,
|
|
31
|
+
sessionId: request.threadId,
|
|
32
|
+
agentId: request.agentId,
|
|
33
|
+
executionMode: request.executionMode,
|
|
34
|
+
adapterKind: request.adapterKind,
|
|
35
|
+
createdAt: request.createdAt,
|
|
36
|
+
updatedAt: request.updatedAt,
|
|
37
|
+
state: request.state,
|
|
38
|
+
checkpointRef: request.checkpointRef,
|
|
39
|
+
resumable: request.resumable,
|
|
40
|
+
startedAt: request.startedAt,
|
|
41
|
+
endedAt: request.endedAt,
|
|
42
|
+
lastActivityAt: request.lastActivityAt,
|
|
43
|
+
currentAgentId: request.currentAgentId,
|
|
44
|
+
delegationChain: request.delegationChain,
|
|
45
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
46
|
+
})),
|
|
30
47
|
pendingDecision: pendingApproval
|
|
31
48
|
? {
|
|
32
49
|
approvalId: pendingApproval.approvalId,
|
|
@@ -38,6 +55,56 @@ export async function buildThreadInspectionRecord(input, threadId) {
|
|
|
38
55
|
: undefined,
|
|
39
56
|
};
|
|
40
57
|
}
|
|
58
|
+
export async function buildThreadInspectionRecord(input, threadId) {
|
|
59
|
+
const session = await buildSessionInspectionRecord({
|
|
60
|
+
persistence: input.persistence,
|
|
61
|
+
getSession: async (sessionId) => {
|
|
62
|
+
const summary = await input.getSession(sessionId);
|
|
63
|
+
return summary
|
|
64
|
+
? {
|
|
65
|
+
agentId: summary.agentId,
|
|
66
|
+
sessionId: summary.threadId,
|
|
67
|
+
latestRequestId: summary.latestRunId,
|
|
68
|
+
createdAt: summary.createdAt,
|
|
69
|
+
updatedAt: summary.updatedAt,
|
|
70
|
+
status: summary.status,
|
|
71
|
+
currentAgentId: summary.currentAgentId,
|
|
72
|
+
}
|
|
73
|
+
: null;
|
|
74
|
+
},
|
|
75
|
+
}, threadId);
|
|
76
|
+
return session
|
|
77
|
+
? {
|
|
78
|
+
threadId: session.sessionId,
|
|
79
|
+
entryAgentId: session.entryAgentId,
|
|
80
|
+
currentAgentId: session.currentAgentId,
|
|
81
|
+
currentState: session.currentState,
|
|
82
|
+
latestRunId: session.latestRequestId,
|
|
83
|
+
createdAt: session.createdAt,
|
|
84
|
+
updatedAt: session.updatedAt,
|
|
85
|
+
messages: session.messages,
|
|
86
|
+
runs: session.requests.map((request) => ({
|
|
87
|
+
runId: request.requestId,
|
|
88
|
+
threadId: request.sessionId,
|
|
89
|
+
agentId: request.agentId,
|
|
90
|
+
executionMode: request.executionMode,
|
|
91
|
+
adapterKind: request.adapterKind,
|
|
92
|
+
createdAt: request.createdAt,
|
|
93
|
+
updatedAt: request.updatedAt,
|
|
94
|
+
state: request.state,
|
|
95
|
+
checkpointRef: request.checkpointRef,
|
|
96
|
+
resumable: request.resumable,
|
|
97
|
+
startedAt: request.startedAt,
|
|
98
|
+
endedAt: request.endedAt,
|
|
99
|
+
lastActivityAt: request.lastActivityAt,
|
|
100
|
+
currentAgentId: request.currentAgentId,
|
|
101
|
+
delegationChain: request.delegationChain,
|
|
102
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
103
|
+
})),
|
|
104
|
+
pendingDecision: session.pendingDecision,
|
|
105
|
+
}
|
|
106
|
+
: null;
|
|
107
|
+
}
|
|
41
108
|
export async function listPublicApprovals(input, filter) {
|
|
42
109
|
const approvals = await input.persistence.listApprovals(filter);
|
|
43
110
|
return approvals.map((approval) => toInspectableApprovalRecord(approval));
|
|
@@ -61,3 +128,18 @@ export async function deleteThreadRecord(input, threadId) {
|
|
|
61
128
|
}
|
|
62
129
|
return deleted;
|
|
63
130
|
}
|
|
131
|
+
export async function deleteSessionRecord(input, sessionId) {
|
|
132
|
+
const session = await input.getSession(sessionId);
|
|
133
|
+
if (!session) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
const activeRequest = session.requests.find((request) => !isTerminalRunState(request.state));
|
|
137
|
+
if (activeRequest) {
|
|
138
|
+
throw new Error(`Cannot delete session ${sessionId} while request ${activeRequest.requestId} is ${activeRequest.state}`);
|
|
139
|
+
}
|
|
140
|
+
const deleted = await input.deleteSession(sessionId);
|
|
141
|
+
if (deleted) {
|
|
142
|
+
await input.deleteSessionCheckpoints(sessionId);
|
|
143
|
+
}
|
|
144
|
+
return deleted;
|
|
145
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
|
|
1
|
+
import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, SessionSummary, ThreadSummary, ThreadRecord, SessionRecord, RequestRecord, RequestSummary, WorkspaceBundle } from "../contracts/types.js";
|
|
2
2
|
import { type RuntimeMcpServerOptions, type ToolMcpServerOptions } from "../mcp.js";
|
|
3
3
|
import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
|
|
@@ -60,9 +60,17 @@ export declare class AgentHarnessRuntime {
|
|
|
60
60
|
initialize(): Promise<void>;
|
|
61
61
|
subscribe(listener: (event: HarnessEvent) => void): () => void;
|
|
62
62
|
getHealth(): Promise<RuntimeHealthSnapshot>;
|
|
63
|
+
listSessions(filter?: {
|
|
64
|
+
agentId?: string;
|
|
65
|
+
}): Promise<SessionSummary[]>;
|
|
63
66
|
listThreads(filter?: {
|
|
64
67
|
agentId?: string;
|
|
65
68
|
}): Promise<ThreadSummary[]>;
|
|
69
|
+
listRequests(filter?: {
|
|
70
|
+
agentId?: string;
|
|
71
|
+
sessionId?: string;
|
|
72
|
+
state?: RequestSummary["state"];
|
|
73
|
+
}): Promise<RequestSummary[]>;
|
|
66
74
|
listRuns(filter?: {
|
|
67
75
|
agentId?: string;
|
|
68
76
|
threadId?: string;
|
|
@@ -73,8 +81,11 @@ export declare class AgentHarnessRuntime {
|
|
|
73
81
|
listMemories(input?: ListMemoriesInput): Promise<ListMemoriesResult>;
|
|
74
82
|
updateMemory(input: UpdateMemoryInput): Promise<MemoryRecord>;
|
|
75
83
|
removeMemory(input: RemoveMemoryInput): Promise<MemoryRecord>;
|
|
84
|
+
getRequest(requestId: string): Promise<RequestRecord | null>;
|
|
76
85
|
getRun(runId: string): Promise<RunRecord | null>;
|
|
86
|
+
private getSessionSummary;
|
|
77
87
|
private getSession;
|
|
88
|
+
getSessionRecord(sessionId: string): Promise<SessionRecord | null>;
|
|
78
89
|
getThread(threadId: string): Promise<ThreadRecord | null>;
|
|
79
90
|
listApprovals(filter?: {
|
|
80
91
|
status?: ApprovalRecord["status"];
|
|
@@ -84,7 +95,9 @@ export declare class AgentHarnessRuntime {
|
|
|
84
95
|
getApproval(approvalId: string): Promise<ApprovalRecord | null>;
|
|
85
96
|
listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
|
|
86
97
|
readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
|
|
98
|
+
listRequestEvents(sessionId: string, requestId: string): Promise<HarnessEvent[]>;
|
|
87
99
|
listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
|
|
100
|
+
exportRequestPackage(input: RuntimeRunPackageInput): Promise<RuntimeRunPackage>;
|
|
88
101
|
exportRunPackage(input: RuntimeRunPackageInput): Promise<RuntimeRunPackage>;
|
|
89
102
|
exportSessionPackage(input: RuntimeSessionPackageInput): Promise<RuntimeSessionPackage>;
|
|
90
103
|
exportEvaluationBundle(input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
|
|
@@ -96,7 +109,9 @@ export declare class AgentHarnessRuntime {
|
|
|
96
109
|
agents: InventoryAgentRecord[];
|
|
97
110
|
};
|
|
98
111
|
private deleteThreadCheckpoints;
|
|
112
|
+
deleteSession(sessionId: string): Promise<boolean>;
|
|
99
113
|
deleteThread(threadId: string): Promise<boolean>;
|
|
114
|
+
deleteThreadLegacy(threadId: string): Promise<boolean>;
|
|
100
115
|
createToolMcpServer(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
|
101
116
|
serveToolsOverStdio(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
|
102
117
|
createRuntimeMcpServer(options?: RuntimeMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
package/dist/runtime/harness.js
CHANGED
|
@@ -38,7 +38,7 @@ import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.
|
|
|
38
38
|
import { initializeHarnessRuntime, reclaimExpiredClaimedRuns as reclaimHarnessExpiredClaimedRuns, recoverStartupRuns as recoverHarnessStartupRuns, isStaleRunningRun as isHarnessStaleRunningRun, } from "./harness/run/startup-runtime.js";
|
|
39
39
|
import { streamHarnessRun } from "./harness/run/stream-run.js";
|
|
40
40
|
import { defaultRequestedAgentId, prepareRunStart } from "./harness/run/start-run.js";
|
|
41
|
-
import {
|
|
41
|
+
import { buildSessionInspectionRecord, deleteSessionRecord, deleteThreadRecord, getPublicApproval, listPublicApprovals, } from "./harness/run/thread-records.js";
|
|
42
42
|
export class AgentHarnessRuntime {
|
|
43
43
|
workspace;
|
|
44
44
|
runtimeAdapterOptions;
|
|
@@ -286,11 +286,79 @@ export class AgentHarnessRuntime {
|
|
|
286
286
|
}
|
|
287
287
|
return createDefaultHealthSnapshot(this.activeRunSlots, this.pendingRunSlots.length);
|
|
288
288
|
}
|
|
289
|
+
async listSessions(filter) {
|
|
290
|
+
const sessions = await this.persistence.listSessions(filter);
|
|
291
|
+
return sessions.map((session) => ({
|
|
292
|
+
agentId: session.agentId,
|
|
293
|
+
sessionId: session.threadId,
|
|
294
|
+
latestRequestId: session.latestRunId,
|
|
295
|
+
createdAt: session.createdAt,
|
|
296
|
+
updatedAt: session.updatedAt,
|
|
297
|
+
status: session.status,
|
|
298
|
+
currentAgentId: session.currentAgentId,
|
|
299
|
+
}));
|
|
300
|
+
}
|
|
289
301
|
async listThreads(filter) {
|
|
290
|
-
|
|
302
|
+
const sessions = await this.listSessions(filter);
|
|
303
|
+
return sessions.map((session) => ({
|
|
304
|
+
agentId: session.agentId,
|
|
305
|
+
threadId: session.sessionId,
|
|
306
|
+
latestRunId: session.latestRequestId,
|
|
307
|
+
createdAt: session.createdAt,
|
|
308
|
+
updatedAt: session.updatedAt,
|
|
309
|
+
status: session.status,
|
|
310
|
+
currentAgentId: session.currentAgentId,
|
|
311
|
+
}));
|
|
312
|
+
}
|
|
313
|
+
async listRequests(filter) {
|
|
314
|
+
const requests = await this.persistence.listRuns({
|
|
315
|
+
agentId: filter?.agentId,
|
|
316
|
+
threadId: filter?.sessionId,
|
|
317
|
+
state: filter?.state,
|
|
318
|
+
});
|
|
319
|
+
return requests.map((request) => ({
|
|
320
|
+
requestId: request.runId,
|
|
321
|
+
sessionId: request.threadId,
|
|
322
|
+
agentId: request.agentId,
|
|
323
|
+
executionMode: request.executionMode,
|
|
324
|
+
adapterKind: request.adapterKind,
|
|
325
|
+
createdAt: request.createdAt,
|
|
326
|
+
updatedAt: request.updatedAt,
|
|
327
|
+
state: request.state,
|
|
328
|
+
checkpointRef: request.checkpointRef,
|
|
329
|
+
resumable: request.resumable,
|
|
330
|
+
startedAt: request.startedAt,
|
|
331
|
+
endedAt: request.endedAt,
|
|
332
|
+
lastActivityAt: request.lastActivityAt,
|
|
333
|
+
currentAgentId: request.currentAgentId,
|
|
334
|
+
delegationChain: request.delegationChain,
|
|
335
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
336
|
+
}));
|
|
291
337
|
}
|
|
292
338
|
async listRuns(filter) {
|
|
293
|
-
|
|
339
|
+
const requests = await this.listRequests({
|
|
340
|
+
agentId: filter?.agentId,
|
|
341
|
+
sessionId: filter?.threadId,
|
|
342
|
+
state: filter?.state,
|
|
343
|
+
});
|
|
344
|
+
return requests.map((request) => ({
|
|
345
|
+
runId: request.requestId,
|
|
346
|
+
threadId: request.sessionId,
|
|
347
|
+
agentId: request.agentId,
|
|
348
|
+
executionMode: request.executionMode,
|
|
349
|
+
adapterKind: request.adapterKind,
|
|
350
|
+
createdAt: request.createdAt,
|
|
351
|
+
updatedAt: request.updatedAt,
|
|
352
|
+
state: request.state,
|
|
353
|
+
checkpointRef: request.checkpointRef,
|
|
354
|
+
resumable: request.resumable,
|
|
355
|
+
startedAt: request.startedAt,
|
|
356
|
+
endedAt: request.endedAt,
|
|
357
|
+
lastActivityAt: request.lastActivityAt,
|
|
358
|
+
currentAgentId: request.currentAgentId,
|
|
359
|
+
delegationChain: request.delegationChain,
|
|
360
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
361
|
+
}));
|
|
294
362
|
}
|
|
295
363
|
async memorize(input) {
|
|
296
364
|
const binding = this.defaultRuntimeEntryBinding;
|
|
@@ -309,12 +377,14 @@ export class AgentHarnessRuntime {
|
|
|
309
377
|
if (candidates.some((record) => typeof record.content !== "string" || record.content.trim().length === 0)) {
|
|
310
378
|
throw new Error("memorize requires every record to include non-empty content.");
|
|
311
379
|
}
|
|
312
|
-
|
|
313
|
-
|
|
380
|
+
const sessionId = input.sessionId ?? input.threadId;
|
|
381
|
+
const requestId = input.requestId ?? input.runId;
|
|
382
|
+
if (candidates.some((record) => (record.scope ?? "thread") === "thread") && !sessionId) {
|
|
383
|
+
throw new Error("memorize requires sessionId (or legacy threadId) when storing thread-scoped memory.");
|
|
314
384
|
}
|
|
315
385
|
const recordedAt = input.recordedAt ?? new Date().toISOString();
|
|
316
|
-
const runId =
|
|
317
|
-
const threadId =
|
|
386
|
+
const runId = requestId ?? createPersistentId(new Date(recordedAt));
|
|
387
|
+
const threadId = sessionId ?? `memory-api-${runId}`;
|
|
318
388
|
return this.persistStructuredMemoryCandidates(binding, {
|
|
319
389
|
candidates: candidates.map((record) => ({ ...record, content: record.content.trim() })),
|
|
320
390
|
threadId,
|
|
@@ -334,6 +404,7 @@ export class AgentHarnessRuntime {
|
|
|
334
404
|
if (typeof input.query !== "string" || input.query.trim().length === 0) {
|
|
335
405
|
throw new Error("recall requires a non-empty query.");
|
|
336
406
|
}
|
|
407
|
+
const sessionId = input.sessionId ?? input.threadId;
|
|
337
408
|
const workspaceId = this.getWorkspaceId(binding);
|
|
338
409
|
const agentId = input.agentId ?? binding.agent.id;
|
|
339
410
|
const userId = input.userId ?? "default";
|
|
@@ -350,7 +421,7 @@ export class AgentHarnessRuntime {
|
|
|
350
421
|
topK,
|
|
351
422
|
includeStale: input.includeStale === true,
|
|
352
423
|
filters: {
|
|
353
|
-
threadId:
|
|
424
|
+
threadId: sessionId,
|
|
354
425
|
agentId,
|
|
355
426
|
workspaceId: input.workspaceId ?? workspaceId,
|
|
356
427
|
userId,
|
|
@@ -366,6 +437,7 @@ export class AgentHarnessRuntime {
|
|
|
366
437
|
if (!binding) {
|
|
367
438
|
throw new Error("listMemories requires a runtime entry binding.");
|
|
368
439
|
}
|
|
440
|
+
const sessionId = input.sessionId ?? input.threadId;
|
|
369
441
|
const workspaceId = this.getWorkspaceId(binding);
|
|
370
442
|
const scopes = Array.isArray(input.scopes) && input.scopes.length > 0
|
|
371
443
|
? Array.from(new Set(input.scopes))
|
|
@@ -379,7 +451,7 @@ export class AgentHarnessRuntime {
|
|
|
379
451
|
.filter((record) => statuses.has(record.status))
|
|
380
452
|
.filter((record) => !kinds || kinds.has(record.kind))
|
|
381
453
|
.filter((record) => this.matchesMemoryFilters(record, {
|
|
382
|
-
threadId:
|
|
454
|
+
threadId: sessionId,
|
|
383
455
|
agentId: input.agentId,
|
|
384
456
|
workspaceId: input.workspaceId ?? workspaceId,
|
|
385
457
|
userId: input.userId,
|
|
@@ -453,17 +525,119 @@ export class AgentHarnessRuntime {
|
|
|
453
525
|
await this.refreshStructuredMemoryScope(binding, existing);
|
|
454
526
|
return existing;
|
|
455
527
|
}
|
|
528
|
+
async getRequest(requestId) {
|
|
529
|
+
const request = await this.persistence.getRun(requestId);
|
|
530
|
+
return request
|
|
531
|
+
? {
|
|
532
|
+
requestId: request.runId,
|
|
533
|
+
sessionId: request.threadId,
|
|
534
|
+
agentId: request.agentId,
|
|
535
|
+
executionMode: request.executionMode,
|
|
536
|
+
adapterKind: request.adapterKind,
|
|
537
|
+
createdAt: request.createdAt,
|
|
538
|
+
updatedAt: request.updatedAt,
|
|
539
|
+
state: request.state,
|
|
540
|
+
checkpointRef: request.checkpointRef,
|
|
541
|
+
resumable: request.resumable,
|
|
542
|
+
startedAt: request.startedAt,
|
|
543
|
+
endedAt: request.endedAt,
|
|
544
|
+
lastActivityAt: request.lastActivityAt,
|
|
545
|
+
currentAgentId: request.currentAgentId,
|
|
546
|
+
delegationChain: request.delegationChain,
|
|
547
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
548
|
+
}
|
|
549
|
+
: null;
|
|
550
|
+
}
|
|
456
551
|
async getRun(runId) {
|
|
457
|
-
|
|
552
|
+
const request = await this.getRequest(runId);
|
|
553
|
+
return request
|
|
554
|
+
? {
|
|
555
|
+
runId: request.requestId,
|
|
556
|
+
threadId: request.sessionId,
|
|
557
|
+
agentId: request.agentId,
|
|
558
|
+
executionMode: request.executionMode,
|
|
559
|
+
adapterKind: request.adapterKind,
|
|
560
|
+
createdAt: request.createdAt,
|
|
561
|
+
updatedAt: request.updatedAt,
|
|
562
|
+
state: request.state,
|
|
563
|
+
checkpointRef: request.checkpointRef,
|
|
564
|
+
resumable: request.resumable,
|
|
565
|
+
startedAt: request.startedAt,
|
|
566
|
+
endedAt: request.endedAt,
|
|
567
|
+
lastActivityAt: request.lastActivityAt,
|
|
568
|
+
currentAgentId: request.currentAgentId,
|
|
569
|
+
delegationChain: request.delegationChain,
|
|
570
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
571
|
+
}
|
|
572
|
+
: null;
|
|
573
|
+
}
|
|
574
|
+
async getSessionSummary(sessionId) {
|
|
575
|
+
const session = await this.persistence.getSession(sessionId);
|
|
576
|
+
return session
|
|
577
|
+
? {
|
|
578
|
+
agentId: session.agentId,
|
|
579
|
+
sessionId: session.threadId,
|
|
580
|
+
latestRequestId: session.latestRunId,
|
|
581
|
+
createdAt: session.createdAt,
|
|
582
|
+
updatedAt: session.updatedAt,
|
|
583
|
+
status: session.status,
|
|
584
|
+
currentAgentId: session.currentAgentId,
|
|
585
|
+
}
|
|
586
|
+
: null;
|
|
458
587
|
}
|
|
459
588
|
async getSession(threadId) {
|
|
460
|
-
|
|
589
|
+
const session = await this.getSessionSummary(threadId);
|
|
590
|
+
return session
|
|
591
|
+
? {
|
|
592
|
+
agentId: session.agentId,
|
|
593
|
+
threadId: session.sessionId,
|
|
594
|
+
latestRunId: session.latestRequestId,
|
|
595
|
+
createdAt: session.createdAt,
|
|
596
|
+
updatedAt: session.updatedAt,
|
|
597
|
+
status: session.status,
|
|
598
|
+
currentAgentId: session.currentAgentId,
|
|
599
|
+
}
|
|
600
|
+
: null;
|
|
461
601
|
}
|
|
462
|
-
async
|
|
463
|
-
return
|
|
602
|
+
async getSessionRecord(sessionId) {
|
|
603
|
+
return buildSessionInspectionRecord({
|
|
464
604
|
persistence: this.persistence,
|
|
465
|
-
getSession: (
|
|
466
|
-
},
|
|
605
|
+
getSession: (currentSessionId) => this.getSessionSummary(currentSessionId),
|
|
606
|
+
}, sessionId);
|
|
607
|
+
}
|
|
608
|
+
async getThread(threadId) {
|
|
609
|
+
const session = await this.getSessionRecord(threadId);
|
|
610
|
+
return session
|
|
611
|
+
? {
|
|
612
|
+
threadId: session.sessionId,
|
|
613
|
+
entryAgentId: session.entryAgentId,
|
|
614
|
+
currentAgentId: session.currentAgentId,
|
|
615
|
+
currentState: session.currentState,
|
|
616
|
+
latestRunId: session.latestRequestId,
|
|
617
|
+
createdAt: session.createdAt,
|
|
618
|
+
updatedAt: session.updatedAt,
|
|
619
|
+
messages: session.messages,
|
|
620
|
+
runs: session.requests.map((request) => ({
|
|
621
|
+
runId: request.requestId,
|
|
622
|
+
threadId: request.sessionId,
|
|
623
|
+
agentId: request.agentId,
|
|
624
|
+
executionMode: request.executionMode,
|
|
625
|
+
adapterKind: request.adapterKind,
|
|
626
|
+
createdAt: request.createdAt,
|
|
627
|
+
updatedAt: request.updatedAt,
|
|
628
|
+
state: request.state,
|
|
629
|
+
checkpointRef: request.checkpointRef,
|
|
630
|
+
resumable: request.resumable,
|
|
631
|
+
startedAt: request.startedAt,
|
|
632
|
+
endedAt: request.endedAt,
|
|
633
|
+
lastActivityAt: request.lastActivityAt,
|
|
634
|
+
currentAgentId: request.currentAgentId,
|
|
635
|
+
delegationChain: request.delegationChain,
|
|
636
|
+
runtimeSnapshot: request.runtimeSnapshot,
|
|
637
|
+
})),
|
|
638
|
+
pendingDecision: session.pendingDecision,
|
|
639
|
+
}
|
|
640
|
+
: null;
|
|
467
641
|
}
|
|
468
642
|
async listApprovals(filter) {
|
|
469
643
|
return listPublicApprovals({
|
|
@@ -481,15 +655,18 @@ export class AgentHarnessRuntime {
|
|
|
481
655
|
async readArtifact(threadId, runId, artifactPath) {
|
|
482
656
|
return this.persistence.readArtifact(threadId, runId, artifactPath);
|
|
483
657
|
}
|
|
658
|
+
async listRequestEvents(sessionId, requestId) {
|
|
659
|
+
return this.persistence.listRunEvents(sessionId, requestId);
|
|
660
|
+
}
|
|
484
661
|
async listRunEvents(threadId, runId) {
|
|
485
|
-
return this.
|
|
662
|
+
return this.listRequestEvents(threadId, runId);
|
|
486
663
|
}
|
|
487
|
-
async
|
|
488
|
-
const
|
|
489
|
-
const
|
|
664
|
+
async exportRequestPackage(input) {
|
|
665
|
+
const session = await this.getSessionRecord(input.sessionId);
|
|
666
|
+
const request = await this.getRequest(input.requestId);
|
|
490
667
|
const approvals = await this.listApprovals({ threadId: input.sessionId, runId: input.requestId });
|
|
491
668
|
const transcript = await this.persistence.listThreadMessages(input.sessionId, 500);
|
|
492
|
-
const events = await this.
|
|
669
|
+
const events = await this.listRequestEvents(input.sessionId, input.requestId);
|
|
493
670
|
const artifactsListing = input.includeArtifacts === false
|
|
494
671
|
? { items: [] }
|
|
495
672
|
: await this.persistence.listArtifacts(input.sessionId, input.requestId);
|
|
@@ -500,8 +677,8 @@ export class AgentHarnessRuntime {
|
|
|
500
677
|
: {}),
|
|
501
678
|
})));
|
|
502
679
|
return {
|
|
503
|
-
session
|
|
504
|
-
request
|
|
680
|
+
session,
|
|
681
|
+
request,
|
|
505
682
|
approvals,
|
|
506
683
|
transcript,
|
|
507
684
|
events,
|
|
@@ -509,10 +686,13 @@ export class AgentHarnessRuntime {
|
|
|
509
686
|
...(input.includeRuntimeHealth === false ? {} : { runtimeHealth: await this.getHealth() }),
|
|
510
687
|
};
|
|
511
688
|
}
|
|
689
|
+
async exportRunPackage(input) {
|
|
690
|
+
return this.exportRequestPackage(input);
|
|
691
|
+
}
|
|
512
692
|
async exportSessionPackage(input) {
|
|
513
|
-
const
|
|
514
|
-
const
|
|
515
|
-
const runs = await Promise.all(
|
|
693
|
+
const session = await this.getSessionRecord(input.sessionId);
|
|
694
|
+
const requestIds = Array.from(new Set((session?.requests ?? []).map((item) => item.requestId)));
|
|
695
|
+
const runs = await Promise.all(requestIds.map((requestId) => this.exportRequestPackage({
|
|
516
696
|
sessionId: input.sessionId,
|
|
517
697
|
requestId,
|
|
518
698
|
includeArtifacts: input.includeArtifacts,
|
|
@@ -520,7 +700,7 @@ export class AgentHarnessRuntime {
|
|
|
520
700
|
includeRuntimeHealth: false,
|
|
521
701
|
})));
|
|
522
702
|
return {
|
|
523
|
-
session
|
|
703
|
+
session,
|
|
524
704
|
requests: runs.map((item) => item.request).filter((item) => Boolean(item)),
|
|
525
705
|
approvals: await this.listApprovals({ threadId: input.sessionId }),
|
|
526
706
|
transcript: await this.persistence.listThreadMessages(input.sessionId, 500),
|
|
@@ -638,7 +818,17 @@ export class AgentHarnessRuntime {
|
|
|
638
818
|
}
|
|
639
819
|
}
|
|
640
820
|
}
|
|
821
|
+
async deleteSession(sessionId) {
|
|
822
|
+
return deleteSessionRecord({
|
|
823
|
+
getSession: (currentSessionId) => this.getSessionRecord(currentSessionId),
|
|
824
|
+
deleteSession: (currentSessionId) => this.persistence.deleteThread(currentSessionId),
|
|
825
|
+
deleteSessionCheckpoints: (currentSessionId) => this.deleteThreadCheckpoints(currentSessionId),
|
|
826
|
+
}, sessionId);
|
|
827
|
+
}
|
|
641
828
|
async deleteThread(threadId) {
|
|
829
|
+
return this.deleteSession(threadId);
|
|
830
|
+
}
|
|
831
|
+
async deleteThreadLegacy(threadId) {
|
|
642
832
|
return deleteThreadRecord({
|
|
643
833
|
getThread: (currentThreadId) => this.getThread(currentThreadId),
|
|
644
834
|
deleteThread: (currentThreadId) => this.persistence.deleteThread(currentThreadId),
|