@botbotgo/agent-harness 0.0.96 → 0.0.97
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/api.d.ts +5 -5
- package/dist/contracts/core.d.ts +9 -0
- package/dist/contracts/core.js +1 -0
- package/dist/contracts/runtime.d.ts +421 -0
- package/dist/contracts/runtime.js +1 -0
- package/dist/contracts/types.d.ts +3 -653
- package/dist/contracts/types.js +3 -1
- package/dist/contracts/workspace.d.ts +229 -0
- package/dist/contracts/workspace.js +1 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/compat/deepagent-compat.d.ts +16 -0
- package/dist/runtime/adapter/compat/deepagent-compat.js +45 -0
- package/dist/runtime/adapter/compat/openai-compatible.d.ts +2 -0
- package/dist/runtime/adapter/compat/openai-compatible.js +43 -0
- package/dist/runtime/adapter/index.d.ts +15 -0
- package/dist/runtime/adapter/index.js +15 -0
- package/dist/runtime/{langgraph-profiles.d.ts → adapter/langgraph/profiles.d.ts} +1 -1
- package/dist/runtime/adapter/model/invocation-request.d.ts +10 -0
- package/dist/runtime/adapter/model/invocation-request.js +46 -0
- package/dist/runtime/adapter/model/message-assembly.d.ts +6 -0
- package/dist/runtime/adapter/model/message-assembly.js +21 -0
- package/dist/runtime/adapter/model/model-providers.d.ts +2 -0
- package/dist/runtime/adapter/model/model-providers.js +27 -0
- package/dist/runtime/adapter/resilience.d.ts +12 -0
- package/dist/runtime/adapter/resilience.js +60 -0
- package/dist/runtime/{declared-middleware.d.ts → adapter/tool/declared-middleware.d.ts} +1 -1
- package/dist/runtime/adapter/tool/interrupt-policy.d.ts +8 -0
- package/dist/runtime/adapter/tool/interrupt-policy.js +34 -0
- package/dist/runtime/adapter/tool/provider-tool.d.ts +2 -0
- package/dist/runtime/adapter/tool/provider-tool.js +25 -0
- package/dist/runtime/adapter/tool/resolved-tool.d.ts +18 -0
- package/dist/runtime/adapter/tool/resolved-tool.js +62 -0
- package/dist/runtime/adapter/tool/tool-arguments.d.ts +7 -0
- package/dist/runtime/adapter/tool/tool-arguments.js +87 -0
- package/dist/runtime/{tool-hitl.d.ts → adapter/tool/tool-hitl.d.ts} +2 -2
- package/dist/runtime/adapter/tool/tool-name-mapping.d.ts +13 -0
- package/dist/runtime/adapter/tool/tool-name-mapping.js +101 -0
- package/dist/runtime/agent-runtime-adapter.d.ts +5 -20
- package/dist/runtime/agent-runtime-adapter.js +33 -536
- package/dist/runtime/checkpoint-maintenance.d.ts +1 -45
- package/dist/runtime/checkpoint-maintenance.js +1 -259
- package/dist/runtime/file-checkpoint-saver.d.ts +1 -20
- package/dist/runtime/file-checkpoint-saver.js +1 -106
- package/dist/runtime/{event-bus.d.ts → harness/events/event-bus.d.ts} +1 -1
- package/dist/runtime/{event-sink.d.ts → harness/events/event-sink.d.ts} +1 -1
- package/dist/runtime/{event-sink.js → harness/events/event-sink.js} +1 -1
- package/dist/runtime/harness/events/events.d.ts +23 -0
- package/dist/runtime/harness/events/events.js +61 -0
- package/dist/runtime/harness/events/streaming.d.ts +19 -0
- package/dist/runtime/harness/events/streaming.js +96 -0
- package/dist/runtime/harness/index.d.ts +16 -0
- package/dist/runtime/harness/index.js +16 -0
- package/dist/runtime/harness/run/helpers.d.ts +33 -0
- package/dist/runtime/harness/run/helpers.js +74 -0
- package/dist/runtime/harness/run/resources.d.ts +7 -0
- package/dist/runtime/harness/run/resources.js +58 -0
- package/dist/runtime/harness/run/resume.d.ts +6 -0
- package/dist/runtime/harness/run/resume.js +56 -0
- package/dist/runtime/harness/run/routing.d.ts +12 -0
- package/dist/runtime/harness/run/routing.js +47 -0
- package/dist/runtime/harness/run/run-lifecycle.d.ts +37 -0
- package/dist/runtime/harness/run/run-lifecycle.js +109 -0
- package/dist/runtime/harness/run/run-queue.d.ts +17 -0
- package/dist/runtime/harness/run/run-queue.js +43 -0
- package/dist/runtime/{health-monitor.d.ts → harness/system/health-monitor.d.ts} +3 -3
- package/dist/runtime/{health-monitor.js → harness/system/health-monitor.js} +2 -2
- package/dist/runtime/{inventory.d.ts → harness/system/inventory.d.ts} +2 -2
- package/dist/runtime/{inventory.js → harness/system/inventory.js} +4 -4
- package/dist/runtime/{policy-engine.d.ts → harness/system/policy-engine.d.ts} +1 -1
- package/dist/runtime/{policy-engine.js → harness/system/policy-engine.js} +1 -1
- package/dist/runtime/{skill-requirements.d.ts → harness/system/skill-requirements.d.ts} +1 -1
- package/dist/runtime/{skill-requirements.js → harness/system/skill-requirements.js} +1 -1
- package/dist/runtime/{thread-memory-sync.d.ts → harness/system/thread-memory-sync.d.ts} +2 -2
- package/dist/runtime/{thread-memory-sync.js → harness/system/thread-memory-sync.js} +1 -1
- package/dist/runtime/harness.d.ts +2 -8
- package/dist/runtime/harness.js +143 -493
- package/dist/runtime/index.d.ts +7 -7
- package/dist/runtime/index.js +7 -7
- package/dist/runtime/maintenance/checkpoint-maintenance.d.ts +45 -0
- package/dist/runtime/maintenance/checkpoint-maintenance.js +259 -0
- package/dist/runtime/maintenance/file-checkpoint-saver.d.ts +20 -0
- package/dist/runtime/maintenance/file-checkpoint-saver.js +106 -0
- package/dist/runtime/maintenance/index.d.ts +4 -0
- package/dist/runtime/maintenance/index.js +4 -0
- package/dist/runtime/{runtime-record-maintenance.d.ts → maintenance/runtime-record-maintenance.d.ts} +1 -1
- package/dist/runtime/{runtime-record-maintenance.js → maintenance/runtime-record-maintenance.js} +2 -2
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +9 -0
- package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +39 -0
- package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +1 -9
- package/dist/runtime/sqlite-maintained-checkpoint-saver.js +1 -39
- package/dist/runtime/support/harness-support.d.ts +4 -4
- package/dist/runtime/support/runtime-factories.d.ts +1 -1
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/package.json +4 -4
- /package/dist/runtime/{langgraph-presets.d.ts → adapter/langgraph/presets.d.ts} +0 -0
- /package/dist/runtime/{langgraph-presets.js → adapter/langgraph/presets.js} +0 -0
- /package/dist/runtime/{langgraph-profiles.js → adapter/langgraph/profiles.js} +0 -0
- /package/dist/runtime/{declared-middleware.js → adapter/tool/declared-middleware.js} +0 -0
- /package/dist/runtime/{tool-hitl.js → adapter/tool/tool-hitl.js} +0 -0
- /package/dist/runtime/{event-bus.js → harness/events/event-bus.js} +0 -0
- /package/dist/runtime/{store.d.ts → harness/system/store.d.ts} +0 -0
- /package/dist/runtime/{store.js → harness/system/store.js} +0 -0
package/dist/runtime/harness.js
CHANGED
|
@@ -4,23 +4,28 @@ import { createPersistentId } from "../utils/id.js";
|
|
|
4
4
|
import { AGENT_INTERRUPT_SENTINEL_PREFIX, AgentRuntimeAdapter, RuntimeOperationTimeoutError } from "./agent-runtime-adapter.js";
|
|
5
5
|
import { normalizeUpstreamRuntimeEvent } from "./parsing/stream-event-parsing.js";
|
|
6
6
|
import { createResourceBackendResolver, createResourceToolResolver } from "../resource/resource.js";
|
|
7
|
-
import { EventBus } from "./event-bus.js";
|
|
8
|
-
import { PolicyEngine } from "./policy-engine.js";
|
|
7
|
+
import { EventBus } from "./harness/events/event-bus.js";
|
|
8
|
+
import { PolicyEngine } from "./harness/system/policy-engine.js";
|
|
9
9
|
import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getRoutingRules, getRoutingSystemPrompt, isModelRoutingEnabled, matchRoutingRule, } from "../workspace/support/workspace-ref-utils.js";
|
|
10
|
-
import { createHarnessEvent,
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { resolveCompiledVectorStore, resolveCompiledVectorStoreRef } from "./support/vector-stores.js";
|
|
14
|
-
import { ThreadMemorySync } from "./thread-memory-sync.js";
|
|
15
|
-
import { FileBackedStore } from "./store.js";
|
|
10
|
+
import { createHarnessEvent, inferRoutingBindings, renderRuntimeFailure, renderToolFailure, } from "./support/harness-support.js";
|
|
11
|
+
import { ThreadMemorySync } from "./harness/system/thread-memory-sync.js";
|
|
12
|
+
import { FileBackedStore } from "./harness/system/store.js";
|
|
16
13
|
import { CheckpointMaintenanceLoop, discoverCheckpointMaintenanceTargets, readCheckpointMaintenanceConfig, } from "./checkpoint-maintenance.js";
|
|
17
|
-
import { RuntimeRecordMaintenanceLoop, discoverRuntimeRecordMaintenanceTargets, readRuntimeRecordMaintenanceConfig, } from "./runtime-record-maintenance.js";
|
|
18
|
-
import { HealthMonitor } from "./health-monitor.js";
|
|
14
|
+
import { RuntimeRecordMaintenanceLoop, discoverRuntimeRecordMaintenanceTargets, readRuntimeRecordMaintenanceConfig, } from "./maintenance/runtime-record-maintenance.js";
|
|
15
|
+
import { HealthMonitor } from "./harness/system/health-monitor.js";
|
|
19
16
|
import { extractMessageText, normalizeMessageContent } from "../utils/message-content.js";
|
|
17
|
+
import { buildPersistedRunRequest, isTerminalRunState, normalizeInvocationEnvelope, normalizeRunPriority, resolveRunListeners, toPublicApprovalRecord, } from "./harness/run/helpers.js";
|
|
18
|
+
import { emitHarnessEvent, emitRunCreatedEvent, emitSyntheticFallbackEvent, persistApproval, requestApprovalAndEmitEvent, setRunStateAndEmitEvent, } from "./harness/events/events.js";
|
|
19
|
+
import { appendAssistantMessage as appendLifecycleAssistantMessage, checkpointRefForState as getCheckpointRefForRunState, expirePendingApprovals as expireLifecyclePendingApprovals, finalizeCancelledRun as finalizeLifecycleCancelledRun, finalizeContinuedRun as finalizeLifecycleContinuedRun, reviewCompletedRun as reviewLifecycleCompletedRun, synthesizeCompletedRun as synthesizeLifecycleCompletedRun, } from "./harness/run/run-lifecycle.js";
|
|
20
|
+
import { createContentBlocksItem as createStreamingContentBlocksItem, createToolResultKey as createStreamingToolResultKey, dispatchRunListeners as dispatchStreamingRunListeners, emitOutputDeltaAndCreateItem as emitStreamingOutputDeltaAndCreateItem, } from "./harness/events/streaming.js";
|
|
21
|
+
import { buildResumePayload as buildHarnessResumePayload, resolveApprovalRecord as resolveHarnessApprovalRecord, } from "./harness/run/resume.js";
|
|
22
|
+
import { dropPendingRunSlot, enqueuePendingRunSlot, shiftNextPendingRunSlot } from "./harness/run/run-queue.js";
|
|
23
|
+
import { buildRoutingInput, getDefaultHostAgentId, heuristicHostRoute, resolveSelectedAgentId } from "./harness/run/routing.js";
|
|
24
|
+
import { resolveCheckpointer, resolveEmbeddingModel, resolveStore, resolveStoreFromConfig, resolveVectorStore, } from "./harness/run/resources.js";
|
|
20
25
|
import { createToolMcpServerFromTools, serveToolsOverStdioFromHarness } from "../mcp.js";
|
|
21
|
-
import { getBindingAdapterKind, getBindingPrimaryTools, getBindingStoreConfig
|
|
26
|
+
import { getBindingAdapterKind, getBindingPrimaryTools, getBindingStoreConfig } from "./support/compiled-binding.js";
|
|
22
27
|
import { isRuntimeEntryBinding } from "./support/runtime-entry.js";
|
|
23
|
-
import { describeWorkspaceInventory, listAgentSkills as listWorkspaceAgentSkills, } from "./inventory.js";
|
|
28
|
+
import { describeWorkspaceInventory, listAgentSkills as listWorkspaceAgentSkills, } from "./harness/system/inventory.js";
|
|
24
29
|
export class AgentHarnessRuntime {
|
|
25
30
|
workspace;
|
|
26
31
|
runtimeAdapterOptions;
|
|
@@ -60,22 +65,6 @@ export class AgentHarnessRuntime {
|
|
|
60
65
|
pendingRunInsertionOrder = 0;
|
|
61
66
|
pendingRunSlots = [];
|
|
62
67
|
runtimeEventSequence = 0;
|
|
63
|
-
toPublicApprovalRecord(approval) {
|
|
64
|
-
const { toolCallId: _toolCallId, checkpointRef: _checkpointRef, eventRefs: _eventRefs, ...publicApproval } = approval;
|
|
65
|
-
return publicApproval;
|
|
66
|
-
}
|
|
67
|
-
normalizeInvocationEnvelope(options) {
|
|
68
|
-
const invocation = options.invocation;
|
|
69
|
-
return {
|
|
70
|
-
context: invocation?.context,
|
|
71
|
-
state: invocation?.inputs,
|
|
72
|
-
files: invocation?.attachments,
|
|
73
|
-
invocation,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
isTerminalRunState(state) {
|
|
77
|
-
return state === "completed" || state === "failed";
|
|
78
|
-
}
|
|
79
68
|
listHostBindings() {
|
|
80
69
|
return inferRoutingBindings(this.workspace).hostBindings;
|
|
81
70
|
}
|
|
@@ -84,90 +73,36 @@ export class AgentHarnessRuntime {
|
|
|
84
73
|
`${this.workspace.workspaceRoot}/run-data`);
|
|
85
74
|
}
|
|
86
75
|
heuristicRoute(input) {
|
|
87
|
-
|
|
88
|
-
return heuristicRoute(extractMessageText(input), primaryBinding, secondaryBinding);
|
|
76
|
+
return heuristicHostRoute(this.workspace, input);
|
|
89
77
|
}
|
|
90
78
|
getDefaultHostAgentId() {
|
|
91
|
-
|
|
92
|
-
if (orchestraBinding && isRuntimeEntryBinding(orchestraBinding)) {
|
|
93
|
-
return orchestraBinding.agent.id;
|
|
94
|
-
}
|
|
95
|
-
return this.heuristicRoute("");
|
|
79
|
+
return getDefaultHostAgentId(this.workspace, AgentHarnessRuntime.DEFAULT_HOST_AGENT_ID);
|
|
96
80
|
}
|
|
97
81
|
async buildRoutingInput(input, threadId) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
return inputText;
|
|
101
|
-
}
|
|
102
|
-
const history = await this.persistence.listThreadMessages(threadId);
|
|
103
|
-
const priorHistory = history.filter((message) => extractMessageText(message.content).trim());
|
|
104
|
-
if (priorHistory.length === 0) {
|
|
105
|
-
return inputText;
|
|
106
|
-
}
|
|
107
|
-
const recentTurns = priorHistory.slice(-6).map((message) => {
|
|
108
|
-
const role = message.role === "assistant" ? "assistant" : "user";
|
|
109
|
-
const compact = extractMessageText(message.content).replace(/\s+/g, " ").trim();
|
|
110
|
-
return `${role}: ${compact.slice(0, 240)}`;
|
|
111
|
-
});
|
|
112
|
-
return [
|
|
113
|
-
"Recent conversation context:",
|
|
114
|
-
...recentTurns,
|
|
115
|
-
"",
|
|
116
|
-
`Current user request: ${inputText}`,
|
|
117
|
-
].join("\n");
|
|
82
|
+
const history = threadId ? await this.persistence.listThreadMessages(threadId) : [];
|
|
83
|
+
return buildRoutingInput(input, history);
|
|
118
84
|
}
|
|
119
85
|
async resolveSelectedAgentId(input, requestedAgentId, threadId) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return this.getDefaultHostAgentId();
|
|
129
|
-
}
|
|
130
|
-
return requestedAgentId;
|
|
86
|
+
return resolveSelectedAgentId({
|
|
87
|
+
workspace: this.workspace,
|
|
88
|
+
input,
|
|
89
|
+
requestedAgentId,
|
|
90
|
+
threadId,
|
|
91
|
+
preferredHostAgentId: AgentHarnessRuntime.DEFAULT_HOST_AGENT_ID,
|
|
92
|
+
getThreadSummary: (currentThreadId) => this.getSession(currentThreadId),
|
|
93
|
+
});
|
|
131
94
|
}
|
|
132
95
|
resolveStore(binding) {
|
|
133
|
-
|
|
134
|
-
return this.resolveStoreFromConfig(storeConfig, binding?.harnessRuntime.runRoot ?? this.defaultRunRoot()) ?? this.defaultStore;
|
|
96
|
+
return resolveStore(this.stores, this.defaultStore, this.defaultRunRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding);
|
|
135
97
|
}
|
|
136
98
|
resolveStoreFromConfig(storeConfig, runRoot) {
|
|
137
|
-
|
|
138
|
-
if (!storeConfig || !cacheKey) {
|
|
139
|
-
return undefined;
|
|
140
|
-
}
|
|
141
|
-
const existing = this.stores.get(cacheKey);
|
|
142
|
-
if (existing) {
|
|
143
|
-
return existing;
|
|
144
|
-
}
|
|
145
|
-
const created = createStoreForConfig(storeConfig, runRoot);
|
|
146
|
-
this.stores.set(cacheKey, created);
|
|
147
|
-
return created;
|
|
99
|
+
return resolveStoreFromConfig(this.stores, storeConfig, runRoot);
|
|
148
100
|
}
|
|
149
101
|
async resolveEmbeddingModel(embeddingModelRef) {
|
|
150
|
-
|
|
151
|
-
const existing = this.embeddingModels.get(compiled.id);
|
|
152
|
-
if (existing) {
|
|
153
|
-
return existing;
|
|
154
|
-
}
|
|
155
|
-
const resolved = await resolveCompiledEmbeddingModel(compiled, this.runtimeAdapterOptions.embeddingModelResolver);
|
|
156
|
-
this.embeddingModels.set(compiled.id, resolved);
|
|
157
|
-
return resolved;
|
|
102
|
+
return resolveEmbeddingModel(this.workspace, this.embeddingModels, embeddingModelRef, this.runtimeAdapterOptions);
|
|
158
103
|
}
|
|
159
104
|
async resolveVectorStore(vectorStoreRef) {
|
|
160
|
-
|
|
161
|
-
const existing = this.vectorStores.get(compiled.id);
|
|
162
|
-
if (existing) {
|
|
163
|
-
return existing;
|
|
164
|
-
}
|
|
165
|
-
const resolved = await resolveCompiledVectorStore(this.workspace, compiled, {
|
|
166
|
-
embeddingModelResolver: this.runtimeAdapterOptions.embeddingModelResolver,
|
|
167
|
-
vectorStoreResolver: this.runtimeAdapterOptions.vectorStoreResolver,
|
|
168
|
-
});
|
|
169
|
-
this.vectorStores.set(compiled.id, resolved);
|
|
170
|
-
return resolved;
|
|
105
|
+
return resolveVectorStore(this.workspace, this.vectorStores, vectorStoreRef, this.runtimeAdapterOptions);
|
|
171
106
|
}
|
|
172
107
|
constructor(workspace, runtimeAdapterOptions = {}) {
|
|
173
108
|
this.workspace = workspace;
|
|
@@ -190,21 +125,7 @@ export class AgentHarnessRuntime {
|
|
|
190
125
|
getVectorStore: (vectorStoreRef) => this.resolveVectorStore(vectorStoreRef),
|
|
191
126
|
}),
|
|
192
127
|
checkpointerResolver: runtimeAdapterOptions.checkpointerResolver ??
|
|
193
|
-
((binding) =>
|
|
194
|
-
const key = `${binding.harnessRuntime.runRoot}:${JSON.stringify(binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" })}`;
|
|
195
|
-
const existing = this.checkpointers.get(key);
|
|
196
|
-
if (existing) {
|
|
197
|
-
return existing;
|
|
198
|
-
}
|
|
199
|
-
const resolvedConfig = binding.harnessRuntime.checkpointer ?? { kind: "FileCheckpointer", path: "checkpoints.json" };
|
|
200
|
-
if (typeof resolvedConfig === "boolean") {
|
|
201
|
-
this.checkpointers.set(key, resolvedConfig);
|
|
202
|
-
return resolvedConfig;
|
|
203
|
-
}
|
|
204
|
-
const saver = createCheckpointerForConfig(resolvedConfig, binding.harnessRuntime.runRoot);
|
|
205
|
-
this.checkpointers.set(key, saver);
|
|
206
|
-
return saver;
|
|
207
|
-
}),
|
|
128
|
+
((binding) => resolveCheckpointer(this.checkpointers, binding)),
|
|
208
129
|
storeResolver: runtimeAdapterOptions.storeResolver ??
|
|
209
130
|
((binding) => this.resolveStore(binding)),
|
|
210
131
|
backendResolver: runtimeAdapterOptions.backendResolver ??
|
|
@@ -328,11 +249,11 @@ export class AgentHarnessRuntime {
|
|
|
328
249
|
}
|
|
329
250
|
async listApprovals(filter) {
|
|
330
251
|
const approvals = await this.persistence.listApprovals(filter);
|
|
331
|
-
return approvals.map((approval) =>
|
|
252
|
+
return approvals.map((approval) => toPublicApprovalRecord(approval));
|
|
332
253
|
}
|
|
333
254
|
async getApproval(approvalId) {
|
|
334
255
|
const approval = await this.persistence.getApproval(approvalId);
|
|
335
|
-
return approval ?
|
|
256
|
+
return approval ? toPublicApprovalRecord(approval) : null;
|
|
336
257
|
}
|
|
337
258
|
listAgentSkills(agentId, options = {}) {
|
|
338
259
|
return listWorkspaceAgentSkills(this.workspace, agentId, options);
|
|
@@ -363,7 +284,7 @@ export class AgentHarnessRuntime {
|
|
|
363
284
|
if (!thread) {
|
|
364
285
|
return false;
|
|
365
286
|
}
|
|
366
|
-
const activeRun = thread.runs.find((run) => !
|
|
287
|
+
const activeRun = thread.runs.find((run) => !isTerminalRunState(run.state));
|
|
367
288
|
if (activeRun) {
|
|
368
289
|
throw new Error(`Cannot delete thread ${threadId} while run ${activeRun.runId} is ${activeRun.state}`);
|
|
369
290
|
}
|
|
@@ -390,7 +311,8 @@ export class AgentHarnessRuntime {
|
|
|
390
311
|
return serveToolsOverStdioFromHarness(tools, options);
|
|
391
312
|
}
|
|
392
313
|
async routeAgent(input, options = {}) {
|
|
393
|
-
const
|
|
314
|
+
const routingHistory = options.threadId ? await this.persistence.listThreadMessages(options.threadId) : [];
|
|
315
|
+
const routingInput = buildRoutingInput(input, routingHistory);
|
|
394
316
|
const rawInput = extractMessageText(input);
|
|
395
317
|
const { primaryBinding, secondaryBinding } = inferRoutingBindings(this.workspace);
|
|
396
318
|
const configuredRule = this.routingRules.find((rule) => matchRoutingRule(rawInput, rule, options));
|
|
@@ -409,7 +331,7 @@ export class AgentHarnessRuntime {
|
|
|
409
331
|
}
|
|
410
332
|
}
|
|
411
333
|
if (!primaryBinding || !secondaryBinding) {
|
|
412
|
-
return
|
|
334
|
+
return heuristicHostRoute(this.workspace, rawInput);
|
|
413
335
|
}
|
|
414
336
|
try {
|
|
415
337
|
return await this.runtimeAdapter.route(routingInput, primaryBinding, secondaryBinding, {
|
|
@@ -417,21 +339,16 @@ export class AgentHarnessRuntime {
|
|
|
417
339
|
});
|
|
418
340
|
}
|
|
419
341
|
catch {
|
|
420
|
-
return
|
|
342
|
+
return heuristicHostRoute(this.workspace, rawInput);
|
|
421
343
|
}
|
|
422
344
|
}
|
|
423
345
|
async emit(threadId, runId, sequence, eventType, payload, source = "runtime") {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
await this.persistence.appendEvent(event);
|
|
432
|
-
}
|
|
433
|
-
this.eventBus.publish(event);
|
|
434
|
-
return event;
|
|
346
|
+
return emitHarnessEvent({
|
|
347
|
+
persistence: this.persistence,
|
|
348
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
349
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
350
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
351
|
+
}, threadId, runId, sequence, eventType, payload, source);
|
|
435
352
|
}
|
|
436
353
|
trackBackgroundTask(task) {
|
|
437
354
|
this.backgroundTasks.add(task);
|
|
@@ -499,15 +416,7 @@ export class AgentHarnessRuntime {
|
|
|
499
416
|
return userTurn?.content ?? "";
|
|
500
417
|
}
|
|
501
418
|
async appendAssistantMessage(threadId, runId, content) {
|
|
502
|
-
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
await this.persistence.appendThreadMessage(threadId, {
|
|
506
|
-
role: "assistant",
|
|
507
|
-
content,
|
|
508
|
-
runId,
|
|
509
|
-
createdAt: new Date().toISOString(),
|
|
510
|
-
});
|
|
419
|
+
return appendLifecycleAssistantMessage(this.persistence, threadId, runId, content);
|
|
511
420
|
}
|
|
512
421
|
async getRunCancellation(runId) {
|
|
513
422
|
const control = await this.persistence.getRunControl(runId);
|
|
@@ -517,37 +426,17 @@ export class AgentHarnessRuntime {
|
|
|
517
426
|
};
|
|
518
427
|
}
|
|
519
428
|
async expirePendingApprovals(threadId, runId) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
}
|
|
525
|
-
await this.persistence.resolveApproval(threadId, runId, approval.approvalId, "expired");
|
|
526
|
-
await this.emit(threadId, runId, 6, "approval.resolved", {
|
|
527
|
-
approvalId: approval.approvalId,
|
|
528
|
-
pendingActionId: approval.pendingActionId,
|
|
529
|
-
decision: "cancel",
|
|
530
|
-
toolName: approval.toolName,
|
|
531
|
-
});
|
|
532
|
-
}
|
|
429
|
+
return expireLifecyclePendingApprovals({
|
|
430
|
+
persistence: this.persistence,
|
|
431
|
+
emit: (currentThreadId, currentRunId, sequence, eventType, payload, source) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload, source),
|
|
432
|
+
}, threadId, runId);
|
|
533
433
|
}
|
|
534
434
|
async finalizeCancelledRun(threadId, runId, previousState, reason) {
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
previousState,
|
|
541
|
-
...(reason ? { error: reason } : {}),
|
|
542
|
-
});
|
|
543
|
-
const runMeta = await this.persistence.getRunMeta(threadId, runId);
|
|
544
|
-
return {
|
|
545
|
-
threadId,
|
|
546
|
-
runId,
|
|
547
|
-
agentId: runMeta.agentId,
|
|
548
|
-
state: "cancelled",
|
|
549
|
-
output: reason ? `cancelled: ${reason}` : "cancelled",
|
|
550
|
-
};
|
|
435
|
+
return finalizeLifecycleCancelledRun({
|
|
436
|
+
persistence: this.persistence,
|
|
437
|
+
emit: (currentThreadId, currentRunId, sequence, eventType, payload, source) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload, source),
|
|
438
|
+
setRunStateAndEmit: (currentThreadId, currentRunId, sequence, state, options) => this.setRunStateAndEmit(currentThreadId, currentRunId, sequence, state, options),
|
|
439
|
+
}, threadId, runId, previousState, reason);
|
|
551
440
|
}
|
|
552
441
|
async invokeWithHistory(binding, input, threadId, runId, resumePayload, priorHistory, options = {}) {
|
|
553
442
|
const history = priorHistory ?? await this.loadPriorHistory(threadId, runId);
|
|
@@ -562,67 +451,12 @@ export class AgentHarnessRuntime {
|
|
|
562
451
|
throw error;
|
|
563
452
|
}
|
|
564
453
|
}
|
|
565
|
-
buildPersistedRunRequest(input, invocation, priority) {
|
|
566
|
-
const envelope = invocation.invocation ?? {
|
|
567
|
-
...(invocation.context ? { context: invocation.context } : {}),
|
|
568
|
-
...(invocation.state ? { inputs: invocation.state } : {}),
|
|
569
|
-
...(invocation.files ? { attachments: invocation.files } : {}),
|
|
570
|
-
};
|
|
571
|
-
return {
|
|
572
|
-
input: normalizeMessageContent(input),
|
|
573
|
-
priority: Number.isFinite(priority) ? Math.trunc(priority) : undefined,
|
|
574
|
-
invocation: envelope && Object.keys(envelope).length > 0
|
|
575
|
-
? {
|
|
576
|
-
...(envelope.context ? { context: envelope.context } : {}),
|
|
577
|
-
...(envelope.inputs ? { inputs: envelope.inputs } : {}),
|
|
578
|
-
...(envelope.attachments ? { attachments: envelope.attachments } : {}),
|
|
579
|
-
...(envelope.capabilities ? { capabilities: envelope.capabilities } : {}),
|
|
580
|
-
}
|
|
581
|
-
: undefined,
|
|
582
|
-
savedAt: new Date().toISOString(),
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
normalizeRunPriority(priority) {
|
|
586
|
-
if (!Number.isFinite(priority)) {
|
|
587
|
-
return 0;
|
|
588
|
-
}
|
|
589
|
-
return Math.trunc(priority);
|
|
590
|
-
}
|
|
591
454
|
async resolvePersistedRunPriority(threadId, runId) {
|
|
592
455
|
const persisted = await this.persistence.getRunRequest(threadId, runId);
|
|
593
|
-
return
|
|
456
|
+
return normalizeRunPriority(persisted?.priority);
|
|
594
457
|
}
|
|
595
458
|
enqueuePendingRunSlot(entry) {
|
|
596
|
-
|
|
597
|
-
.filter((candidate) => Boolean(candidate.threadId && candidate.runId))
|
|
598
|
-
.map((candidate, index) => [candidate.runId, index + 1]));
|
|
599
|
-
const queuedEntry = {
|
|
600
|
-
...entry,
|
|
601
|
-
insertionOrder: this.pendingRunInsertionOrder++,
|
|
602
|
-
};
|
|
603
|
-
this.pendingRunSlots.push(queuedEntry);
|
|
604
|
-
this.pendingRunSlots.sort((left, right) => {
|
|
605
|
-
if (right.priority !== left.priority) {
|
|
606
|
-
return right.priority - left.priority;
|
|
607
|
-
}
|
|
608
|
-
return left.insertionOrder - right.insertionOrder;
|
|
609
|
-
});
|
|
610
|
-
return this.pendingRunSlots.flatMap((candidate, index) => {
|
|
611
|
-
if (!candidate.threadId || !candidate.runId) {
|
|
612
|
-
return [];
|
|
613
|
-
}
|
|
614
|
-
const previousPosition = previousPositions.get(candidate.runId);
|
|
615
|
-
const queuePosition = index + 1;
|
|
616
|
-
if (previousPosition === undefined || previousPosition === queuePosition) {
|
|
617
|
-
return [];
|
|
618
|
-
}
|
|
619
|
-
return [{
|
|
620
|
-
threadId: candidate.threadId,
|
|
621
|
-
runId: candidate.runId,
|
|
622
|
-
priority: candidate.priority,
|
|
623
|
-
queuePosition,
|
|
624
|
-
}];
|
|
625
|
-
});
|
|
459
|
+
return enqueuePendingRunSlot(this.pendingRunSlots, entry, this.pendingRunInsertionOrder++);
|
|
626
460
|
}
|
|
627
461
|
async executeQueuedRun(binding, input, threadId, runId, agentId, options = {}) {
|
|
628
462
|
const previousState = options.previousState ?? "running";
|
|
@@ -690,164 +524,80 @@ export class AgentHarnessRuntime {
|
|
|
690
524
|
}
|
|
691
525
|
}
|
|
692
526
|
checkpointRefForState(threadId, runId, state) {
|
|
693
|
-
return
|
|
527
|
+
return getCheckpointRefForRunState(threadId, runId, state);
|
|
694
528
|
}
|
|
695
529
|
async finalizeContinuedRun(binding, threadId, runId, input, actual, options) {
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
:
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
checkpointRef,
|
|
705
|
-
});
|
|
706
|
-
if (finalizedActual.state === "waiting_for_approval" && options.approvalSequence) {
|
|
707
|
-
approval = (await this.requestApprovalAndEmit(threadId, runId, input, finalizedActual.interruptContent, checkpointRef, options.approvalSequence)).approval;
|
|
708
|
-
}
|
|
709
|
-
if (finalizedActual.state === "completed") {
|
|
710
|
-
await this.reviewCompletedRun(binding, threadId, runId, input, finalizedActual);
|
|
711
|
-
}
|
|
712
|
-
return {
|
|
713
|
-
...finalizedActual,
|
|
714
|
-
threadId,
|
|
715
|
-
runId,
|
|
716
|
-
approvalId: approval?.approvalId ?? finalizedActual.approvalId,
|
|
717
|
-
pendingActionId: approval?.pendingActionId ?? finalizedActual.pendingActionId,
|
|
718
|
-
};
|
|
530
|
+
return finalizeLifecycleContinuedRun({
|
|
531
|
+
persistence: this.persistence,
|
|
532
|
+
emit: (currentThreadId, currentRunId, sequence, eventType, payload, source) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload, source),
|
|
533
|
+
setRunStateAndEmit: (currentThreadId, currentRunId, sequence, state, lifecycleOptions) => this.setRunStateAndEmit(currentThreadId, currentRunId, sequence, state, lifecycleOptions),
|
|
534
|
+
requestApprovalAndEmit: (currentThreadId, currentRunId, lifecycleInput, interruptContent, checkpointRef, sequence) => this.requestApprovalAndEmit(currentThreadId, currentRunId, lifecycleInput, interruptContent, checkpointRef, sequence),
|
|
535
|
+
synthesizeFinalResult: (currentBinding, lifecycleInput, lifecycleActual) => this.runtimeAdapter.synthesizeFinalResult(currentBinding, lifecycleInput, lifecycleActual),
|
|
536
|
+
reviewRunResult: (currentBinding, lifecycleInput, lifecycleActual) => this.runtimeAdapter.reviewRunResult(currentBinding, lifecycleInput, lifecycleActual),
|
|
537
|
+
}, binding, threadId, runId, input, actual, options);
|
|
719
538
|
}
|
|
720
539
|
async synthesizeCompletedRun(binding, input, actual) {
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
return actual;
|
|
725
|
-
}
|
|
726
|
-
return {
|
|
727
|
-
...actual,
|
|
728
|
-
output: synthesized.output,
|
|
729
|
-
finalMessageText: synthesized.finalMessageText,
|
|
730
|
-
metadata: {
|
|
731
|
-
...(typeof actual.metadata === "object" && actual.metadata ? actual.metadata : {}),
|
|
732
|
-
finalSynthesis: {
|
|
733
|
-
modelId: synthesized.modelId,
|
|
734
|
-
},
|
|
735
|
-
},
|
|
736
|
-
};
|
|
737
|
-
}
|
|
738
|
-
catch {
|
|
739
|
-
return actual;
|
|
740
|
-
}
|
|
540
|
+
return synthesizeLifecycleCompletedRun({
|
|
541
|
+
synthesizeFinalResult: (currentBinding, lifecycleInput, lifecycleActual) => this.runtimeAdapter.synthesizeFinalResult(currentBinding, lifecycleInput, lifecycleActual),
|
|
542
|
+
}, binding, input, actual);
|
|
741
543
|
}
|
|
742
544
|
async reviewCompletedRun(binding, threadId, runId, input, actual) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
748
|
-
await this.emit(threadId, runId, 7, "run.reviewed", {
|
|
749
|
-
modelId: review.modelId,
|
|
750
|
-
assessment: review.assessment,
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
catch {
|
|
754
|
-
// Review is advisory; do not fail the completed run if the review pass fails.
|
|
755
|
-
}
|
|
545
|
+
return reviewLifecycleCompletedRun({
|
|
546
|
+
reviewRunResult: (currentBinding, lifecycleInput, lifecycleActual) => this.runtimeAdapter.reviewRunResult(currentBinding, lifecycleInput, lifecycleActual),
|
|
547
|
+
emit: (currentThreadId, currentRunId, sequence, eventType, payload, source) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload, source),
|
|
548
|
+
}, binding, threadId, runId, input, actual);
|
|
756
549
|
}
|
|
757
550
|
async emitOutputDeltaAndCreateItem(threadId, runId, agentId, content) {
|
|
758
|
-
|
|
759
|
-
content,
|
|
760
|
-
});
|
|
761
|
-
return {
|
|
762
|
-
type: "content",
|
|
763
|
-
threadId,
|
|
764
|
-
runId,
|
|
765
|
-
agentId,
|
|
766
|
-
content,
|
|
767
|
-
};
|
|
551
|
+
return emitStreamingOutputDeltaAndCreateItem((currentThreadId, currentRunId, sequence, eventType, payload) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload), threadId, runId, agentId, content);
|
|
768
552
|
}
|
|
769
553
|
createContentBlocksItem(threadId, runId, agentId, contentBlocks) {
|
|
770
|
-
return
|
|
771
|
-
type: "content-blocks",
|
|
772
|
-
threadId,
|
|
773
|
-
runId,
|
|
774
|
-
agentId,
|
|
775
|
-
contentBlocks,
|
|
776
|
-
};
|
|
554
|
+
return createStreamingContentBlocksItem(threadId, runId, agentId, contentBlocks);
|
|
777
555
|
}
|
|
778
556
|
createToolResultKey(toolName, output, isError) {
|
|
779
|
-
|
|
780
|
-
try {
|
|
781
|
-
serializedOutput = JSON.stringify(output);
|
|
782
|
-
}
|
|
783
|
-
catch {
|
|
784
|
-
serializedOutput = String(output);
|
|
785
|
-
}
|
|
786
|
-
return JSON.stringify([toolName, serializedOutput, isError === true]);
|
|
557
|
+
return createStreamingToolResultKey(toolName, output, isError);
|
|
787
558
|
}
|
|
788
559
|
async emitRunCreated(threadId, runId, payload) {
|
|
789
|
-
return
|
|
560
|
+
return emitRunCreatedEvent({
|
|
561
|
+
persistence: this.persistence,
|
|
562
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
563
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
564
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
565
|
+
}, threadId, runId, payload);
|
|
790
566
|
}
|
|
791
567
|
async setRunStateAndEmit(threadId, runId, sequence, state, options) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
});
|
|
568
|
+
return setRunStateAndEmitEvent({
|
|
569
|
+
persistence: this.persistence,
|
|
570
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
571
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
572
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
573
|
+
}, threadId, runId, sequence, state, options);
|
|
799
574
|
}
|
|
800
575
|
async requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
allowedDecisions: approval.allowedDecisions,
|
|
808
|
-
checkpointRef,
|
|
809
|
-
});
|
|
810
|
-
return { approval, event };
|
|
576
|
+
return requestApprovalAndEmitEvent({
|
|
577
|
+
persistence: this.persistence,
|
|
578
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
579
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
580
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
581
|
+
}, threadId, runId, input, interruptContent, checkpointRef, sequence);
|
|
811
582
|
}
|
|
812
583
|
async emitSyntheticFallback(threadId, runId, selectedAgentId, error, sequence = 3) {
|
|
813
|
-
await
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
584
|
+
await emitSyntheticFallbackEvent({
|
|
585
|
+
persistence: this.persistence,
|
|
586
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
587
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
588
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
589
|
+
}, threadId, runId, selectedAgentId, error, sequence);
|
|
817
590
|
}
|
|
818
591
|
async persistApproval(threadId, runId, checkpointRef, input, interruptContent) {
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
createdAt: approval.requestedAt,
|
|
826
|
-
}, approval);
|
|
827
|
-
await this.emit(threadId, runId, 5, "artifact.created", {
|
|
828
|
-
artifactId: artifact.artifactId,
|
|
829
|
-
kind: artifact.kind,
|
|
830
|
-
path: artifact.path,
|
|
831
|
-
});
|
|
832
|
-
return approval;
|
|
592
|
+
return persistApproval({
|
|
593
|
+
persistence: this.persistence,
|
|
594
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
595
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
596
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
597
|
+
}, threadId, runId, checkpointRef, input, interruptContent);
|
|
833
598
|
}
|
|
834
599
|
async resolveApprovalRecord(options, thread) {
|
|
835
|
-
|
|
836
|
-
const approval = await this.persistence.getApproval(options.approvalId);
|
|
837
|
-
if (!approval) {
|
|
838
|
-
throw new Error(`Unknown approval ${options.approvalId}`);
|
|
839
|
-
}
|
|
840
|
-
return approval;
|
|
841
|
-
}
|
|
842
|
-
const runId = options.runId ?? thread.latestRunId;
|
|
843
|
-
const approvals = await this.persistence.getRunApprovals(options.threadId ?? thread.threadId, runId);
|
|
844
|
-
const approval = approvals
|
|
845
|
-
.filter((candidate) => candidate.status === "pending")
|
|
846
|
-
.sort((left, right) => right.requestedAt.localeCompare(left.requestedAt))[0];
|
|
847
|
-
if (!approval) {
|
|
848
|
-
throw new Error(`No pending approval for run ${runId}`);
|
|
849
|
-
}
|
|
850
|
-
return approval;
|
|
600
|
+
return resolveHarnessApprovalRecord(this.persistence, options, thread);
|
|
851
601
|
}
|
|
852
602
|
isDecisionRun(options) {
|
|
853
603
|
return "decision" in options;
|
|
@@ -927,7 +677,7 @@ export class AgentHarnessRuntime {
|
|
|
927
677
|
released = true;
|
|
928
678
|
await releaseLease();
|
|
929
679
|
this.activeRunSlots = Math.max(0, this.activeRunSlots - 1);
|
|
930
|
-
const next = this.pendingRunSlots
|
|
680
|
+
const next = shiftNextPendingRunSlot(this.pendingRunSlots);
|
|
931
681
|
void next?.activate();
|
|
932
682
|
};
|
|
933
683
|
}
|
|
@@ -1009,98 +759,18 @@ export class AgentHarnessRuntime {
|
|
|
1009
759
|
released = true;
|
|
1010
760
|
await releaseLease();
|
|
1011
761
|
this.activeRunSlots = Math.max(0, this.activeRunSlots - 1);
|
|
1012
|
-
const next = this.pendingRunSlots
|
|
762
|
+
const next = shiftNextPendingRunSlot(this.pendingRunSlots);
|
|
1013
763
|
void next?.activate();
|
|
1014
764
|
};
|
|
1015
765
|
}
|
|
1016
766
|
dropPendingRunSlot(runId) {
|
|
1017
|
-
|
|
1018
|
-
if (index < 0) {
|
|
1019
|
-
return false;
|
|
1020
|
-
}
|
|
1021
|
-
const [entry] = this.pendingRunSlots.splice(index, 1);
|
|
1022
|
-
entry?.abort();
|
|
1023
|
-
return true;
|
|
767
|
+
return dropPendingRunSlot(this.pendingRunSlots, runId);
|
|
1024
768
|
}
|
|
1025
769
|
async dispatchRunListeners(stream, listeners) {
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
if (item.type === "event") {
|
|
1031
|
-
latestEvent = item.event;
|
|
1032
|
-
await this.notifyListener(listeners.onEvent, item.event);
|
|
1033
|
-
continue;
|
|
1034
|
-
}
|
|
1035
|
-
if (item.type === "upstream-event") {
|
|
1036
|
-
await this.notifyListener(listeners.onUpstreamEvent, item.event);
|
|
1037
|
-
continue;
|
|
1038
|
-
}
|
|
1039
|
-
if (item.type === "result") {
|
|
1040
|
-
latestResult = item.result;
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
if (item.type === "content") {
|
|
1044
|
-
output += item.content;
|
|
1045
|
-
await this.notifyListener(listeners.onChunk, item.content);
|
|
1046
|
-
continue;
|
|
1047
|
-
}
|
|
1048
|
-
if (item.type === "content-blocks") {
|
|
1049
|
-
await this.notifyListener(listeners.onContentBlocks, item.contentBlocks);
|
|
1050
|
-
continue;
|
|
1051
|
-
}
|
|
1052
|
-
if (item.type === "reasoning") {
|
|
1053
|
-
await this.notifyListener(listeners.onReasoning, item.content);
|
|
1054
|
-
continue;
|
|
1055
|
-
}
|
|
1056
|
-
if (item.type === "step") {
|
|
1057
|
-
await this.notifyListener(listeners.onStep, item.content);
|
|
1058
|
-
continue;
|
|
1059
|
-
}
|
|
1060
|
-
if (item.type === "tool-result") {
|
|
1061
|
-
await this.notifyListener(listeners.onToolResult, {
|
|
1062
|
-
toolName: item.toolName,
|
|
1063
|
-
output: item.output,
|
|
1064
|
-
isError: item.isError,
|
|
1065
|
-
});
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
if (!latestEvent) {
|
|
1069
|
-
throw new Error("run did not emit any events");
|
|
1070
|
-
}
|
|
1071
|
-
if (latestResult) {
|
|
1072
|
-
return {
|
|
1073
|
-
...latestResult,
|
|
1074
|
-
output: latestResult.output || output,
|
|
1075
|
-
finalMessageText: latestResult.finalMessageText ?? latestResult.output ?? output,
|
|
1076
|
-
};
|
|
1077
|
-
}
|
|
1078
|
-
const thread = await this.getThread(latestEvent.threadId);
|
|
1079
|
-
if (!thread) {
|
|
1080
|
-
throw new Error(`Unknown thread ${latestEvent.threadId}`);
|
|
1081
|
-
}
|
|
1082
|
-
return {
|
|
1083
|
-
threadId: thread.threadId,
|
|
1084
|
-
runId: thread.latestRunId,
|
|
1085
|
-
agentId: thread.runs[0]?.agentId ?? thread.entryAgentId,
|
|
1086
|
-
state: thread.currentState,
|
|
1087
|
-
output,
|
|
1088
|
-
approvalId: thread.pendingDecision?.approvalId,
|
|
1089
|
-
pendingActionId: thread.pendingDecision?.pendingActionId,
|
|
1090
|
-
};
|
|
1091
|
-
}
|
|
1092
|
-
resolveRunListeners(options) {
|
|
1093
|
-
const runtimeListeners = "runtimeListeners" in options ? options.runtimeListeners : undefined;
|
|
1094
|
-
const frontendListeners = "frontendListeners" in options ? options.frontendListeners : undefined;
|
|
1095
|
-
const listeners = options.listeners;
|
|
1096
|
-
if (!listeners && !runtimeListeners && !frontendListeners) {
|
|
1097
|
-
return undefined;
|
|
1098
|
-
}
|
|
1099
|
-
return {
|
|
1100
|
-
...(runtimeListeners ?? {}),
|
|
1101
|
-
...(frontendListeners ?? {}),
|
|
1102
|
-
...(listeners ?? {}),
|
|
1103
|
-
};
|
|
770
|
+
return dispatchStreamingRunListeners(stream, listeners, {
|
|
771
|
+
notifyListener: (listener, value) => this.notifyListener(listener, value),
|
|
772
|
+
getThread: (threadId) => this.getThread(threadId),
|
|
773
|
+
});
|
|
1104
774
|
}
|
|
1105
775
|
async run(options) {
|
|
1106
776
|
if (this.isDecisionRun(options)) {
|
|
@@ -1113,12 +783,19 @@ export class AgentHarnessRuntime {
|
|
|
1113
783
|
};
|
|
1114
784
|
return this.resume(resumeOptions);
|
|
1115
785
|
}
|
|
1116
|
-
const resolvedListeners =
|
|
786
|
+
const resolvedListeners = resolveRunListeners(options);
|
|
1117
787
|
if (resolvedListeners) {
|
|
1118
788
|
return this.dispatchRunListeners(this.streamEvents(options), resolvedListeners);
|
|
1119
789
|
}
|
|
1120
|
-
const invocation =
|
|
1121
|
-
const selectedAgentId = await
|
|
790
|
+
const invocation = normalizeInvocationEnvelope(options);
|
|
791
|
+
const selectedAgentId = await resolveSelectedAgentId({
|
|
792
|
+
workspace: this.workspace,
|
|
793
|
+
input: options.input,
|
|
794
|
+
requestedAgentId: options.agentId,
|
|
795
|
+
threadId: options.threadId,
|
|
796
|
+
preferredHostAgentId: AgentHarnessRuntime.DEFAULT_HOST_AGENT_ID,
|
|
797
|
+
getThreadSummary: (threadId) => this.getSession(threadId),
|
|
798
|
+
});
|
|
1122
799
|
const binding = this.workspace.bindings.get(selectedAgentId);
|
|
1123
800
|
if (!binding) {
|
|
1124
801
|
throw new Error(`Unknown agent ${selectedAgentId}`);
|
|
@@ -1127,8 +804,8 @@ export class AgentHarnessRuntime {
|
|
|
1127
804
|
if (!policyDecision.allowed) {
|
|
1128
805
|
throw new Error(`Policy evaluation blocked agent ${selectedAgentId}: ${policyDecision.reasons.join(", ")}`);
|
|
1129
806
|
}
|
|
1130
|
-
const priority =
|
|
1131
|
-
const runRequest =
|
|
807
|
+
const priority = normalizeRunPriority(options.priority);
|
|
808
|
+
const runRequest = buildPersistedRunRequest(options.input, invocation, priority);
|
|
1132
809
|
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
1133
810
|
const runCreatedEventPromise = this.emitRunCreated(threadId, runId, {
|
|
1134
811
|
agentId: binding.agent.id,
|
|
@@ -1155,8 +832,15 @@ export class AgentHarnessRuntime {
|
|
|
1155
832
|
}
|
|
1156
833
|
}
|
|
1157
834
|
async *streamEvents(options) {
|
|
1158
|
-
const invocation =
|
|
1159
|
-
const selectedAgentId = await
|
|
835
|
+
const invocation = normalizeInvocationEnvelope(options);
|
|
836
|
+
const selectedAgentId = await resolveSelectedAgentId({
|
|
837
|
+
workspace: this.workspace,
|
|
838
|
+
input: options.input,
|
|
839
|
+
requestedAgentId: options.agentId,
|
|
840
|
+
threadId: options.threadId,
|
|
841
|
+
preferredHostAgentId: AgentHarnessRuntime.DEFAULT_HOST_AGENT_ID,
|
|
842
|
+
getThreadSummary: (threadId) => this.getSession(threadId),
|
|
843
|
+
});
|
|
1160
844
|
const binding = this.workspace.bindings.get(selectedAgentId);
|
|
1161
845
|
if (!binding) {
|
|
1162
846
|
const result = await this.run(options);
|
|
@@ -1173,8 +857,8 @@ export class AgentHarnessRuntime {
|
|
|
1173
857
|
}
|
|
1174
858
|
let emitted = false;
|
|
1175
859
|
let streamActivityObserved = false;
|
|
1176
|
-
const priority =
|
|
1177
|
-
const runRequest =
|
|
860
|
+
const priority = normalizeRunPriority(options.priority);
|
|
861
|
+
const runRequest = buildPersistedRunRequest(options.input, invocation, priority);
|
|
1178
862
|
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
1179
863
|
const priorHistoryPromise = Promise.resolve(isNewThread ? [] : undefined).then((historyHint) => historyHint ?? this.loadPriorHistory(threadId, runId));
|
|
1180
864
|
const runCreatedEventPromise = this.emitRunCreated(threadId, runId, {
|
|
@@ -1521,41 +1205,7 @@ export class AgentHarnessRuntime {
|
|
|
1521
1205
|
}
|
|
1522
1206
|
}
|
|
1523
1207
|
buildResumePayload(binding, approval, options) {
|
|
1524
|
-
|
|
1525
|
-
return options.decision === "edit" && options.editedInput
|
|
1526
|
-
? { decision: "edit", editedInput: options.editedInput }
|
|
1527
|
-
: (options.decision ?? "approve");
|
|
1528
|
-
}
|
|
1529
|
-
const decisionType = options.decision ?? "approve";
|
|
1530
|
-
if (decisionType === "edit" && options.editedInput) {
|
|
1531
|
-
return {
|
|
1532
|
-
decisions: [
|
|
1533
|
-
{
|
|
1534
|
-
type: "edit",
|
|
1535
|
-
editedAction: {
|
|
1536
|
-
name: approval.toolName,
|
|
1537
|
-
args: options.editedInput,
|
|
1538
|
-
},
|
|
1539
|
-
},
|
|
1540
|
-
],
|
|
1541
|
-
};
|
|
1542
|
-
}
|
|
1543
|
-
if (decisionType === "reject") {
|
|
1544
|
-
return {
|
|
1545
|
-
decisions: [
|
|
1546
|
-
{
|
|
1547
|
-
type: "reject",
|
|
1548
|
-
},
|
|
1549
|
-
],
|
|
1550
|
-
};
|
|
1551
|
-
}
|
|
1552
|
-
return {
|
|
1553
|
-
decisions: [
|
|
1554
|
-
{
|
|
1555
|
-
type: "approve",
|
|
1556
|
-
},
|
|
1557
|
-
],
|
|
1558
|
-
};
|
|
1208
|
+
return buildHarnessResumePayload(binding, approval, options);
|
|
1559
1209
|
}
|
|
1560
1210
|
async restartConversation(options) {
|
|
1561
1211
|
const thread = await this.getSession(options.threadId);
|
|
@@ -1598,7 +1248,7 @@ export class AgentHarnessRuntime {
|
|
|
1598
1248
|
if (!run) {
|
|
1599
1249
|
throw new Error(`Unknown run ${options.runId}`);
|
|
1600
1250
|
}
|
|
1601
|
-
if (
|
|
1251
|
+
if (isTerminalRunState(run.state)) {
|
|
1602
1252
|
return {
|
|
1603
1253
|
threadId: run.threadId,
|
|
1604
1254
|
runId: run.runId,
|
|
@@ -1647,7 +1297,7 @@ export class AgentHarnessRuntime {
|
|
|
1647
1297
|
});
|
|
1648
1298
|
continue;
|
|
1649
1299
|
}
|
|
1650
|
-
const releaseRunSlot = await this.acquireRunSlot(thread.threadId, thread.latestRunId, "running",
|
|
1300
|
+
const releaseRunSlot = await this.acquireRunSlot(thread.threadId, thread.latestRunId, "running", normalizeRunPriority(request.priority));
|
|
1651
1301
|
try {
|
|
1652
1302
|
await this.executeQueuedRun(binding, request.input, thread.threadId, thread.latestRunId, runMeta.agentId, {
|
|
1653
1303
|
context: request.invocation?.context,
|
|
@@ -1690,7 +1340,7 @@ export class AgentHarnessRuntime {
|
|
|
1690
1340
|
await this.persistence.releaseRunClaim(thread.latestRunId);
|
|
1691
1341
|
continue;
|
|
1692
1342
|
}
|
|
1693
|
-
const releaseRunSlot = await this.acquireRunSlot(thread.threadId, thread.latestRunId, "running",
|
|
1343
|
+
const releaseRunSlot = await this.acquireRunSlot(thread.threadId, thread.latestRunId, "running", normalizeRunPriority(request.priority));
|
|
1694
1344
|
try {
|
|
1695
1345
|
await this.emit(thread.threadId, thread.latestRunId, 100, "run.resumed", {
|
|
1696
1346
|
resumeKind: "startup-running-recovery",
|