@botbotgo/agent-harness 0.0.108 → 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 +7 -0
- package/dist/runtime/adapter/execution-context.js +9 -2
- package/dist/runtime/adapter/middleware-assembly.js +2 -2
- package/dist/runtime/adapter/runnable-config.d.ts +44 -0
- package/dist/runtime/adapter/runnable-config.js +51 -0
- package/dist/runtime/adapter/runtime-adapter-support.d.ts +0 -1
- package/dist/runtime/adapter/runtime-adapter-support.js +1 -4
- package/dist/runtime/agent-runtime-adapter.js +3 -5
- 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 +4 -3
- package/dist/runtime/harness.js +177 -252
- 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 -13
- package/dist/runtime/adapter/deepagent-runnable-config.js +0 -29
- package/dist/runtime/adapter/langchain-runnable-config.d.ts +0 -11
- package/dist/runtime/adapter/langchain-runnable-config.js +0 -24
package/dist/runtime/harness.js
CHANGED
|
@@ -1,34 +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";
|
|
7
5
|
import { createBackgroundEventRuntime } from "./harness/background-runtime.js";
|
|
8
6
|
import { PolicyEngine } from "./harness/system/policy-engine.js";
|
|
9
|
-
import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getRoutingRules,
|
|
7
|
+
import { getConcurrencyConfig, getRecoveryConfig, getRoutingDefaultAgentId, getRoutingRules, } from "../workspace/support/workspace-ref-utils.js";
|
|
10
8
|
import { createHarnessEvent, inferRoutingBindings, renderRuntimeFailure, } from "./support/harness-support.js";
|
|
11
9
|
import { ThreadMemorySync } from "./harness/system/thread-memory-sync.js";
|
|
12
10
|
import { FileBackedStore } from "./harness/system/store.js";
|
|
13
11
|
import { HealthMonitor, readHealthMonitorConfig, } from "./harness/system/health-monitor.js";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
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";
|
|
21
19
|
import { acquireRunSlot as acquireHarnessRunSlot } from "./harness/run/run-slot-acquisition.js";
|
|
22
20
|
import { dropPendingRunSlot, enqueuePendingRunSlot } from "./harness/run/run-queue.js";
|
|
23
|
-
import { getDefaultHostAgentId, resolveSelectedAgentId } from "./harness/run/routing.js";
|
|
24
|
-
import {
|
|
21
|
+
import { getDefaultHostAgentId, resolveSelectedAgentId, routeAgentId } from "./harness/run/routing.js";
|
|
22
|
+
import { resolveStoreFromConfig, } from "./harness/run/resources.js";
|
|
25
23
|
import { createToolMcpServerFromTools, serveToolsOverStdioFromHarness } from "../mcp.js";
|
|
26
|
-
import { getBindingAdapterKind
|
|
27
|
-
import {
|
|
24
|
+
import { getBindingAdapterKind } from "./support/compiled-binding.js";
|
|
25
|
+
import { bindingSupportsRunningReplay, getWorkspaceBinding, resolveWorkspaceAgentTools, } from "./harness/bindings.js";
|
|
28
26
|
import { describeWorkspaceInventory, listAgentSkills as listWorkspaceAgentSkills, } from "./harness/system/inventory.js";
|
|
29
27
|
import { createDefaultHealthSnapshot, isInventoryEnabled, isThreadMemorySyncEnabled, } from "./harness/runtime-defaults.js";
|
|
30
|
-
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";
|
|
31
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";
|
|
32
33
|
import { deleteThreadRecord, getPublicApproval, getThreadRecord, listPublicApprovals, } from "./harness/run/thread-records.js";
|
|
33
34
|
export class AgentHarnessRuntime {
|
|
34
35
|
workspace;
|
|
@@ -67,7 +68,10 @@ export class AgentHarnessRuntime {
|
|
|
67
68
|
pendingRunInsertionOrder = 0;
|
|
68
69
|
pendingRunSlots = [];
|
|
69
70
|
runtimeEventSequence = 0;
|
|
71
|
+
initialized = false;
|
|
72
|
+
closed = false;
|
|
70
73
|
backgroundEventRuntime;
|
|
74
|
+
runtimeEventOperations;
|
|
71
75
|
defaultRunRoot() {
|
|
72
76
|
return this.defaultRunRootValue;
|
|
73
77
|
}
|
|
@@ -99,21 +103,16 @@ export class AgentHarnessRuntime {
|
|
|
99
103
|
? this.defaultHostBinding.harnessRuntime.runtimeMemory.store
|
|
100
104
|
: undefined;
|
|
101
105
|
this.runtimeMemoryStore = resolveStoreFromConfig(this.stores, runtimeMemoryStoreConfig, runRoot) ?? this.defaultStore;
|
|
102
|
-
this.resolvedRuntimeAdapterOptions = {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
storeResolver: runtimeAdapterOptions.storeResolver ??
|
|
113
|
-
((binding) => resolveStore(this.stores, this.defaultStore, this.defaultRunRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding)),
|
|
114
|
-
backendResolver: runtimeAdapterOptions.backendResolver ??
|
|
115
|
-
((binding) => createResourceBackendResolver(workspace)(binding)),
|
|
116
|
-
};
|
|
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
|
+
});
|
|
117
116
|
this.runtimeAdapter = new AgentRuntimeAdapter(this.resolvedRuntimeAdapterOptions);
|
|
118
117
|
this.backgroundEventRuntime = createBackgroundEventRuntime({
|
|
119
118
|
persistence: this.persistence,
|
|
@@ -121,6 +120,7 @@ export class AgentHarnessRuntime {
|
|
|
121
120
|
trackBackgroundTask: (task) => this.trackBackgroundTask(task),
|
|
122
121
|
backgroundEventTypes: AgentHarnessRuntime.BACKGROUND_EVENT_TYPES,
|
|
123
122
|
});
|
|
123
|
+
this.runtimeEventOperations = createRuntimeEventOperations(this.backgroundEventRuntime);
|
|
124
124
|
this.routingRules = getRoutingRules(workspace.refs);
|
|
125
125
|
this.routingDefaultAgentId = getRoutingDefaultAgentId(workspace.refs);
|
|
126
126
|
if (isThreadMemorySyncEnabled(workspace)) {
|
|
@@ -156,10 +156,18 @@ export class AgentHarnessRuntime {
|
|
|
156
156
|
this.healthMonitor?.recordLlmFailure(Date.now() - startedAt);
|
|
157
157
|
}
|
|
158
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
|
+
}
|
|
159
165
|
await initializeHarnessRuntime({
|
|
160
166
|
persistence: this.persistence,
|
|
161
167
|
healthMonitor: this.healthMonitor,
|
|
162
168
|
});
|
|
169
|
+
await this.recoverStartupRuns();
|
|
170
|
+
this.initialized = true;
|
|
163
171
|
}
|
|
164
172
|
subscribe(listener) {
|
|
165
173
|
return this.eventBus.subscribe(listener);
|
|
@@ -236,45 +244,21 @@ export class AgentHarnessRuntime {
|
|
|
236
244
|
}, threadId);
|
|
237
245
|
}
|
|
238
246
|
async createToolMcpServer(options) {
|
|
239
|
-
const tools =
|
|
240
|
-
workspace: this.workspace,
|
|
241
|
-
agentId: options.agentId,
|
|
242
|
-
toolResolver: this.resolvedRuntimeAdapterOptions.toolResolver,
|
|
243
|
-
}).map(({ compiledTool, resolvedTool }) => ({
|
|
244
|
-
compiledTool,
|
|
245
|
-
resolvedTool,
|
|
246
|
-
sourceTool: this.workspace.tools.get(compiledTool.id),
|
|
247
|
-
}));
|
|
247
|
+
const tools = this.resolveToolMcpServerTools(options.agentId);
|
|
248
248
|
return createToolMcpServerFromTools(tools, options);
|
|
249
249
|
}
|
|
250
250
|
async serveToolsOverStdio(options) {
|
|
251
|
-
const tools =
|
|
252
|
-
workspace: this.workspace,
|
|
253
|
-
agentId: options.agentId,
|
|
254
|
-
toolResolver: this.resolvedRuntimeAdapterOptions.toolResolver,
|
|
255
|
-
}).map(({ compiledTool, resolvedTool }) => ({
|
|
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
|
-
? getWorkspaceBinding(this.workspace, 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,71 +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
|
-
...this.backgroundEventRuntime,
|
|
436
|
-
}, threadId, runId, agentId, error, 103);
|
|
437
|
-
await this.setRunStateAndEmit(threadId, runId, 104, "failed", {
|
|
438
|
-
previousState: previousState === "queued" ? "running" : previousState,
|
|
439
|
-
error: error instanceof Error ? error.message : String(error),
|
|
440
|
-
});
|
|
441
|
-
return {
|
|
442
|
-
threadId,
|
|
443
|
-
runId,
|
|
444
|
-
agentId,
|
|
445
|
-
state: "failed",
|
|
446
|
-
output: renderRuntimeFailure(error),
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
finally {
|
|
450
|
-
await this.persistence.clearRunRequest(threadId, runId);
|
|
451
|
-
}
|
|
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
|
+
});
|
|
452
359
|
}
|
|
453
360
|
async finalizeContinuedRun(binding, threadId, runId, input, actual, options) {
|
|
454
361
|
return finalizeLifecycleContinuedRun({
|
|
@@ -459,14 +366,10 @@ export class AgentHarnessRuntime {
|
|
|
459
366
|
}, binding, threadId, runId, input, actual, options);
|
|
460
367
|
}
|
|
461
368
|
async setRunStateAndEmit(threadId, runId, sequence, state, options) {
|
|
462
|
-
return
|
|
463
|
-
...this.backgroundEventRuntime,
|
|
464
|
-
}, threadId, runId, sequence, state, options);
|
|
369
|
+
return this.runtimeEventOperations.setRunStateAndEmit(threadId, runId, sequence, state, options);
|
|
465
370
|
}
|
|
466
371
|
async requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence) {
|
|
467
|
-
return
|
|
468
|
-
...this.backgroundEventRuntime,
|
|
469
|
-
}, threadId, runId, input, interruptContent, checkpointRef, sequence);
|
|
372
|
+
return this.runtimeEventOperations.requestApprovalAndEmit(threadId, runId, input, interruptContent, checkpointRef, sequence);
|
|
470
373
|
}
|
|
471
374
|
isDecisionRun(options) {
|
|
472
375
|
return "decision" in options;
|
|
@@ -477,29 +380,6 @@ export class AgentHarnessRuntime {
|
|
|
477
380
|
}
|
|
478
381
|
await listener(value);
|
|
479
382
|
}
|
|
480
|
-
async prepareRunStart(options, invocation, runCreatedPayload) {
|
|
481
|
-
const selectedAgentId = await this.resolveSelectedAgentId(options.input, options.agentId, options.threadId);
|
|
482
|
-
const binding = getRequiredWorkspaceBinding(this.workspace, selectedAgentId);
|
|
483
|
-
const policyDecision = this.policyEngine.evaluate(binding);
|
|
484
|
-
if (!policyDecision.allowed) {
|
|
485
|
-
throw new Error(`Policy evaluation blocked agent ${selectedAgentId}: ${policyDecision.reasons.join(", ")}`);
|
|
486
|
-
}
|
|
487
|
-
const priority = normalizeRunPriority(options.priority);
|
|
488
|
-
const runRequest = buildPersistedRunRequest(options.input, invocation, priority);
|
|
489
|
-
const { threadId, runId, isNewThread } = await this.ensureThreadStarted(selectedAgentId, binding, options.input, runRequest, options.threadId);
|
|
490
|
-
return {
|
|
491
|
-
binding,
|
|
492
|
-
selectedAgentId,
|
|
493
|
-
priority,
|
|
494
|
-
threadId,
|
|
495
|
-
runId,
|
|
496
|
-
isNewThread,
|
|
497
|
-
runCreatedEventPromise: emitRunCreatedEvent({
|
|
498
|
-
...this.backgroundEventRuntime,
|
|
499
|
-
}, threadId, runId, runCreatedPayload(binding, selectedAgentId)),
|
|
500
|
-
releaseRunSlotPromise: this.acquireRunSlot(threadId, runId, "running", priority),
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
383
|
async acquireRunSlot(threadId, runId, activeState = "running", priority = 0) {
|
|
504
384
|
return acquireHarnessRunSlot({
|
|
505
385
|
persistence: this.persistence,
|
|
@@ -523,12 +403,6 @@ export class AgentHarnessRuntime {
|
|
|
523
403
|
dropPendingRunSlot(runId) {
|
|
524
404
|
return dropPendingRunSlot(this.pendingRunSlots, runId);
|
|
525
405
|
}
|
|
526
|
-
async dispatchRunListeners(stream, listeners) {
|
|
527
|
-
return dispatchStreamingRunListeners(stream, listeners, {
|
|
528
|
-
notifyListener: (listener, value) => this.notifyListener(listener, value),
|
|
529
|
-
getThread: (threadId) => this.getThread(threadId),
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
406
|
async run(options) {
|
|
533
407
|
if (this.isDecisionRun(options)) {
|
|
534
408
|
const resumeOptions = {
|
|
@@ -542,15 +416,29 @@ export class AgentHarnessRuntime {
|
|
|
542
416
|
}
|
|
543
417
|
const resolvedListeners = resolveRunListeners(options);
|
|
544
418
|
if (resolvedListeners) {
|
|
545
|
-
return
|
|
419
|
+
return createListenerDispatchRuntime({
|
|
420
|
+
notifyListener: (listener, value) => this.notifyListener(listener, value),
|
|
421
|
+
getThread: (threadId) => this.getThread(threadId),
|
|
422
|
+
}).dispatchRunListeners(this.streamEvents(options), resolvedListeners);
|
|
546
423
|
}
|
|
547
424
|
const invocation = normalizeInvocationEnvelope(options);
|
|
548
|
-
const { binding, selectedAgentId, threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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
|
+
});
|
|
554
442
|
await runCreatedEventPromise;
|
|
555
443
|
const releaseRunSlot = await releaseRunSlotPromise;
|
|
556
444
|
try {
|
|
@@ -585,13 +473,34 @@ export class AgentHarnessRuntime {
|
|
|
585
473
|
}
|
|
586
474
|
return;
|
|
587
475
|
}
|
|
588
|
-
const { threadId, runId, isNewThread, runCreatedEventPromise, releaseRunSlotPromise, } = await
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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
|
+
});
|
|
595
504
|
yield* streamHarnessRun({
|
|
596
505
|
binding,
|
|
597
506
|
input: options.input,
|
|
@@ -602,42 +511,25 @@ export class AgentHarnessRuntime {
|
|
|
602
511
|
isNewThread,
|
|
603
512
|
runCreatedEventPromise,
|
|
604
513
|
releaseRunSlotPromise,
|
|
605
|
-
|
|
606
|
-
stream: (activeBinding, input, currentThreadId, priorHistory, streamOptions) => this.runtimeAdapter.stream(activeBinding, input, currentThreadId, priorHistory, streamOptions),
|
|
607
|
-
invokeWithHistory: (activeBinding, input, currentThreadId, currentRunId) => this.invokeWithHistory(activeBinding, input, currentThreadId, currentRunId),
|
|
608
|
-
emit: (currentThreadId, currentRunId, sequence, eventType, payload) => this.emit(currentThreadId, currentRunId, sequence, eventType, payload),
|
|
609
|
-
setRunStateAndEmit: (currentThreadId, currentRunId, sequence, state, stateOptions) => this.setRunStateAndEmit(currentThreadId, currentRunId, sequence, state, stateOptions),
|
|
610
|
-
requestApprovalAndEmit: (currentThreadId, currentRunId, input, interruptContent, checkpointRef, sequence) => this.requestApprovalAndEmit(currentThreadId, currentRunId, input, interruptContent, checkpointRef, sequence),
|
|
611
|
-
appendAssistantMessage: (currentThreadId, currentRunId, content) => appendLifecycleAssistantMessage(this.persistence, currentThreadId, currentRunId, content),
|
|
612
|
-
clearRunRequest: (currentThreadId, currentRunId) => this.persistence.clearRunRequest(currentThreadId, currentRunId),
|
|
613
|
-
emitSyntheticFallback: (currentThreadId, currentRunId, currentSelectedAgentId, error) => emitSyntheticFallbackEvent({
|
|
614
|
-
...this.backgroundEventRuntime,
|
|
615
|
-
}, currentThreadId, currentRunId, currentSelectedAgentId, error),
|
|
514
|
+
...streamRuntime,
|
|
616
515
|
});
|
|
617
516
|
}
|
|
618
517
|
async resume(options) {
|
|
619
|
-
return resumeRun({
|
|
620
|
-
|
|
518
|
+
return resumeRun(createResumeRunRuntime({
|
|
519
|
+
persistence: this.persistence,
|
|
520
|
+
workspace: this.workspace,
|
|
521
|
+
runtimeAdapter: this.runtimeAdapter,
|
|
621
522
|
getSession: (threadId) => this.getSession(threadId),
|
|
622
|
-
resolveApprovalRecord: (resumeOptions, thread) => resolveHarnessApprovalRecord(this.persistence, resumeOptions, thread),
|
|
623
|
-
getBinding: (agentId) => getWorkspaceBinding(this.workspace, agentId),
|
|
624
|
-
buildResumePayload: (binding, approval, resumeOptions) => buildHarnessResumePayload(binding, approval, resumeOptions),
|
|
625
523
|
getRunCancellation: (runId) => this.getRunCancellation(runId),
|
|
626
524
|
finalizeCancelledRun: (threadId, runId, previousState, reason) => this.finalizeCancelledRun(threadId, runId, previousState, reason),
|
|
627
|
-
setRunState: (threadId, runId, state, checkpointRef) => this.persistence.setRunState(threadId, runId, state, checkpointRef),
|
|
628
525
|
acquireRunSlot: (threadId, runId, activeState, priority) => this.acquireRunSlot(threadId, runId, activeState, priority),
|
|
629
526
|
resolvePersistedRunPriority: (threadId, runId) => this.resolvePersistedRunPriority(threadId, runId),
|
|
630
|
-
saveRecoveryIntent: (threadId, runId, payload) => this.persistence.saveRecoveryIntent(threadId, runId, payload),
|
|
631
527
|
emit: (threadId, runId, sequence, eventType, payload) => this.emit(threadId, runId, sequence, eventType, payload),
|
|
632
|
-
resolveApproval: (threadId, runId, approvalId, resolution) => this.persistence.resolveApproval(threadId, runId, approvalId, resolution),
|
|
633
|
-
listThreadMessages: (threadId) => this.persistence.listThreadMessages(threadId),
|
|
634
528
|
loadRunInput: (threadId, runId) => this.loadRunInput(threadId, runId),
|
|
635
|
-
invoke: (binding, input, threadId, runId, resumePayload, priorHistory) => this.runtimeAdapter.invoke(binding, input, threadId, runId, resumePayload, priorHistory),
|
|
636
529
|
recordLlmSuccess: (startedAt) => this.recordLlmSuccess(startedAt),
|
|
637
530
|
recordLlmFailure: (startedAt) => this.recordLlmFailure(startedAt),
|
|
638
|
-
clearRecoveryIntent: (threadId, runId) => this.persistence.clearRecoveryIntent(threadId, runId),
|
|
639
531
|
finalizeContinuedRun: (binding, threadId, runId, input, actual, operationOptions) => this.finalizeContinuedRun(binding, threadId, runId, input, actual, operationOptions),
|
|
640
|
-
}, options);
|
|
532
|
+
}), options);
|
|
641
533
|
}
|
|
642
534
|
async restartConversation(options) {
|
|
643
535
|
const thread = await this.getSession(options.threadId);
|
|
@@ -665,10 +557,15 @@ export class AgentHarnessRuntime {
|
|
|
665
557
|
};
|
|
666
558
|
}
|
|
667
559
|
async close() {
|
|
560
|
+
if (this.closed) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
this.closed = true;
|
|
668
564
|
await this.healthMonitor?.stop();
|
|
669
565
|
this.unregisterThreadMemorySync();
|
|
670
566
|
await Promise.allSettled(Array.from(this.backgroundTasks));
|
|
671
567
|
await this.threadMemorySync?.close();
|
|
568
|
+
this.initialized = false;
|
|
672
569
|
}
|
|
673
570
|
async stop() {
|
|
674
571
|
await this.close();
|
|
@@ -683,10 +580,38 @@ export class AgentHarnessRuntime {
|
|
|
683
580
|
}, options);
|
|
684
581
|
}
|
|
685
582
|
async recoverStartupRuns() {
|
|
686
|
-
|
|
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
|
+
});
|
|
687
606
|
}
|
|
688
|
-
async reclaimExpiredClaimedRuns(
|
|
689
|
-
|
|
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);
|
|
690
615
|
}
|
|
691
616
|
async isStaleRunningRun(thread, nowMs = Date.now()) {
|
|
692
617
|
return isHarnessStaleRunningRun({
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CompiledAgentBinding, RuntimeAdapterOptions, WorkspaceBundle } from "../../contracts/types.js";
|
|
2
|
+
import type { StoreLike } from "../harness/system/store.js";
|
|
3
|
+
export declare function createBindingStoreResolver(input: {
|
|
4
|
+
stores: Map<string, StoreLike>;
|
|
5
|
+
defaultStore: StoreLike;
|
|
6
|
+
getDefaultRunRoot: () => string;
|
|
7
|
+
}): (binding?: CompiledAgentBinding) => StoreLike;
|
|
8
|
+
export declare function resolveRuntimeAdapterOptions(input: {
|
|
9
|
+
workspace: WorkspaceBundle;
|
|
10
|
+
runtimeAdapterOptions: RuntimeAdapterOptions;
|
|
11
|
+
checkpointers: Map<string, unknown>;
|
|
12
|
+
stores: Map<string, StoreLike>;
|
|
13
|
+
defaultStore: StoreLike;
|
|
14
|
+
embeddingModels: Map<string, unknown>;
|
|
15
|
+
vectorStores: Map<string, unknown>;
|
|
16
|
+
getDefaultRunRoot: () => string;
|
|
17
|
+
}): RuntimeAdapterOptions;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createResourceBackendResolver, createResourceToolResolver } from "../../resource/resource.js";
|
|
2
|
+
import { resolveCheckpointer, resolveEmbeddingModel, resolveStore, resolveVectorStore, } from "../harness/run/resources.js";
|
|
3
|
+
import { getBindingStoreConfig } from "./compiled-binding.js";
|
|
4
|
+
export function createBindingStoreResolver(input) {
|
|
5
|
+
return (binding) => resolveStore(input.stores, input.defaultStore, input.getDefaultRunRoot(), (currentBinding) => currentBinding ? getBindingStoreConfig(currentBinding) : undefined, binding);
|
|
6
|
+
}
|
|
7
|
+
export function resolveRuntimeAdapterOptions(input) {
|
|
8
|
+
const { workspace, runtimeAdapterOptions, checkpointers, stores, defaultStore, embeddingModels, vectorStores, getDefaultRunRoot, } = input;
|
|
9
|
+
const storeResolver = runtimeAdapterOptions.storeResolver ??
|
|
10
|
+
createBindingStoreResolver({
|
|
11
|
+
stores,
|
|
12
|
+
defaultStore,
|
|
13
|
+
getDefaultRunRoot,
|
|
14
|
+
});
|
|
15
|
+
return {
|
|
16
|
+
...runtimeAdapterOptions,
|
|
17
|
+
toolResolver: runtimeAdapterOptions.toolResolver ??
|
|
18
|
+
createResourceToolResolver(workspace, {
|
|
19
|
+
getStore: (binding) => binding ? storeResolver(binding) : defaultStore,
|
|
20
|
+
getEmbeddingModel: (embeddingModelRef) => resolveEmbeddingModel(workspace, embeddingModels, embeddingModelRef, runtimeAdapterOptions),
|
|
21
|
+
getVectorStore: (vectorStoreRef) => resolveVectorStore(workspace, vectorStores, vectorStoreRef, runtimeAdapterOptions),
|
|
22
|
+
}),
|
|
23
|
+
checkpointerResolver: runtimeAdapterOptions.checkpointerResolver ??
|
|
24
|
+
((binding) => resolveCheckpointer(checkpointers, binding)),
|
|
25
|
+
storeResolver,
|
|
26
|
+
backendResolver: runtimeAdapterOptions.backendResolver ??
|
|
27
|
+
((binding) => createResourceBackendResolver(workspace)(binding)),
|
|
28
|
+
};
|
|
29
|
+
}
|