@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
package/dist/runtime/harness.js
CHANGED
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
import { AUTO_AGENT_ID } from "../contracts/types.js";
|
|
2
1
|
import { SqlitePersistence } from "../persistence/sqlite-store.js";
|
|
3
2
|
import { createPersistentId } from "../utils/id.js";
|
|
4
3
|
import { AgentRuntimeAdapter } from "./agent-runtime-adapter.js";
|
|
5
|
-
import { createResourceBackendResolver, createResourceToolResolver } from "../resource/resource.js";
|
|
6
4
|
import { EventBus } from "./harness/events/event-bus.js";
|
|
5
|
+
import { createBackgroundEventRuntime } from "./harness/background-runtime.js";
|
|
7
6
|
import { PolicyEngine } from "./harness/system/policy-engine.js";
|
|
8
|
-
import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getRoutingRules,
|
|
7
|
+
import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getRoutingRules, } from "../workspace/support/workspace-ref-utils.js";
|
|
9
8
|
import { createHarnessEvent, inferRoutingBindings, renderRuntimeFailure, } from "./support/harness-support.js";
|
|
10
9
|
import { ThreadMemorySync } from "./harness/system/thread-memory-sync.js";
|
|
11
10
|
import { FileBackedStore } from "./harness/system/store.js";
|
|
12
11
|
import { HealthMonitor, readHealthMonitorConfig, } from "./harness/system/health-monitor.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
12
|
+
import { normalizeInvocationEnvelope, normalizeRunPriority, resolveRunListeners, } from "./harness/run/helpers.js";
|
|
13
|
+
import { emitHarnessEvent, } from "./harness/events/events.js";
|
|
14
|
+
import { createRuntimeEventOperations } from "./harness/events/runtime-event-operations.js";
|
|
15
|
+
import { finalizeCancelledRun as finalizeLifecycleCancelledRun, finalizeContinuedRun as finalizeLifecycleContinuedRun, } from "./harness/run/run-lifecycle.js";
|
|
16
|
+
import { createListenerDispatchRuntime } from "./harness/events/listener-runtime.js";
|
|
17
|
+
import { cancelRunOperation, executeQueuedRunOperation, resumeRun } from "./harness/run/run-operations.js";
|
|
18
|
+
import { createResumeRunRuntime } from "./harness/run/resume-runtime.js";
|
|
20
19
|
import { acquireRunSlot as acquireHarnessRunSlot } from "./harness/run/run-slot-acquisition.js";
|
|
21
20
|
import { dropPendingRunSlot, enqueuePendingRunSlot } from "./harness/run/run-queue.js";
|
|
22
|
-
import { getDefaultHostAgentId, resolveSelectedAgentId } from "./harness/run/routing.js";
|
|
23
|
-
import {
|
|
21
|
+
import { getDefaultHostAgentId, resolveSelectedAgentId, routeAgentId } from "./harness/run/routing.js";
|
|
22
|
+
import { resolveStoreFromConfig, } from "./harness/run/resources.js";
|
|
24
23
|
import { createToolMcpServerFromTools, serveToolsOverStdioFromHarness } from "../mcp.js";
|
|
25
|
-
import { getBindingAdapterKind
|
|
24
|
+
import { getBindingAdapterKind } from "./support/compiled-binding.js";
|
|
25
|
+
import { bindingSupportsRunningReplay, getWorkspaceBinding, resolveWorkspaceAgentTools, } from "./harness/bindings.js";
|
|
26
26
|
import { describeWorkspaceInventory, listAgentSkills as listWorkspaceAgentSkills, } from "./harness/system/inventory.js";
|
|
27
27
|
import { createDefaultHealthSnapshot, isInventoryEnabled, isThreadMemorySyncEnabled, } from "./harness/runtime-defaults.js";
|
|
28
|
-
import {
|
|
28
|
+
import { resolveRuntimeAdapterOptions } from "./support/runtime-adapter-options.js";
|
|
29
|
+
import { initializeHarnessRuntime, reclaimExpiredClaimedRuns as reclaimHarnessExpiredClaimedRuns, recoverStartupRuns as recoverHarnessStartupRuns, isStaleRunningRun as isHarnessStaleRunningRun, } from "./harness/run/startup-runtime.js";
|
|
29
30
|
import { streamHarnessRun } from "./harness/run/stream-run.js";
|
|
31
|
+
import { createStreamRunRuntime } from "./harness/run/stream-runtime.js";
|
|
32
|
+
import { defaultRequestedAgentId, prepareRunStart } from "./harness/run/start-run.js";
|
|
30
33
|
import { deleteThreadRecord, getPublicApproval, getThreadRecord, listPublicApprovals, } from "./harness/run/thread-records.js";
|
|
31
34
|
export class AgentHarnessRuntime {
|
|
32
35
|
workspace;
|
|
@@ -65,6 +68,10 @@ export class AgentHarnessRuntime {
|
|
|
65
68
|
pendingRunInsertionOrder = 0;
|
|
66
69
|
pendingRunSlots = [];
|
|
67
70
|
runtimeEventSequence = 0;
|
|
71
|
+
initialized = false;
|
|
72
|
+
closed = false;
|
|
73
|
+
backgroundEventRuntime;
|
|
74
|
+
runtimeEventOperations;
|
|
68
75
|
defaultRunRoot() {
|
|
69
76
|
return this.defaultRunRootValue;
|
|
70
77
|
}
|
|
@@ -96,22 +103,24 @@ export class AgentHarnessRuntime {
|
|
|
96
103
|
? this.defaultHostBinding.harnessRuntime.runtimeMemory.store
|
|
97
104
|
: undefined;
|
|
98
105
|
this.runtimeMemoryStore = resolveStoreFromConfig(this.stores, runtimeMemoryStoreConfig, runRoot) ?? this.defaultStore;
|
|
99
|
-
this.resolvedRuntimeAdapterOptions = {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
storeResolver: runtimeAdapterOptions.storeResolver ??
|
|
110
|
-
((binding) => resolveStore(this.stores, this.defaultStore, this.defaultRunRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding)),
|
|
111
|
-
backendResolver: runtimeAdapterOptions.backendResolver ??
|
|
112
|
-
((binding) => createResourceBackendResolver(workspace)(binding)),
|
|
113
|
-
};
|
|
106
|
+
this.resolvedRuntimeAdapterOptions = resolveRuntimeAdapterOptions({
|
|
107
|
+
workspace,
|
|
108
|
+
runtimeAdapterOptions,
|
|
109
|
+
checkpointers: this.checkpointers,
|
|
110
|
+
stores: this.stores,
|
|
111
|
+
defaultStore: this.defaultStore,
|
|
112
|
+
embeddingModels: this.embeddingModels,
|
|
113
|
+
vectorStores: this.vectorStores,
|
|
114
|
+
getDefaultRunRoot: () => this.defaultRunRoot(),
|
|
115
|
+
});
|
|
114
116
|
this.runtimeAdapter = new AgentRuntimeAdapter(this.resolvedRuntimeAdapterOptions);
|
|
117
|
+
this.backgroundEventRuntime = createBackgroundEventRuntime({
|
|
118
|
+
persistence: this.persistence,
|
|
119
|
+
publishEvent: (event) => this.eventBus.publish(event),
|
|
120
|
+
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
121
|
+
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
122
|
+
});
|
|
123
|
+
this.runtimeEventOperations = createRuntimeEventOperations(this.backgroundEventRuntime);
|
|
115
124
|
this.routingRules = getRoutingRules(workspace.refs);
|
|
116
125
|
this.routingDefaultAgentId = getRoutingDefaultAgentId(workspace.refs);
|
|
117
126
|
if (isThreadMemorySyncEnabled(workspace)) {
|
|
@@ -147,10 +156,18 @@ export class AgentHarnessRuntime {
|
|
|
147
156
|
this.healthMonitor?.recordLlmFailure(Date.now() - startedAt);
|
|
148
157
|
}
|
|
149
158
|
async initialize() {
|
|
159
|
+
if (this.closed) {
|
|
160
|
+
throw new Error("AgentHarnessRuntime has been closed and cannot be reinitialized");
|
|
161
|
+
}
|
|
162
|
+
if (this.initialized) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
150
165
|
await initializeHarnessRuntime({
|
|
151
166
|
persistence: this.persistence,
|
|
152
167
|
healthMonitor: this.healthMonitor,
|
|
153
168
|
});
|
|
169
|
+
await this.recoverStartupRuns();
|
|
170
|
+
this.initialized = true;
|
|
154
171
|
}
|
|
155
172
|
subscribe(listener) {
|
|
156
173
|
return this.eventBus.subscribe(listener);
|
|
@@ -161,23 +178,6 @@ export class AgentHarnessRuntime {
|
|
|
161
178
|
}
|
|
162
179
|
return createDefaultHealthSnapshot(this.activeRunSlots, this.pendingRunSlots.length);
|
|
163
180
|
}
|
|
164
|
-
resolveAgentTools(agentId) {
|
|
165
|
-
const binding = this.workspace.bindings.get(agentId);
|
|
166
|
-
if (!binding) {
|
|
167
|
-
throw new Error(`Unknown agent ${agentId}`);
|
|
168
|
-
}
|
|
169
|
-
const compiledTools = getBindingPrimaryTools(binding);
|
|
170
|
-
const resolver = this.resolvedRuntimeAdapterOptions.toolResolver;
|
|
171
|
-
const resolvedTools = resolver ? resolver(compiledTools.map((tool) => tool.id), binding) : [];
|
|
172
|
-
return compiledTools.map((compiledTool, index) => ({
|
|
173
|
-
compiledTool,
|
|
174
|
-
resolvedTool: resolvedTools[index],
|
|
175
|
-
}));
|
|
176
|
-
}
|
|
177
|
-
supportsRunningReplay(binding) {
|
|
178
|
-
const tools = getBindingPrimaryTools(binding);
|
|
179
|
-
return tools.every((tool) => tool.retryable === true);
|
|
180
|
-
}
|
|
181
181
|
async listThreads(filter) {
|
|
182
182
|
return this.persistence.listSessions(filter);
|
|
183
183
|
}
|
|
@@ -244,37 +244,21 @@ export class AgentHarnessRuntime {
|
|
|
244
244
|
}, threadId);
|
|
245
245
|
}
|
|
246
246
|
async createToolMcpServer(options) {
|
|
247
|
-
const tools = this.
|
|
248
|
-
compiledTool,
|
|
249
|
-
resolvedTool,
|
|
250
|
-
sourceTool: this.workspace.tools.get(compiledTool.id),
|
|
251
|
-
}));
|
|
247
|
+
const tools = this.resolveToolMcpServerTools(options.agentId);
|
|
252
248
|
return createToolMcpServerFromTools(tools, options);
|
|
253
249
|
}
|
|
254
250
|
async serveToolsOverStdio(options) {
|
|
255
|
-
const tools = this.
|
|
256
|
-
compiledTool,
|
|
257
|
-
resolvedTool,
|
|
258
|
-
sourceTool: this.workspace.tools.get(compiledTool.id),
|
|
259
|
-
}));
|
|
251
|
+
const tools = this.resolveToolMcpServerTools(options.agentId);
|
|
260
252
|
return serveToolsOverStdioFromHarness(tools, options);
|
|
261
253
|
}
|
|
262
254
|
async routeAgent(input, options = {}) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
const defaultBinding = this.routingDefaultAgentId
|
|
272
|
-
? this.workspace.bindings.get(this.routingDefaultAgentId)
|
|
273
|
-
: undefined;
|
|
274
|
-
if (defaultBinding) {
|
|
275
|
-
return defaultBinding.agent.id;
|
|
276
|
-
}
|
|
277
|
-
return this.getDefaultHostAgentId();
|
|
255
|
+
return routeAgentId({
|
|
256
|
+
workspace: this.workspace,
|
|
257
|
+
input,
|
|
258
|
+
routingRules: this.routingRules,
|
|
259
|
+
routingDefaultAgentId: this.routingDefaultAgentId,
|
|
260
|
+
threadId: options.threadId,
|
|
261
|
+
});
|
|
278
262
|
}
|
|
279
263
|
async emit(threadId, runId, sequence, eventType, payload, source = "runtime") {
|
|
280
264
|
return emitHarnessEvent({
|
|
@@ -290,55 +274,16 @@ export class AgentHarnessRuntime {
|
|
|
290
274
|
this.backgroundTasks.delete(task);
|
|
291
275
|
});
|
|
292
276
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
};
|
|
304
|
-
if (typeof this.persistence.bootstrapRun === "function") {
|
|
305
|
-
await this.persistence.bootstrapRun({
|
|
306
|
-
threadId,
|
|
307
|
-
agentId: binding.agent.id,
|
|
308
|
-
runId,
|
|
309
|
-
status: "running",
|
|
310
|
-
createdAt,
|
|
311
|
-
executionMode: getBindingAdapterKind(binding),
|
|
312
|
-
adapterKind: getBindingAdapterKind(binding),
|
|
313
|
-
userMessage,
|
|
314
|
-
runRequest,
|
|
315
|
-
createThread: isNewThread,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
if (isNewThread) {
|
|
320
|
-
await this.persistence.createThread({
|
|
321
|
-
threadId,
|
|
322
|
-
agentId: selectedAgentId,
|
|
323
|
-
runId,
|
|
324
|
-
status: "running",
|
|
325
|
-
createdAt,
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
await Promise.all([
|
|
329
|
-
this.persistence.appendThreadMessage(threadId, userMessage),
|
|
330
|
-
this.persistence.createRun({
|
|
331
|
-
threadId,
|
|
332
|
-
runId,
|
|
333
|
-
agentId: binding.agent.id,
|
|
334
|
-
executionMode: getBindingAdapterKind(binding),
|
|
335
|
-
adapterKind: getBindingAdapterKind(binding),
|
|
336
|
-
createdAt,
|
|
337
|
-
}),
|
|
338
|
-
this.persistence.saveRunRequest(threadId, runId, runRequest),
|
|
339
|
-
]);
|
|
340
|
-
}
|
|
341
|
-
return { threadId, runId, createdAt, isNewThread };
|
|
277
|
+
resolveToolMcpServerTools(agentId) {
|
|
278
|
+
return resolveWorkspaceAgentTools({
|
|
279
|
+
workspace: this.workspace,
|
|
280
|
+
agentId,
|
|
281
|
+
toolResolver: this.resolvedRuntimeAdapterOptions.toolResolver,
|
|
282
|
+
}).map(({ compiledTool, resolvedTool }) => ({
|
|
283
|
+
compiledTool,
|
|
284
|
+
resolvedTool,
|
|
285
|
+
sourceTool: this.workspace.tools.get(compiledTool.id),
|
|
286
|
+
}));
|
|
342
287
|
}
|
|
343
288
|
async loadPriorHistory(threadId, runId) {
|
|
344
289
|
const history = await this.persistence.listThreadMessages(threadId);
|
|
@@ -384,74 +329,33 @@ export class AgentHarnessRuntime {
|
|
|
384
329
|
return enqueuePendingRunSlot(this.pendingRunSlots, entry, this.pendingRunInsertionOrder++);
|
|
385
330
|
}
|
|
386
331
|
async executeQueuedRun(binding, input, threadId, runId, agentId, options = {}) {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
const actual = await this.invokeWithHistory(binding, input, threadId, runId, undefined, options.priorHistory, {
|
|
415
|
-
context: options.context,
|
|
416
|
-
state: options.state,
|
|
417
|
-
files: options.files,
|
|
418
|
-
});
|
|
419
|
-
const cancelledAfterInvoke = await this.getRunCancellation(runId);
|
|
420
|
-
if (cancelledAfterInvoke.requested) {
|
|
421
|
-
return this.finalizeCancelledRun(threadId, runId, previousState === "queued" ? "running" : previousState, cancelledAfterInvoke.reason);
|
|
422
|
-
}
|
|
423
|
-
const finalized = await this.finalizeContinuedRun(binding, threadId, runId, input, actual, {
|
|
424
|
-
previousState: previousState === "queued" ? "running" : previousState,
|
|
425
|
-
stateSequence: options.stateSequence ?? 103,
|
|
426
|
-
approvalSequence: options.approvalSequence ?? 104,
|
|
427
|
-
});
|
|
428
|
-
return {
|
|
429
|
-
...finalized,
|
|
430
|
-
agentId,
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
catch (error) {
|
|
434
|
-
await emitSyntheticFallbackEvent({
|
|
435
|
-
persistence: this.persistence,
|
|
436
|
-
publishEvent: (event) => this.eventBus.publish(event),
|
|
437
|
-
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
438
|
-
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
439
|
-
}, threadId, runId, agentId, error, 103);
|
|
440
|
-
await this.setRunStateAndEmit(threadId, runId, 104, "failed", {
|
|
441
|
-
previousState: previousState === "queued" ? "running" : previousState,
|
|
442
|
-
error: error instanceof Error ? error.message : String(error),
|
|
443
|
-
});
|
|
444
|
-
return {
|
|
445
|
-
threadId,
|
|
446
|
-
runId,
|
|
447
|
-
agentId,
|
|
448
|
-
state: "failed",
|
|
449
|
-
output: renderRuntimeFailure(error),
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
finally {
|
|
453
|
-
await this.persistence.clearRunRequest(threadId, runId);
|
|
454
|
-
}
|
|
332
|
+
return executeQueuedRunOperation({
|
|
333
|
+
persistence: this.persistence,
|
|
334
|
+
getRunCancellation: (currentRunId) => this.getRunCancellation(currentRunId),
|
|
335
|
+
finalizeCancelledRun: (currentThreadId, currentRunId, previousRunState, reason) => this.finalizeCancelledRun(currentThreadId, currentRunId, previousRunState, reason),
|
|
336
|
+
emit: (currentThreadId, currentRunId, sequence, eventType, payload) => {
|
|
337
|
+
if (eventType === "run.dequeued") {
|
|
338
|
+
return this.emit(currentThreadId, currentRunId, sequence, eventType, {
|
|
339
|
+
...payload,
|
|
340
|
+
activeRunCount: this.activeRunSlots,
|
|
341
|
+
maxConcurrentRuns: this.concurrencyConfig.maxConcurrentRuns,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return this.emit(currentThreadId, currentRunId, sequence, eventType, payload);
|
|
345
|
+
},
|
|
346
|
+
setRunStateAndEmit: (currentThreadId, currentRunId, sequence, state, stateOptions) => this.setRunStateAndEmit(currentThreadId, currentRunId, sequence, state, stateOptions),
|
|
347
|
+
invokeWithHistory: (activeBinding, activeInput, currentThreadId, currentRunId, resumePayload, priorHistory, invokeOptions) => this.invokeWithHistory(activeBinding, activeInput, currentThreadId, currentRunId, resumePayload, priorHistory, invokeOptions),
|
|
348
|
+
finalizeContinuedRun: (activeBinding, currentThreadId, currentRunId, currentInput, actual, finalizeOptions) => this.finalizeContinuedRun(activeBinding, currentThreadId, currentRunId, currentInput, actual, finalizeOptions),
|
|
349
|
+
emitSyntheticFallback: (currentThreadId, currentRunId, currentAgentId, error) => this.runtimeEventOperations.emitSyntheticFallback(currentThreadId, currentRunId, currentAgentId, error, 103),
|
|
350
|
+
renderRuntimeFailure,
|
|
351
|
+
}, {
|
|
352
|
+
binding,
|
|
353
|
+
message: input,
|
|
354
|
+
threadId,
|
|
355
|
+
runId,
|
|
356
|
+
agentId,
|
|
357
|
+
options,
|
|
358
|
+
});
|
|
455
359
|
}
|
|
456
360
|
async finalizeContinuedRun(binding, threadId, runId, input, actual, options) {
|
|
457
361
|
return finalizeLifecycleContinuedRun({
|
|
@@ -462,20 +366,10 @@ export class AgentHarnessRuntime {
|
|
|
462
366
|
}, binding, threadId, runId, input, actual, options);
|
|
463
367
|
}
|
|
464
368
|
async setRunStateAndEmit(threadId, runId, sequence, state, options) {
|
|
465
|
-
return
|
|
466
|
-
persistence: this.persistence,
|
|
467
|
-
publishEvent: (event) => this.eventBus.publish(event),
|
|
468
|
-
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
469
|
-
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
470
|
-
}, threadId, runId, sequence, state, options);
|
|
369
|
+
return this.runtimeEventOperations.setRunStateAndEmit(threadId, runId, sequence, state, options);
|
|
471
370
|
}
|
|
472
371
|
async requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence) {
|
|
473
|
-
return
|
|
474
|
-
persistence: this.persistence,
|
|
475
|
-
publishEvent: (event) => this.eventBus.publish(event),
|
|
476
|
-
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
477
|
-
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
478
|
-
}, threadId, runId, input, interruptContent, checkpointRef, sequence);
|
|
372
|
+
return this.runtimeEventOperations.requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence);
|
|
479
373
|
}
|
|
480
374
|
isDecisionRun(options) {
|
|
481
375
|
return "decision" in options;
|
|
@@ -486,55 +380,6 @@ export class AgentHarnessRuntime {
|
|
|
486
380
|
}
|
|
487
381
|
await listener(value);
|
|
488
382
|
}
|
|
489
|
-
async prepareRunStart(options, invocation, runCreatedPayload) {
|
|
490
|
-
const selectedAgentId = await this.resolveSelectedAgentId(options.input, options.agentId, options.threadId);
|
|
491
|
-
const binding = this.workspace.bindings.get(selectedAgentId);
|
|
492
|
-
if (!binding) {
|
|
493
|
-
throw new Error(`Unknown agent ${selectedAgentId}`);
|
|
494
|
-
}
|
|
495
|
-
const policyDecision = this.policyEngine.evaluate(binding);
|
|
496
|
-
if (!policyDecision.allowed) {
|
|
497
|
-
throw new Error(`Policy evaluation blocked agent ${selectedAgentId}: ${policyDecision.reasons.join(", ")}`);
|
|
498
|
-
}
|
|
499
|
-
const priority = normalizeRunPriority(options.priority);
|
|
500
|
-
const runRequest = buildPersistedRunRequest(options.input, invocation, priority);
|
|
501
|
-
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
502
|
-
return {
|
|
503
|
-
binding,
|
|
504
|
-
selectedAgentId,
|
|
505
|
-
priority,
|
|
506
|
-
threadId,
|
|
507
|
-
runId,
|
|
508
|
-
isNewThread,
|
|
509
|
-
runCreatedEventPromise: emitRunCreatedEvent({
|
|
510
|
-
persistence: this.persistence,
|
|
511
|
-
publishEvent: (event) => this.eventBus.publish(event),
|
|
512
|
-
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
513
|
-
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
514
|
-
}, threadId, runId, runCreatedPayload(binding, selectedAgentId)),
|
|
515
|
-
releaseRunSlotPromise: this.acquireRunSlot(threadId, runId, "running", priority),
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
createStartupRecoveryContext() {
|
|
519
|
-
return {
|
|
520
|
-
persistence: this.persistence,
|
|
521
|
-
workspace: this.workspace,
|
|
522
|
-
runtimeAdapter: this.runtimeAdapter,
|
|
523
|
-
recoveryConfig: this.recoveryConfig,
|
|
524
|
-
concurrencyConfig: this.concurrencyConfig,
|
|
525
|
-
getBinding: (agentId) => this.workspace.bindings.get(agentId),
|
|
526
|
-
acquireRunSlot: (threadId, runId, activeState = "running", priority = 0) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
527
|
-
executeQueuedRun: (binding, input, threadId, runId, agentId, options = {}) => this.executeQueuedRun(binding, input, threadId, runId, agentId, options),
|
|
528
|
-
setRunStateAndEmit: (threadId, runId, sequence, state, options) => this.setRunStateAndEmit(threadId, runId, sequence, state, options),
|
|
529
|
-
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
530
|
-
loadRunInput: (threadId, runId) => this.loadRunInput(threadId, runId),
|
|
531
|
-
finalizeContinuedRun: (binding, threadId, runId, input, actual, options) => this.finalizeContinuedRun(binding, threadId, runId, input, actual, options),
|
|
532
|
-
supportsRunningReplay: (binding) => this.supportsRunningReplay(binding),
|
|
533
|
-
isStaleRunningRun: (thread, nowMs = Date.now()) => this.isStaleRunningRun(thread, nowMs),
|
|
534
|
-
recordLlmSuccess: (startedAt) => this.recordLlmSuccess(startedAt),
|
|
535
|
-
recordLlmFailure: (startedAt) => this.recordLlmFailure(startedAt),
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
383
|
async acquireRunSlot(threadId, runId, activeState = "running", priority = 0) {
|
|
539
384
|
return acquireHarnessRunSlot({
|
|
540
385
|
persistence: this.persistence,
|
|
@@ -558,12 +403,6 @@ export class AgentHarnessRuntime {
|
|
|
558
403
|
dropPendingRunSlot(runId) {
|
|
559
404
|
return dropPendingRunSlot(this.pendingRunSlots, runId);
|
|
560
405
|
}
|
|
561
|
-
async dispatchRunListeners(stream, listeners) {
|
|
562
|
-
return dispatchStreamingRunListeners(stream, listeners, {
|
|
563
|
-
notifyListener: (listener, value) => this.notifyListener(listener, value),
|
|
564
|
-
getThread: (threadId) => this.getThread(threadId),
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
406
|
async run(options) {
|
|
568
407
|
if (this.isDecisionRun(options)) {
|
|
569
408
|
const resumeOptions = {
|
|
@@ -577,15 +416,29 @@ export class AgentHarnessRuntime {
|
|
|
577
416
|
}
|
|
578
417
|
const resolvedListeners = resolveRunListeners(options);
|
|
579
418
|
if (resolvedListeners) {
|
|
580
|
-
return
|
|
419
|
+
return createListenerDispatchRuntime({
|
|
420
|
+
notifyListener: (listener, value) => this.notifyListener(listener, value),
|
|
421
|
+
getThread: (threadId) => this.getThread(threadId),
|
|
422
|
+
}).dispatchRunListeners(this.streamEvents(options), resolvedListeners);
|
|
581
423
|
}
|
|
582
424
|
const invocation = normalizeInvocationEnvelope(options);
|
|
583
|
-
const { binding, selectedAgentId, threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
425
|
+
const { binding, selectedAgentId, threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await prepareRunStart({
|
|
426
|
+
workspace: this.workspace,
|
|
427
|
+
policyEngine: this.policyEngine,
|
|
428
|
+
persistence: this.persistence,
|
|
429
|
+
resolveSelectedAgentId: (input, requestedAgentId, threadId) => this.resolveSelectedAgentId(input, requestedAgentId, threadId),
|
|
430
|
+
emitRunCreated: (threadId, runId, payload) => this.runtimeEventOperations.emitRunCreated(threadId, runId, payload),
|
|
431
|
+
acquireRunSlot: (threadId, runId, activeState, priority) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
432
|
+
}, {
|
|
433
|
+
options,
|
|
434
|
+
invocation,
|
|
435
|
+
runCreatedPayload: (activeBinding, activeSelectedAgentId) => ({
|
|
436
|
+
agentId: activeBinding.agent.id,
|
|
437
|
+
requestedAgentId: defaultRequestedAgentId(options.agentId),
|
|
438
|
+
selectedAgentId: activeSelectedAgentId,
|
|
439
|
+
executionMode: getBindingAdapterKind(activeBinding),
|
|
440
|
+
}),
|
|
441
|
+
});
|
|
589
442
|
await runCreatedEventPromise;
|
|
590
443
|
const releaseRunSlot = await releaseRunSlotPromise;
|
|
591
444
|
try {
|
|
@@ -606,7 +459,7 @@ export class AgentHarnessRuntime {
|
|
|
606
459
|
async *streamEvents(options) {
|
|
607
460
|
const invocation = normalizeInvocationEnvelope(options);
|
|
608
461
|
const selectedAgentId = await this.resolveSelectedAgentId(options.input, options.agentId, options.threadId);
|
|
609
|
-
const binding = this.workspace
|
|
462
|
+
const binding = getWorkspaceBinding(this.workspace, selectedAgentId);
|
|
610
463
|
if (!binding) {
|
|
611
464
|
const result = await this.run(options);
|
|
612
465
|
for (const line of result.output.split("\n")) {
|
|
@@ -620,13 +473,34 @@ export class AgentHarnessRuntime {
|
|
|
620
473
|
}
|
|
621
474
|
return;
|
|
622
475
|
}
|
|
623
|
-
const { threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
476
|
+
const { threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await prepareRunStart({
|
|
477
|
+
workspace: this.workspace,
|
|
478
|
+
policyEngine: this.policyEngine,
|
|
479
|
+
persistence: this.persistence,
|
|
480
|
+
resolveSelectedAgentId: (input, requestedAgentId, threadId) => this.resolveSelectedAgentId(input, requestedAgentId, threadId),
|
|
481
|
+
emitRunCreated: (threadId, runId, payload) => this.runtimeEventOperations.emitRunCreated(threadId, runId, payload),
|
|
482
|
+
acquireRunSlot: (threadId, runId, activeState, priority) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
483
|
+
}, {
|
|
484
|
+
options,
|
|
485
|
+
invocation,
|
|
486
|
+
runCreatedPayload: (_binding, activeSelectedAgentId) => ({
|
|
487
|
+
agentId: activeSelectedAgentId,
|
|
488
|
+
requestedAgentId: defaultRequestedAgentId(options.agentId),
|
|
489
|
+
selectedAgentId: activeSelectedAgentId,
|
|
490
|
+
input: options.input,
|
|
491
|
+
state: "running",
|
|
492
|
+
}),
|
|
493
|
+
});
|
|
494
|
+
const streamRuntime = createStreamRunRuntime({
|
|
495
|
+
persistence: this.persistence,
|
|
496
|
+
runtimeAdapter: this.runtimeAdapter,
|
|
497
|
+
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
498
|
+
setRunStateAndEmit: (threadId, runId, sequence, state, stateOptions) => this.setRunStateAndEmit(threadId, runId, sequence, state, stateOptions),
|
|
499
|
+
requestApprovalAndEmit: (threadId, runId, input, interruptContent, checkpointRef, sequence) => this.requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence),
|
|
500
|
+
loadPriorHistory: (threadId, runId) => this.loadPriorHistory(threadId, runId),
|
|
501
|
+
invokeWithHistory: (binding, input, threadId, runId) => this.invokeWithHistory(binding, input, threadId, runId),
|
|
502
|
+
emitSyntheticFallback: (threadId, runId, selectedAgentId, error) => this.runtimeEventOperations.emitSyntheticFallback(threadId, runId, selectedAgentId, error),
|
|
503
|
+
});
|
|
630
504
|
yield* streamHarnessRun({
|
|
631
505
|
binding,
|
|
632
506
|
input: options.input,
|
|
@@ -637,45 +511,25 @@ export class AgentHarnessRuntime {
|
|
|
637
511
|
isNewThread,
|
|
638
512
|
runCreatedEventPromise,
|
|
639
513
|
releaseRunSlotPromise,
|
|
640
|
-
|
|
641
|
-
stream: (activeBinding, input, currentThreadId, priorHistory, streamOptions) => this.runtimeAdapter.stream(activeBinding, input, currentThreadId, priorHistory, streamOptions),
|
|
642
|
-
invokeWithHistory: (activeBinding, input, currentThreadId, currentRunId) => this.invokeWithHistory(activeBinding, input, currentThreadId, currentRunId),
|
|
643
|
-
emit: (currentThreadId, currentRunId, sequence, eventType, payload) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload),
|
|
644
|
-
setRunStateAndEmit: (currentThreadId, currentRunId, sequence, state, stateOptions) => this.setRunStateAndEmit(currentThreadId, currentRunId, sequence, state, stateOptions),
|
|
645
|
-
requestApprovalAndEmit: (currentThreadId, currentRunId, input, interruptContent, checkpointRef, sequence) => this.requestApprovalAndEmit(currentThreadId, currentRunId, input, interruptContent, checkpointRef, sequence),
|
|
646
|
-
appendAssistantMessage: (currentThreadId, currentRunId, content) => appendLifecycleAssistantMessage(this.persistence, currentThreadId, currentRunId, content),
|
|
647
|
-
clearRunRequest: (currentThreadId, currentRunId) => this.persistence.clearRunRequest(currentThreadId, currentRunId),
|
|
648
|
-
emitSyntheticFallback: (currentThreadId, currentRunId, currentSelectedAgentId, error) => emitSyntheticFallbackEvent({
|
|
649
|
-
persistence: this.persistence,
|
|
650
|
-
publishEvent: (event) => this.eventBus.publish(event),
|
|
651
|
-
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
652
|
-
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
653
|
-
}, currentThreadId, currentRunId, currentSelectedAgentId, error),
|
|
514
|
+
...streamRuntime,
|
|
654
515
|
});
|
|
655
516
|
}
|
|
656
517
|
async resume(options) {
|
|
657
|
-
return resumeRun({
|
|
658
|
-
|
|
518
|
+
return resumeRun(createResumeRunRuntime({
|
|
519
|
+
persistence: this.persistence,
|
|
520
|
+
workspace: this.workspace,
|
|
521
|
+
runtimeAdapter: this.runtimeAdapter,
|
|
659
522
|
getSession: (threadId) => this.getSession(threadId),
|
|
660
|
-
resolveApprovalRecord: (resumeOptions, thread) => resolveHarnessApprovalRecord(this.persistence, resumeOptions, thread),
|
|
661
|
-
getBinding: (agentId) => this.workspace.bindings.get(agentId),
|
|
662
|
-
buildResumePayload: (binding, approval, resumeOptions) => buildHarnessResumePayload(binding, approval, resumeOptions),
|
|
663
523
|
getRunCancellation: (runId) => this.getRunCancellation(runId),
|
|
664
524
|
finalizeCancelledRun: (threadId, runId, previousState, reason) => this.finalizeCancelledRun(threadId, runId, previousState, reason),
|
|
665
|
-
setRunState: (threadId, runId, state, checkpointRef) => this.persistence.setRunState(threadId, runId, state, checkpointRef),
|
|
666
525
|
acquireRunSlot: (threadId, runId, activeState, priority) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
667
526
|
resolvePersistedRunPriority: (threadId, runId) => this.resolvePersistedRunPriority(threadId, runId),
|
|
668
|
-
saveRecoveryIntent: (threadId, runId, payload) => this.persistence.saveRecoveryIntent(threadId, runId, payload),
|
|
669
527
|
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
670
|
-
resolveApproval: (threadId, runId, approvalId, resolution) => this.persistence.resolveApproval(threadId, runId, approvalId, resolution),
|
|
671
|
-
listThreadMessages: (threadId) => this.persistence.listThreadMessages(threadId),
|
|
672
528
|
loadRunInput: (threadId, runId) => this.loadRunInput(threadId, runId),
|
|
673
|
-
invoke: (binding, input, threadId, runId, resumePayload, priorHistory) => this.runtimeAdapter.invoke(binding, input, threadId, runId, resumePayload, priorHistory),
|
|
674
529
|
recordLlmSuccess: (startedAt) => this.recordLlmSuccess(startedAt),
|
|
675
530
|
recordLlmFailure: (startedAt) => this.recordLlmFailure(startedAt),
|
|
676
|
-
clearRecoveryIntent: (threadId, runId) => this.persistence.clearRecoveryIntent(threadId, runId),
|
|
677
531
|
finalizeContinuedRun: (binding, threadId, runId, input, actual, operationOptions) => this.finalizeContinuedRun(binding, threadId, runId, input, actual, operationOptions),
|
|
678
|
-
}, options);
|
|
532
|
+
}), options);
|
|
679
533
|
}
|
|
680
534
|
async restartConversation(options) {
|
|
681
535
|
const thread = await this.getSession(options.threadId);
|
|
@@ -703,10 +557,15 @@ export class AgentHarnessRuntime {
|
|
|
703
557
|
};
|
|
704
558
|
}
|
|
705
559
|
async close() {
|
|
560
|
+
if (this.closed) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
this.closed = true;
|
|
706
564
|
await this.healthMonitor?.stop();
|
|
707
565
|
this.unregisterThreadMemorySync();
|
|
708
566
|
await Promise.allSettled(Array.from(this.backgroundTasks));
|
|
709
567
|
await this.threadMemorySync?.close();
|
|
568
|
+
this.initialized = false;
|
|
710
569
|
}
|
|
711
570
|
async stop() {
|
|
712
571
|
await this.close();
|
|
@@ -721,10 +580,38 @@ export class AgentHarnessRuntime {
|
|
|
721
580
|
}, options);
|
|
722
581
|
}
|
|
723
582
|
async recoverStartupRuns() {
|
|
724
|
-
|
|
583
|
+
await recoverHarnessStartupRuns({
|
|
584
|
+
recoveryConfig: this.recoveryConfig,
|
|
585
|
+
persistence: this.persistence,
|
|
586
|
+
createStartupRecoveryContext: () => ({
|
|
587
|
+
persistence: this.persistence,
|
|
588
|
+
workspace: this.workspace,
|
|
589
|
+
runtimeAdapter: this.runtimeAdapter,
|
|
590
|
+
recoveryConfig: this.recoveryConfig,
|
|
591
|
+
concurrencyConfig: this.concurrencyConfig,
|
|
592
|
+
getBinding: (agentId) => getWorkspaceBinding(this.workspace, agentId),
|
|
593
|
+
acquireRunSlot: (threadId, runId, activeState, priority) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
594
|
+
executeQueuedRun: (binding, input, threadId, runId, agentId, options) => this.executeQueuedRun(binding, input, threadId, runId, agentId, options),
|
|
595
|
+
setRunStateAndEmit: (threadId, runId, sequence, state, options) => this.setRunStateAndEmit(threadId, runId, sequence, state, options),
|
|
596
|
+
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
597
|
+
loadRunInput: (threadId, runId) => this.loadRunInput(threadId, runId),
|
|
598
|
+
finalizeContinuedRun: (binding, threadId, runId, input, actual, options) => this.finalizeContinuedRun(binding, threadId, runId, input, actual, options),
|
|
599
|
+
supportsRunningReplay: (binding) => bindingSupportsRunningReplay(binding),
|
|
600
|
+
isStaleRunningRun: (thread, nowMs) => this.isStaleRunningRun(thread, nowMs),
|
|
601
|
+
recordLlmSuccess: (startedAt) => this.recordLlmSuccess(startedAt),
|
|
602
|
+
recordLlmFailure: (startedAt) => this.recordLlmFailure(startedAt),
|
|
603
|
+
}),
|
|
604
|
+
reclaimExpiredClaimedRuns: (nowIso) => this.reclaimExpiredClaimedRuns(nowIso),
|
|
605
|
+
});
|
|
725
606
|
}
|
|
726
|
-
async reclaimExpiredClaimedRuns(
|
|
727
|
-
|
|
607
|
+
async reclaimExpiredClaimedRuns(nowIso = new Date().toISOString()) {
|
|
608
|
+
await reclaimHarnessExpiredClaimedRuns({
|
|
609
|
+
persistence: this.persistence,
|
|
610
|
+
setRunStateAndEmit: (threadId, runId, sequence, state, options) => this.setRunStateAndEmit(threadId, runId, sequence, state, options),
|
|
611
|
+
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
612
|
+
concurrencyConfig: this.concurrencyConfig,
|
|
613
|
+
getActiveRunSlots: () => this.activeRunSlots,
|
|
614
|
+
}, nowIso);
|
|
728
615
|
}
|
|
729
616
|
async isStaleRunningRun(thread, nowMs = Date.now()) {
|
|
730
617
|
return isHarnessStaleRunningRun({
|