@botbotgo/agent-harness 0.0.107 → 0.0.109
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/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/execution-context.d.ts +34 -0
- package/dist/runtime/adapter/execution-context.js +52 -0
- package/dist/runtime/adapter/middleware-assembly.js +29 -14
- package/dist/runtime/adapter/runnable-config.d.ts +57 -0
- package/dist/runtime/adapter/runnable-config.js +64 -0
- package/dist/runtime/adapter/runtime-adapter-support.d.ts +0 -1
- package/dist/runtime/adapter/runtime-adapter-support.js +5 -8
- package/dist/runtime/agent-runtime-adapter.js +28 -34
- package/dist/runtime/harness/background-runtime.d.ts +13 -0
- package/dist/runtime/harness/background-runtime.js +8 -0
- package/dist/runtime/harness/bindings.d.ts +14 -0
- package/dist/runtime/harness/bindings.js +23 -0
- package/dist/runtime/harness/events/listener-runtime.d.ts +18 -0
- package/dist/runtime/harness/events/listener-runtime.js +9 -0
- package/dist/runtime/harness/events/runtime-event-operations.d.ts +17 -0
- package/dist/runtime/harness/events/runtime-event-operations.js +9 -0
- package/dist/runtime/harness/run/recovery.d.ts +1 -1
- package/dist/runtime/harness/run/resume-runtime.d.ts +55 -0
- package/dist/runtime/harness/run/resume-runtime.js +26 -0
- package/dist/runtime/harness/run/routing.d.ts +8 -0
- package/dist/runtime/harness/run/routing.js +21 -0
- package/dist/runtime/harness/run/run-operations.d.ts +47 -0
- package/dist/runtime/harness/run/run-operations.js +67 -0
- package/dist/runtime/harness/run/start-run.d.ts +82 -0
- package/dist/runtime/harness/run/start-run.js +88 -0
- package/dist/runtime/harness/run/startup-runtime.d.ts +2 -1
- package/dist/runtime/harness/run/startup-runtime.js +38 -3
- package/dist/runtime/harness/run/stream-runtime.d.ts +48 -0
- package/dist/runtime/harness/run/stream-runtime.js +14 -0
- package/dist/runtime/harness.d.ts +5 -6
- package/dist/runtime/harness.js +186 -299
- package/dist/runtime/support/compiled-binding.d.ts +14 -0
- package/dist/runtime/support/compiled-binding.js +14 -10
- package/dist/runtime/support/runtime-adapter-options.d.ts +17 -0
- package/dist/runtime/support/runtime-adapter-options.js +29 -0
- package/package.json +1 -1
- package/dist/runtime/adapter/deepagent-runnable-config.d.ts +0 -30
- package/dist/runtime/adapter/deepagent-runnable-config.js +0 -22
- package/dist/runtime/adapter/langchain-runnable-config.d.ts +0 -25
- package/dist/runtime/adapter/langchain-runnable-config.js +0 -19
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CompiledAgentBinding, InternalApprovalRecord, MessageContent, ResumeOptions, RunResult, ThreadSummary, TranscriptMessage, WorkspaceBundle } from "../../../contracts/types.js";
|
|
2
|
+
import type { RuntimePersistence } from "../../../persistence/types.js";
|
|
3
|
+
import type { AgentRuntimeAdapter } from "../../agent-runtime-adapter.js";
|
|
4
|
+
type Binding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
|
|
5
|
+
export declare function createResumeRunRuntime(input: {
|
|
6
|
+
persistence: RuntimePersistence;
|
|
7
|
+
workspace: WorkspaceBundle;
|
|
8
|
+
runtimeAdapter: AgentRuntimeAdapter;
|
|
9
|
+
getSession: (threadId: string) => Promise<ThreadSummary | null>;
|
|
10
|
+
getRunCancellation: (runId: string) => Promise<{
|
|
11
|
+
requested: boolean;
|
|
12
|
+
reason?: string;
|
|
13
|
+
}>;
|
|
14
|
+
finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
|
|
15
|
+
acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
|
|
16
|
+
resolvePersistedRunPriority: (threadId: string, runId: string) => Promise<number>;
|
|
17
|
+
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
|
|
18
|
+
loadRunInput: (threadId: string, runId: string) => Promise<MessageContent>;
|
|
19
|
+
recordLlmSuccess: (startedAt: number) => void;
|
|
20
|
+
recordLlmFailure: (startedAt: number) => void;
|
|
21
|
+
finalizeContinuedRun: (binding: Binding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
|
|
22
|
+
previousState: RunResult["state"] | null;
|
|
23
|
+
stateSequence: number;
|
|
24
|
+
approvalSequence?: number;
|
|
25
|
+
}) => Promise<RunResult>;
|
|
26
|
+
}): {
|
|
27
|
+
getApprovalById: (approvalId: string) => Promise<InternalApprovalRecord | null>;
|
|
28
|
+
getSession: (threadId: string) => Promise<ThreadSummary | null>;
|
|
29
|
+
resolveApprovalRecord: (resumeOptions: ResumeOptions, thread: ThreadSummary) => Promise<InternalApprovalRecord>;
|
|
30
|
+
getBinding: (agentId: string) => CompiledAgentBinding | undefined;
|
|
31
|
+
buildResumePayload: (binding: CompiledAgentBinding, approval: InternalApprovalRecord, resumeOptions: ResumeOptions) => unknown;
|
|
32
|
+
getRunCancellation: (runId: string) => Promise<{
|
|
33
|
+
requested: boolean;
|
|
34
|
+
reason?: string;
|
|
35
|
+
}>;
|
|
36
|
+
finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
|
|
37
|
+
setRunState: (threadId: string, runId: string, state: RunResult["state"], checkpointRef: string | null) => Promise<void>;
|
|
38
|
+
acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
|
|
39
|
+
resolvePersistedRunPriority: (threadId: string, runId: string) => Promise<number>;
|
|
40
|
+
saveRecoveryIntent: (threadId: string, runId: string, payload: Record<string, unknown>) => Promise<void>;
|
|
41
|
+
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
|
|
42
|
+
resolveApproval: (threadId: string, runId: string, approvalId: string, resolution: "approved" | "edited" | "rejected" | "expired") => Promise<InternalApprovalRecord>;
|
|
43
|
+
listThreadMessages: (threadId: string) => Promise<TranscriptMessage[]>;
|
|
44
|
+
loadRunInput: (threadId: string, runId: string) => Promise<MessageContent>;
|
|
45
|
+
invoke: (binding: CompiledAgentBinding, message: MessageContent, threadId: string, runId: string, resumePayload: unknown, priorHistory: TranscriptMessage[]) => Promise<RunResult>;
|
|
46
|
+
recordLlmSuccess: (startedAt: number) => void;
|
|
47
|
+
recordLlmFailure: (startedAt: number) => void;
|
|
48
|
+
clearRecoveryIntent: (threadId: string, runId: string) => Promise<void>;
|
|
49
|
+
finalizeContinuedRun: (binding: Binding, threadId: string, runId: string, message: MessageContent, actual: RunResult, options: {
|
|
50
|
+
previousState: RunResult["state"] | null;
|
|
51
|
+
stateSequence: number;
|
|
52
|
+
approvalSequence?: number;
|
|
53
|
+
}) => Promise<RunResult>;
|
|
54
|
+
};
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getWorkspaceBinding } from "../bindings.js";
|
|
2
|
+
import { buildResumePayload as buildHarnessResumePayload, resolveApprovalRecord as resolveHarnessApprovalRecord } from "./resume.js";
|
|
3
|
+
export function createResumeRunRuntime(input) {
|
|
4
|
+
return {
|
|
5
|
+
getApprovalById: (approvalId) => input.persistence.getApproval(approvalId),
|
|
6
|
+
getSession: (threadId) => input.getSession(threadId),
|
|
7
|
+
resolveApprovalRecord: (resumeOptions, thread) => resolveHarnessApprovalRecord(input.persistence, resumeOptions, thread),
|
|
8
|
+
getBinding: (agentId) => getWorkspaceBinding(input.workspace, agentId),
|
|
9
|
+
buildResumePayload: (binding, approval, resumeOptions) => buildHarnessResumePayload(binding, approval, resumeOptions),
|
|
10
|
+
getRunCancellation: (runId) => input.getRunCancellation(runId),
|
|
11
|
+
finalizeCancelledRun: (threadId, runId, previousState, reason) => input.finalizeCancelledRun(threadId, runId, previousState, reason),
|
|
12
|
+
setRunState: (threadId, runId, state, checkpointRef) => input.persistence.setRunState(threadId, runId, state, checkpointRef),
|
|
13
|
+
acquireRunSlot: (threadId, runId, activeState, priority) => input.acquireRunSlot(threadId, runId, activeState, priority),
|
|
14
|
+
resolvePersistedRunPriority: (threadId, runId) => input.resolvePersistedRunPriority(threadId, runId),
|
|
15
|
+
saveRecoveryIntent: (threadId, runId, payload) => input.persistence.saveRecoveryIntent(threadId, runId, payload),
|
|
16
|
+
emit: (threadId, runId, sequence, eventType, payload) => input.emit(threadId, runId, sequence, eventType, payload),
|
|
17
|
+
resolveApproval: (threadId, runId, approvalId, resolution) => input.persistence.resolveApproval(threadId, runId, approvalId, resolution),
|
|
18
|
+
listThreadMessages: (threadId) => input.persistence.listThreadMessages(threadId),
|
|
19
|
+
loadRunInput: (threadId, runId) => input.loadRunInput(threadId, runId),
|
|
20
|
+
invoke: (binding, message, threadId, runId, resumePayload, priorHistory) => input.runtimeAdapter.invoke(binding, message, threadId, runId, resumePayload, priorHistory),
|
|
21
|
+
recordLlmSuccess: (startedAt) => input.recordLlmSuccess(startedAt),
|
|
22
|
+
recordLlmFailure: (startedAt) => input.recordLlmFailure(startedAt),
|
|
23
|
+
clearRecoveryIntent: (threadId, runId) => input.persistence.clearRecoveryIntent(threadId, runId),
|
|
24
|
+
finalizeContinuedRun: (binding, threadId, runId, message, actual, options) => input.finalizeContinuedRun(binding, threadId, runId, message, actual, options),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type MessageContent, type ThreadSummary, type WorkspaceBundle } from "../../../contracts/types.js";
|
|
2
|
+
import type { RoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
|
|
2
3
|
export declare function getDefaultHostAgentId(workspace: WorkspaceBundle, preferredHostAgentId?: string): string;
|
|
3
4
|
export declare function resolveSelectedAgentId(options: {
|
|
4
5
|
workspace: WorkspaceBundle;
|
|
@@ -8,3 +9,10 @@ export declare function resolveSelectedAgentId(options: {
|
|
|
8
9
|
preferredHostAgentId?: string;
|
|
9
10
|
getThreadSummary: (threadId: string) => Promise<ThreadSummary | null>;
|
|
10
11
|
}): Promise<string>;
|
|
12
|
+
export declare function routeAgentId(options: {
|
|
13
|
+
workspace: WorkspaceBundle;
|
|
14
|
+
input: MessageContent;
|
|
15
|
+
routingRules: RoutingRule[];
|
|
16
|
+
routingDefaultAgentId?: string;
|
|
17
|
+
threadId?: string;
|
|
18
|
+
}): string;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { AUTO_AGENT_ID } from "../../../contracts/types.js";
|
|
2
|
+
import { extractMessageText } from "../../../utils/message-content.js";
|
|
3
|
+
import { matchRoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
|
|
4
|
+
import { getWorkspaceBinding } from "../bindings.js";
|
|
2
5
|
import { inferRoutingBindings } from "../../support/harness-support.js";
|
|
3
6
|
export function getDefaultHostAgentId(workspace, preferredHostAgentId) {
|
|
4
7
|
const preferredBinding = preferredHostAgentId ? workspace.bindings.get(preferredHostAgentId) : undefined;
|
|
@@ -21,3 +24,21 @@ export async function resolveSelectedAgentId(options) {
|
|
|
21
24
|
}
|
|
22
25
|
return requestedAgentId;
|
|
23
26
|
}
|
|
27
|
+
export function routeAgentId(options) {
|
|
28
|
+
const { workspace, input, routingRules, routingDefaultAgentId, threadId } = options;
|
|
29
|
+
const rawInput = extractMessageText(input);
|
|
30
|
+
const configuredRule = routingRules.find((rule) => matchRoutingRule(rawInput, rule, { threadId }));
|
|
31
|
+
if (configuredRule) {
|
|
32
|
+
const configuredBinding = getWorkspaceBinding(workspace, configuredRule.agentId);
|
|
33
|
+
if (configuredBinding) {
|
|
34
|
+
return configuredBinding.agent.id;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const defaultBinding = routingDefaultAgentId
|
|
38
|
+
? getWorkspaceBinding(workspace, routingDefaultAgentId)
|
|
39
|
+
: undefined;
|
|
40
|
+
if (defaultBinding) {
|
|
41
|
+
return defaultBinding.agent.id;
|
|
42
|
+
}
|
|
43
|
+
return getDefaultHostAgentId(workspace, routingDefaultAgentId);
|
|
44
|
+
}
|
|
@@ -45,6 +45,53 @@ type CancelOperationRuntime = {
|
|
|
45
45
|
error?: string;
|
|
46
46
|
}) => Promise<unknown>;
|
|
47
47
|
};
|
|
48
|
+
type ExecuteQueuedRunOperationRuntime = {
|
|
49
|
+
persistence: {
|
|
50
|
+
getRun: (runId: string) => Promise<{
|
|
51
|
+
state: RunResult["state"];
|
|
52
|
+
} | null>;
|
|
53
|
+
clearRunRequest: (threadId: string, runId: string) => Promise<void>;
|
|
54
|
+
};
|
|
55
|
+
getRunCancellation: (runId: string) => Promise<{
|
|
56
|
+
requested: boolean;
|
|
57
|
+
reason?: string;
|
|
58
|
+
}>;
|
|
59
|
+
finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
|
|
60
|
+
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
|
|
61
|
+
setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
|
|
62
|
+
previousState: string | null;
|
|
63
|
+
checkpointRef?: string | null;
|
|
64
|
+
error?: string;
|
|
65
|
+
}) => Promise<unknown>;
|
|
66
|
+
invokeWithHistory: (binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string, resumePayload?: unknown, priorHistory?: TranscriptMessage[], options?: {
|
|
67
|
+
context?: Record<string, unknown>;
|
|
68
|
+
state?: Record<string, unknown>;
|
|
69
|
+
files?: Record<string, unknown>;
|
|
70
|
+
}) => Promise<RunResult>;
|
|
71
|
+
finalizeContinuedRun: (binding: CompiledAgentBinding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
|
|
72
|
+
previousState: RunResult["state"] | null;
|
|
73
|
+
stateSequence: number;
|
|
74
|
+
approvalSequence?: number;
|
|
75
|
+
}) => Promise<RunResult>;
|
|
76
|
+
emitSyntheticFallback: (threadId: string, runId: string, agentId: string, error: unknown) => Promise<void>;
|
|
77
|
+
renderRuntimeFailure: (error: unknown) => string;
|
|
78
|
+
};
|
|
48
79
|
export declare function resumeRun(runtime: ResumeOperationRuntime, options: ResumeOptions): Promise<RunResult>;
|
|
49
80
|
export declare function cancelRunOperation(runtime: CancelOperationRuntime, options: CancelOptions): Promise<RunResult>;
|
|
81
|
+
export declare function executeQueuedRunOperation(runtime: ExecuteQueuedRunOperationRuntime, input: {
|
|
82
|
+
binding: CompiledAgentBinding;
|
|
83
|
+
message: MessageContent;
|
|
84
|
+
threadId: string;
|
|
85
|
+
runId: string;
|
|
86
|
+
agentId: string;
|
|
87
|
+
options?: {
|
|
88
|
+
context?: Record<string, unknown>;
|
|
89
|
+
state?: Record<string, unknown>;
|
|
90
|
+
files?: Record<string, unknown>;
|
|
91
|
+
priorHistory?: TranscriptMessage[];
|
|
92
|
+
previousState?: RunResult["state"];
|
|
93
|
+
stateSequence?: number;
|
|
94
|
+
approvalSequence?: number;
|
|
95
|
+
};
|
|
96
|
+
}): Promise<RunResult>;
|
|
50
97
|
export {};
|
|
@@ -111,3 +111,70 @@ export async function cancelRunOperation(runtime, options) {
|
|
|
111
111
|
output: options.reason ? `cancelling: ${options.reason}` : "cancelling",
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
|
+
export async function executeQueuedRunOperation(runtime, input) {
|
|
115
|
+
const { binding, message, threadId, runId, agentId } = input;
|
|
116
|
+
const options = input.options ?? {};
|
|
117
|
+
const previousState = options.previousState ?? "running";
|
|
118
|
+
const currentRun = await runtime.persistence.getRun(runId);
|
|
119
|
+
if (currentRun?.state === "cancelled") {
|
|
120
|
+
return {
|
|
121
|
+
threadId,
|
|
122
|
+
runId,
|
|
123
|
+
agentId,
|
|
124
|
+
state: "cancelled",
|
|
125
|
+
output: "cancelled",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const cancellation = await runtime.getRunCancellation(runId);
|
|
129
|
+
if (cancellation.requested) {
|
|
130
|
+
return runtime.finalizeCancelledRun(threadId, runId, previousState, cancellation.reason);
|
|
131
|
+
}
|
|
132
|
+
if (previousState === "queued") {
|
|
133
|
+
await runtime.emit(threadId, runId, 101, "run.dequeued", {
|
|
134
|
+
queuePosition: 0,
|
|
135
|
+
activeRunCount: 0,
|
|
136
|
+
maxConcurrentRuns: 0,
|
|
137
|
+
recoveredOnStartup: true,
|
|
138
|
+
});
|
|
139
|
+
await runtime.setRunStateAndEmit(threadId, runId, 102, "running", {
|
|
140
|
+
previousState: "queued",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const actual = await runtime.invokeWithHistory(binding, message, threadId, runId, undefined, options.priorHistory, {
|
|
145
|
+
context: options.context,
|
|
146
|
+
state: options.state,
|
|
147
|
+
files: options.files,
|
|
148
|
+
});
|
|
149
|
+
const cancelledAfterInvoke = await runtime.getRunCancellation(runId);
|
|
150
|
+
if (cancelledAfterInvoke.requested) {
|
|
151
|
+
return runtime.finalizeCancelledRun(threadId, runId, previousState === "queued" ? "running" : previousState, cancelledAfterInvoke.reason);
|
|
152
|
+
}
|
|
153
|
+
const finalized = await runtime.finalizeContinuedRun(binding, threadId, runId, message, actual, {
|
|
154
|
+
previousState: previousState === "queued" ? "running" : previousState,
|
|
155
|
+
stateSequence: options.stateSequence ?? 103,
|
|
156
|
+
approvalSequence: options.approvalSequence ?? 104,
|
|
157
|
+
});
|
|
158
|
+
return {
|
|
159
|
+
...finalized,
|
|
160
|
+
agentId,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
await runtime.emitSyntheticFallback(threadId, runId, agentId, error);
|
|
165
|
+
await runtime.setRunStateAndEmit(threadId, runId, 104, "failed", {
|
|
166
|
+
previousState: previousState === "queued" ? "running" : previousState,
|
|
167
|
+
error: error instanceof Error ? error.message : String(error),
|
|
168
|
+
});
|
|
169
|
+
return {
|
|
170
|
+
threadId,
|
|
171
|
+
runId,
|
|
172
|
+
agentId,
|
|
173
|
+
state: "failed",
|
|
174
|
+
output: runtime.renderRuntimeFailure(error),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
await runtime.persistence.clearRunRequest(threadId, runId);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { HarnessEvent, InvocationEnvelope, MessageContent, RunResult, RunStartOptions, WorkspaceBundle } from "../../../contracts/types.js";
|
|
2
|
+
import type { PersistedRunRequest } from "../../../persistence/types.js";
|
|
3
|
+
import type { PolicyEngine } from "../system/policy-engine.js";
|
|
4
|
+
type Binding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
|
|
5
|
+
type EnsureThreadStartedRuntime = {
|
|
6
|
+
persistence: {
|
|
7
|
+
bootstrapRun?: (input: {
|
|
8
|
+
threadId: string;
|
|
9
|
+
agentId: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
status: RunResult["state"];
|
|
12
|
+
createdAt: string;
|
|
13
|
+
executionMode: string;
|
|
14
|
+
adapterKind: string;
|
|
15
|
+
userMessage: {
|
|
16
|
+
role: "user";
|
|
17
|
+
content: MessageContent;
|
|
18
|
+
runId: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
};
|
|
21
|
+
runRequest: PersistedRunRequest;
|
|
22
|
+
createThread: boolean;
|
|
23
|
+
}) => Promise<void>;
|
|
24
|
+
createThread: (input: {
|
|
25
|
+
threadId: string;
|
|
26
|
+
agentId: string;
|
|
27
|
+
runId: string;
|
|
28
|
+
status: RunResult["state"];
|
|
29
|
+
createdAt: string;
|
|
30
|
+
}) => Promise<void>;
|
|
31
|
+
appendThreadMessage: (threadId: string, message: {
|
|
32
|
+
role: "user";
|
|
33
|
+
content: MessageContent;
|
|
34
|
+
runId: string;
|
|
35
|
+
createdAt: string;
|
|
36
|
+
}) => Promise<void>;
|
|
37
|
+
createRun: (input: {
|
|
38
|
+
threadId: string;
|
|
39
|
+
runId: string;
|
|
40
|
+
agentId: string;
|
|
41
|
+
executionMode: string;
|
|
42
|
+
adapterKind: string;
|
|
43
|
+
createdAt: string;
|
|
44
|
+
}) => Promise<void>;
|
|
45
|
+
saveRunRequest: (threadId: string, runId: string, runRequest: PersistedRunRequest) => Promise<void>;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
type PrepareRunStartRuntime = EnsureThreadStartedRuntime & {
|
|
49
|
+
workspace: WorkspaceBundle;
|
|
50
|
+
policyEngine: PolicyEngine;
|
|
51
|
+
resolveSelectedAgentId: (input: MessageContent, requestedAgentId?: string, threadId?: string) => Promise<string>;
|
|
52
|
+
emitRunCreated: (threadId: string, runId: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
|
|
53
|
+
acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
|
|
54
|
+
};
|
|
55
|
+
export declare function ensureThreadStarted(runtime: EnsureThreadStartedRuntime, input: {
|
|
56
|
+
selectedAgentId: string;
|
|
57
|
+
binding: Binding;
|
|
58
|
+
message: MessageContent;
|
|
59
|
+
runRequest: PersistedRunRequest;
|
|
60
|
+
existingThreadId?: string;
|
|
61
|
+
}): Promise<{
|
|
62
|
+
threadId: string;
|
|
63
|
+
runId: string;
|
|
64
|
+
createdAt: string;
|
|
65
|
+
isNewThread: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
export declare function prepareRunStart(runtime: PrepareRunStartRuntime, input: {
|
|
68
|
+
options: Pick<RunStartOptions, "input" | "agentId" | "threadId" | "priority">;
|
|
69
|
+
invocation: InvocationEnvelope;
|
|
70
|
+
runCreatedPayload: (binding: Binding, selectedAgentId: string) => Record<string, unknown>;
|
|
71
|
+
}): Promise<{
|
|
72
|
+
binding: Binding;
|
|
73
|
+
selectedAgentId: string;
|
|
74
|
+
priority: number;
|
|
75
|
+
threadId: string;
|
|
76
|
+
runId: string;
|
|
77
|
+
isNewThread: boolean;
|
|
78
|
+
runCreatedEventPromise: Promise<HarnessEvent>;
|
|
79
|
+
releaseRunSlotPromise: Promise<() => Promise<void>>;
|
|
80
|
+
}>;
|
|
81
|
+
export declare function defaultRequestedAgentId(agentId?: string): string;
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { AUTO_AGENT_ID } from "../../../contracts/types.js";
|
|
2
|
+
import { createPersistentId } from "../../../utils/id.js";
|
|
3
|
+
import { normalizeMessageContent } from "../../../utils/message-content.js";
|
|
4
|
+
import { buildPersistedRunRequest, normalizeRunPriority } from "./helpers.js";
|
|
5
|
+
import { getRequiredWorkspaceBinding } from "../bindings.js";
|
|
6
|
+
import { getBindingAdapterKind } from "../../support/compiled-binding.js";
|
|
7
|
+
export async function ensureThreadStarted(runtime, input) {
|
|
8
|
+
const { selectedAgentId, binding, message, runRequest, existingThreadId } = input;
|
|
9
|
+
const threadId = existingThreadId ?? createPersistentId();
|
|
10
|
+
const runId = createPersistentId();
|
|
11
|
+
const createdAt = new Date().toISOString();
|
|
12
|
+
const isNewThread = !existingThreadId;
|
|
13
|
+
const userMessage = {
|
|
14
|
+
role: "user",
|
|
15
|
+
content: normalizeMessageContent(message),
|
|
16
|
+
runId,
|
|
17
|
+
createdAt,
|
|
18
|
+
};
|
|
19
|
+
if (typeof runtime.persistence.bootstrapRun === "function") {
|
|
20
|
+
await runtime.persistence.bootstrapRun({
|
|
21
|
+
threadId,
|
|
22
|
+
agentId: binding.agent.id,
|
|
23
|
+
runId,
|
|
24
|
+
status: "running",
|
|
25
|
+
createdAt,
|
|
26
|
+
executionMode: getBindingAdapterKind(binding),
|
|
27
|
+
adapterKind: getBindingAdapterKind(binding),
|
|
28
|
+
userMessage,
|
|
29
|
+
runRequest,
|
|
30
|
+
createThread: isNewThread,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (isNewThread) {
|
|
35
|
+
await runtime.persistence.createThread({
|
|
36
|
+
threadId,
|
|
37
|
+
agentId: selectedAgentId,
|
|
38
|
+
runId,
|
|
39
|
+
status: "running",
|
|
40
|
+
createdAt,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
await Promise.all([
|
|
44
|
+
runtime.persistence.appendThreadMessage(threadId, userMessage),
|
|
45
|
+
runtime.persistence.createRun({
|
|
46
|
+
threadId,
|
|
47
|
+
runId,
|
|
48
|
+
agentId: binding.agent.id,
|
|
49
|
+
executionMode: getBindingAdapterKind(binding),
|
|
50
|
+
adapterKind: getBindingAdapterKind(binding),
|
|
51
|
+
createdAt,
|
|
52
|
+
}),
|
|
53
|
+
runtime.persistence.saveRunRequest(threadId, runId, runRequest),
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
return { threadId, runId, createdAt, isNewThread };
|
|
57
|
+
}
|
|
58
|
+
export async function prepareRunStart(runtime, input) {
|
|
59
|
+
const { options, invocation, runCreatedPayload } = input;
|
|
60
|
+
const selectedAgentId = await runtime.resolveSelectedAgentId(options.input, options.agentId, options.threadId);
|
|
61
|
+
const binding = getRequiredWorkspaceBinding(runtime.workspace, selectedAgentId);
|
|
62
|
+
const policyDecision = runtime.policyEngine.evaluate(binding);
|
|
63
|
+
if (!policyDecision.allowed) {
|
|
64
|
+
throw new Error(`Policy evaluation blocked agent ${selectedAgentId}: ${policyDecision.reasons.join(", ")}`);
|
|
65
|
+
}
|
|
66
|
+
const priority = normalizeRunPriority(options.priority);
|
|
67
|
+
const runRequest = buildPersistedRunRequest(options.input, invocation, priority);
|
|
68
|
+
const { threadId, runId, isNewThread } = await ensureThreadStarted(runtime, {
|
|
69
|
+
selectedAgentId,
|
|
70
|
+
binding,
|
|
71
|
+
message: options.input,
|
|
72
|
+
runRequest,
|
|
73
|
+
existingThreadId: options.threadId,
|
|
74
|
+
});
|
|
75
|
+
return {
|
|
76
|
+
binding,
|
|
77
|
+
selectedAgentId,
|
|
78
|
+
priority,
|
|
79
|
+
threadId,
|
|
80
|
+
runId,
|
|
81
|
+
isNewThread,
|
|
82
|
+
runCreatedEventPromise: runtime.emitRunCreated(threadId, runId, runCreatedPayload(binding, selectedAgentId)),
|
|
83
|
+
releaseRunSlotPromise: runtime.acquireRunSlot(threadId, runId, "running", priority),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function defaultRequestedAgentId(agentId) {
|
|
87
|
+
return agentId ?? AUTO_AGENT_ID;
|
|
88
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { RunResult, ThreadSummary } from "../../../contracts/types.js";
|
|
2
2
|
import type { RuntimePersistence } from "../../../persistence/types.js";
|
|
3
3
|
import type { ConcurrencyConfig, RecoveryConfig } from "../../../workspace/support/workspace-ref-utils.js";
|
|
4
|
+
import { type StartupRecoveryContext } from "./recovery.js";
|
|
4
5
|
type Startable = {
|
|
5
6
|
start(): Promise<void>;
|
|
6
7
|
};
|
|
@@ -11,7 +12,7 @@ export declare function initializeHarnessRuntime(input: {
|
|
|
11
12
|
export declare function recoverStartupRuns(input: {
|
|
12
13
|
recoveryConfig: RecoveryConfig;
|
|
13
14
|
persistence: RuntimePersistence;
|
|
14
|
-
createStartupRecoveryContext: () =>
|
|
15
|
+
createStartupRecoveryContext: () => StartupRecoveryContext;
|
|
15
16
|
reclaimExpiredClaimedRuns: (nowIso?: string) => Promise<void>;
|
|
16
17
|
}): Promise<void>;
|
|
17
18
|
export declare function reclaimExpiredClaimedRuns(input: {
|
|
@@ -1,13 +1,48 @@
|
|
|
1
|
+
import { recoverQueuedStartupRun, recoverResumingStartupRun, recoverRunningStartupRun, } from "./recovery.js";
|
|
1
2
|
export async function initializeHarnessRuntime(input) {
|
|
2
3
|
await input.persistence.initialize();
|
|
3
4
|
await input.healthMonitor?.start();
|
|
4
5
|
}
|
|
5
6
|
export async function recoverStartupRuns(input) {
|
|
6
|
-
|
|
7
|
+
if (!input.recoveryConfig.enabled) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
await input.reclaimExpiredClaimedRuns();
|
|
11
|
+
const threads = await input.persistence.listSessions();
|
|
12
|
+
if (threads.length === 0) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const context = input.createStartupRecoveryContext();
|
|
16
|
+
for (const thread of threads) {
|
|
17
|
+
if (await recoverQueuedStartupRun(context, thread)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (await recoverRunningStartupRun(context, thread)) {
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
await recoverResumingStartupRun(context, thread);
|
|
24
|
+
}
|
|
7
25
|
}
|
|
8
26
|
export async function reclaimExpiredClaimedRuns(input, nowIso = new Date().toISOString()) {
|
|
9
|
-
|
|
10
|
-
|
|
27
|
+
const expiredRuns = await input.persistence.listExpiredClaimedRuns(nowIso);
|
|
28
|
+
if (expiredRuns.length === 0) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const activeRunCount = input.getActiveRunSlots();
|
|
32
|
+
const maxConcurrentRuns = input.concurrencyConfig.maxConcurrentRuns;
|
|
33
|
+
for (const [index, claimedRun] of expiredRuns.entries()) {
|
|
34
|
+
await input.persistence.releaseRunClaim(claimedRun.runId);
|
|
35
|
+
await input.setRunStateAndEmit(claimedRun.threadId, claimedRun.runId, 100, "queued", {
|
|
36
|
+
previousState: "claimed",
|
|
37
|
+
});
|
|
38
|
+
await input.emit(claimedRun.threadId, claimedRun.runId, 101, "run.queued", {
|
|
39
|
+
queuePosition: activeRunCount + index + 1,
|
|
40
|
+
activeRunCount,
|
|
41
|
+
...(maxConcurrentRuns !== undefined ? { maxConcurrentRuns } : {}),
|
|
42
|
+
priority: claimedRun.priority,
|
|
43
|
+
recoveryKind: "startup-claim-recovery",
|
|
44
|
+
});
|
|
45
|
+
}
|
|
11
46
|
}
|
|
12
47
|
export async function isStaleRunningRun(input, thread, nowMs = Date.now()) {
|
|
13
48
|
const control = await input.persistence.getRunControl(thread.latestRunId);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { CompiledAgentBinding, HarnessEvent, MessageContent, RunResult, TranscriptMessage } from "../../../contracts/types.js";
|
|
2
|
+
import type { RuntimePersistence } from "../../../persistence/types.js";
|
|
3
|
+
import type { AgentRuntimeAdapter } from "../../agent-runtime-adapter.js";
|
|
4
|
+
export declare function createStreamRunRuntime(input: {
|
|
5
|
+
persistence: RuntimePersistence;
|
|
6
|
+
runtimeAdapter: AgentRuntimeAdapter;
|
|
7
|
+
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
|
|
8
|
+
setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
|
|
9
|
+
previousState: string | null;
|
|
10
|
+
checkpointRef?: string | null;
|
|
11
|
+
error?: string;
|
|
12
|
+
}) => Promise<HarnessEvent>;
|
|
13
|
+
requestApprovalAndEmit: (threadId: string, runId: string, input: MessageContent, interruptContent: string | undefined, checkpointRef: string, sequence: number) => Promise<{
|
|
14
|
+
approval: {
|
|
15
|
+
approvalId: string;
|
|
16
|
+
pendingActionId: string;
|
|
17
|
+
};
|
|
18
|
+
event: HarnessEvent;
|
|
19
|
+
}>;
|
|
20
|
+
loadPriorHistory: (threadId: string, runId: string) => Promise<TranscriptMessage[]>;
|
|
21
|
+
invokeWithHistory: (binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string) => Promise<RunResult>;
|
|
22
|
+
emitSyntheticFallback: (threadId: string, runId: string, selectedAgentId: string, error: unknown) => Promise<void>;
|
|
23
|
+
}): {
|
|
24
|
+
loadPriorHistory: (threadId: string, runId: string) => Promise<TranscriptMessage[]>;
|
|
25
|
+
stream: (binding: CompiledAgentBinding, message: MessageContent, threadId: string, priorHistory: TranscriptMessage[], options: {
|
|
26
|
+
context?: Record<string, unknown>;
|
|
27
|
+
state?: Record<string, unknown>;
|
|
28
|
+
files?: Record<string, unknown>;
|
|
29
|
+
runId: string;
|
|
30
|
+
}) => AsyncGenerator<string | import("../../parsing/stream-event-parsing.js").RuntimeStreamChunk, any, any>;
|
|
31
|
+
invokeWithHistory: (binding: CompiledAgentBinding, message: MessageContent, threadId: string, runId: string) => Promise<RunResult>;
|
|
32
|
+
emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
|
|
33
|
+
setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
|
|
34
|
+
previousState: string | null;
|
|
35
|
+
checkpointRef?: string | null;
|
|
36
|
+
error?: string;
|
|
37
|
+
}) => Promise<HarnessEvent>;
|
|
38
|
+
requestApprovalAndEmit: (threadId: string, runId: string, message: MessageContent, interruptContent: string | undefined, checkpointRef: string, sequence: number) => Promise<{
|
|
39
|
+
approval: {
|
|
40
|
+
approvalId: string;
|
|
41
|
+
pendingActionId: string;
|
|
42
|
+
};
|
|
43
|
+
event: HarnessEvent;
|
|
44
|
+
}>;
|
|
45
|
+
appendAssistantMessage: (threadId: string, runId: string, content?: string) => Promise<void>;
|
|
46
|
+
clearRunRequest: (threadId: string, runId: string) => Promise<void>;
|
|
47
|
+
emitSyntheticFallback: (threadId: string, runId: string, selectedAgentId: string, error: unknown) => Promise<void>;
|
|
48
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { appendAssistantMessage as appendLifecycleAssistantMessage } from "./run-lifecycle.js";
|
|
2
|
+
export function createStreamRunRuntime(input) {
|
|
3
|
+
return {
|
|
4
|
+
loadPriorHistory: (threadId, runId) => input.loadPriorHistory(threadId, runId),
|
|
5
|
+
stream: (binding, message, threadId, priorHistory, options) => input.runtimeAdapter.stream(binding, message, threadId, priorHistory, options),
|
|
6
|
+
invokeWithHistory: (binding, message, threadId, runId) => input.invokeWithHistory(binding, message, threadId, runId),
|
|
7
|
+
emit: (threadId, runId, sequence, eventType, payload) => input.emit(threadId, runId, sequence, eventType, payload),
|
|
8
|
+
setRunStateAndEmit: (threadId, runId, sequence, state, options) => input.setRunStateAndEmit(threadId, runId, sequence, state, options),
|
|
9
|
+
requestApprovalAndEmit: (threadId, runId, message, interruptContent, checkpointRef, sequence) => input.requestApprovalAndEmit(threadId, runId, message, interruptContent, checkpointRef, sequence),
|
|
10
|
+
appendAssistantMessage: (threadId, runId, content) => appendLifecycleAssistantMessage(input.persistence, threadId, runId, content),
|
|
11
|
+
clearRunRequest: (threadId, runId) => input.persistence.clearRunRequest(threadId, runId),
|
|
12
|
+
emitSyntheticFallback: (threadId, runId, selectedAgentId, error) => input.emitSyntheticFallback(threadId, runId, selectedAgentId, error),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -33,6 +33,10 @@ export declare class AgentHarnessRuntime {
|
|
|
33
33
|
private pendingRunInsertionOrder;
|
|
34
34
|
private readonly pendingRunSlots;
|
|
35
35
|
private runtimeEventSequence;
|
|
36
|
+
private initialized;
|
|
37
|
+
private closed;
|
|
38
|
+
private readonly backgroundEventRuntime;
|
|
39
|
+
private readonly runtimeEventOperations;
|
|
36
40
|
private defaultRunRoot;
|
|
37
41
|
private getDefaultHostAgentId;
|
|
38
42
|
private resolveSelectedAgentId;
|
|
@@ -43,8 +47,6 @@ export declare class AgentHarnessRuntime {
|
|
|
43
47
|
initialize(): Promise<void>;
|
|
44
48
|
subscribe(listener: (event: HarnessEvent) => void): () => void;
|
|
45
49
|
getHealth(): Promise<RuntimeHealthSnapshot>;
|
|
46
|
-
private resolveAgentTools;
|
|
47
|
-
private supportsRunningReplay;
|
|
48
50
|
listThreads(filter?: {
|
|
49
51
|
agentId?: string;
|
|
50
52
|
}): Promise<ThreadSummary[]>;
|
|
@@ -76,7 +78,7 @@ export declare class AgentHarnessRuntime {
|
|
|
76
78
|
}): Promise<string>;
|
|
77
79
|
private emit;
|
|
78
80
|
private trackBackgroundTask;
|
|
79
|
-
private
|
|
81
|
+
private resolveToolMcpServerTools;
|
|
80
82
|
private loadPriorHistory;
|
|
81
83
|
private loadRunInput;
|
|
82
84
|
private getRunCancellation;
|
|
@@ -90,11 +92,8 @@ export declare class AgentHarnessRuntime {
|
|
|
90
92
|
private requestApprovalAndEmit;
|
|
91
93
|
private isDecisionRun;
|
|
92
94
|
private notifyListener;
|
|
93
|
-
private prepareRunStart;
|
|
94
|
-
private createStartupRecoveryContext;
|
|
95
95
|
private acquireRunSlot;
|
|
96
96
|
private dropPendingRunSlot;
|
|
97
|
-
private dispatchRunListeners;
|
|
98
97
|
run(options: RunOptions): Promise<RunResult>;
|
|
99
98
|
streamEvents(options: RunStartOptions): AsyncGenerator<HarnessStreamItem>;
|
|
100
99
|
resume(options: ResumeOptions): Promise<RunResult>;
|