@botbotgo/agent-harness 0.0.108 → 0.0.110

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.
Files changed (39) hide show
  1. package/dist/package-version.d.ts +1 -1
  2. package/dist/package-version.js +1 -1
  3. package/dist/runtime/adapter/execution-context.d.ts +7 -0
  4. package/dist/runtime/adapter/execution-context.js +9 -2
  5. package/dist/runtime/adapter/middleware-assembly.js +2 -2
  6. package/dist/runtime/adapter/runnable-config.d.ts +44 -0
  7. package/dist/runtime/adapter/runnable-config.js +51 -0
  8. package/dist/runtime/adapter/runtime-adapter-support.d.ts +0 -1
  9. package/dist/runtime/adapter/runtime-adapter-support.js +1 -4
  10. package/dist/runtime/agent-runtime-adapter.d.ts +1 -0
  11. package/dist/runtime/agent-runtime-adapter.js +37 -20
  12. package/dist/runtime/harness/events/listener-runtime.d.ts +18 -0
  13. package/dist/runtime/harness/events/listener-runtime.js +9 -0
  14. package/dist/runtime/harness/events/runtime-event-operations.d.ts +17 -0
  15. package/dist/runtime/harness/events/runtime-event-operations.js +9 -0
  16. package/dist/runtime/harness/run/recovery.d.ts +1 -1
  17. package/dist/runtime/harness/run/recovery.js +65 -47
  18. package/dist/runtime/harness/run/routing.d.ts +8 -0
  19. package/dist/runtime/harness/run/routing.js +21 -0
  20. package/dist/runtime/harness/run/run-operations.d.ts +47 -0
  21. package/dist/runtime/harness/run/run-operations.js +108 -6
  22. package/dist/runtime/harness/run/start-run.d.ts +82 -0
  23. package/dist/runtime/harness/run/start-run.js +88 -0
  24. package/dist/runtime/harness/run/startup-runtime.d.ts +2 -1
  25. package/dist/runtime/harness/run/startup-runtime.js +38 -3
  26. package/dist/runtime/harness.d.ts +5 -3
  27. package/dist/runtime/harness.js +163 -238
  28. package/dist/runtime/support/runtime-adapter-options.d.ts +17 -0
  29. package/dist/runtime/support/runtime-adapter-options.js +29 -0
  30. package/dist/workspace/agent-binding-compiler.js +24 -88
  31. package/dist/workspace/support/agent-capabilities.js +2 -6
  32. package/dist/workspace/support/agent-execution-config.d.ts +18 -0
  33. package/dist/workspace/support/agent-execution-config.js +35 -0
  34. package/dist/workspace/validate.js +6 -11
  35. package/package.json +1 -1
  36. package/dist/runtime/adapter/deepagent-runnable-config.d.ts +0 -13
  37. package/dist/runtime/adapter/deepagent-runnable-config.js +0 -29
  38. package/dist/runtime/adapter/langchain-runnable-config.d.ts +0 -11
  39. package/dist/runtime/adapter/langchain-runnable-config.js +0 -24
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.107";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.109";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.107";
1
+ export const AGENT_HARNESS_VERSION = "0.0.109";
@@ -1,6 +1,13 @@
1
1
  import type { CompiledAgentBinding, CompiledTool } from "../../contracts/types.js";
2
2
  import type { ToolNameMapping } from "./tool/tool-name-mapping.js";
3
3
  import { getBindingPrimaryModel } from "../support/compiled-binding.js";
4
+ export declare function buildBindingToolCatalog(input: {
5
+ binding: CompiledAgentBinding;
6
+ getToolNameMapping: (binding: CompiledAgentBinding) => ToolNameMapping;
7
+ }): {
8
+ primaryTools: CompiledTool[];
9
+ toolNameMapping: ToolNameMapping;
10
+ };
4
11
  export declare function buildBindingToolExecutionContext(input: {
5
12
  binding: CompiledAgentBinding;
6
13
  resolveTools: (tools: CompiledTool[], binding?: CompiledAgentBinding) => unknown[];
@@ -1,9 +1,16 @@
1
1
  import { buildExecutableToolMap } from "./tool-resolution.js";
2
2
  import { getBindingLangChainParams, getBindingPrimaryModel, getBindingPrimaryTools, isLangChainBinding } from "../support/compiled-binding.js";
3
- export function buildBindingToolExecutionContext(input) {
3
+ export function buildBindingToolCatalog(input) {
4
4
  const primaryTools = getBindingPrimaryTools(input.binding);
5
- const resolvedTools = input.resolveTools(primaryTools, input.binding);
6
5
  const toolNameMapping = input.getToolNameMapping(input.binding);
6
+ return {
7
+ primaryTools,
8
+ toolNameMapping,
9
+ };
10
+ }
11
+ export function buildBindingToolExecutionContext(input) {
12
+ const { primaryTools, toolNameMapping } = buildBindingToolCatalog(input);
13
+ const resolvedTools = input.resolveTools(primaryTools, input.binding);
7
14
  const executableTools = buildExecutableToolMap({
8
15
  primaryTools,
9
16
  resolvedTools,
@@ -4,7 +4,7 @@ import { createAgent, humanInTheLoopMiddleware } from "langchain";
4
4
  import { createBuiltinMiddlewareTools } from "./tool/builtin-middleware-tools.js";
5
5
  import { compileInterruptOn } from "./tool/interrupt-policy.js";
6
6
  import { extractToolFallbackContext, extractVisibleOutput } from "../parsing/output-parsing.js";
7
- import { hasConfiguredMiddlewareKind, hasConfiguredSubagentSupport, isObject, isRecord } from "./runtime-adapter-support.js";
7
+ import { hasConfiguredMiddlewareKind, hasConfiguredSubagentSupport, isRecord } from "./runtime-adapter-support.js";
8
8
  import { resolveDeclaredMiddleware } from "./tool/declared-middleware.js";
9
9
  import { getBindingDeepAgentParams, getBindingInterruptCompatibilityRules, getBindingLangChainParams, getBindingMiddlewareConfigs, getBindingPrimaryModel, isDeepAgentBinding, isLangChainBinding, } from "../support/compiled-binding.js";
10
10
  import { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths } from "./compat/deepagent-compat.js";
@@ -76,7 +76,7 @@ export async function invokeBuiltinTaskTool(input) {
76
76
  if (!params) {
77
77
  throw new Error(`Agent ${input.binding.agent.id} has no deepagent params`);
78
78
  }
79
- const typedInput = isObject(input.toolInput) ? input.toolInput : {};
79
+ const typedInput = isRecord(input.toolInput) ? input.toolInput : {};
80
80
  const description = typeof typedInput.description === "string" ? typedInput.description : "";
81
81
  const subagentType = typeof typedInput.subagent_type === "string" ? typedInput.subagent_type : "";
82
82
  const builtinBackend = input.resolveBuiltinMiddlewareBackend(input.binding, input.options);
@@ -5,9 +5,53 @@ export type ResolvedRunnableDependencies = {
5
5
  resolvedCheckpointer: unknown;
6
6
  resolvedStore: unknown;
7
7
  };
8
+ type LangChainRunnableConfigParams = {
9
+ langchainParams: {
10
+ passthrough?: Record<string, unknown>;
11
+ systemPrompt?: string;
12
+ stateSchema?: unknown;
13
+ responseFormat?: unknown;
14
+ contextSchema?: unknown;
15
+ includeAgentName?: unknown;
16
+ version?: unknown;
17
+ name?: unknown;
18
+ description?: unknown;
19
+ };
20
+ resolvedModel: unknown;
21
+ resolvedTools: unknown[];
22
+ resolvedMiddleware: unknown[];
23
+ resolvedCheckpointer: unknown;
24
+ resolvedStore: unknown;
25
+ passthroughOverride?: Record<string, unknown>;
26
+ systemPromptOverride?: string;
27
+ };
28
+ type DeepAgentRunnableConfigParams = {
29
+ compatibleParams: {
30
+ passthrough?: Record<string, unknown>;
31
+ systemPrompt?: string;
32
+ responseFormat?: unknown;
33
+ contextSchema?: unknown;
34
+ name?: unknown;
35
+ memory?: unknown;
36
+ generalPurposeAgent?: unknown;
37
+ taskDescription?: unknown;
38
+ };
39
+ resolvedModel: unknown;
40
+ resolvedTools: unknown[];
41
+ resolvedMiddleware: unknown[];
42
+ resolvedSubagents: unknown[];
43
+ resolvedCheckpointer: unknown;
44
+ resolvedStore: unknown;
45
+ resolvedBackend: unknown;
46
+ resolvedInterruptOn: unknown;
47
+ resolvedSkills: string[];
48
+ };
8
49
  export declare function buildResolvedRunnableConfig(params: {
9
50
  passthrough?: Record<string, unknown>;
10
51
  staticConfig?: Record<string, unknown>;
11
52
  resolved: ResolvedRunnableDependencies;
12
53
  extraConfig?: Record<string, unknown>;
13
54
  }): Record<string, unknown>;
55
+ export declare function buildLangChainRunnableConfig(params: LangChainRunnableConfigParams): Record<string, unknown>;
56
+ export declare function buildDeepAgentRunnableConfig(params: DeepAgentRunnableConfigParams): Record<string, unknown>;
57
+ export {};
@@ -11,3 +11,54 @@ export function buildResolvedRunnableConfig(params) {
11
11
  ...(extraConfig ?? {}),
12
12
  };
13
13
  }
14
+ export function buildLangChainRunnableConfig(params) {
15
+ const { langchainParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedCheckpointer, resolvedStore, passthroughOverride, systemPromptOverride, } = params;
16
+ return buildResolvedRunnableConfig({
17
+ passthrough: passthroughOverride ?? langchainParams.passthrough ?? {},
18
+ staticConfig: {
19
+ systemPrompt: systemPromptOverride ?? langchainParams.systemPrompt,
20
+ stateSchema: langchainParams.stateSchema,
21
+ responseFormat: langchainParams.responseFormat,
22
+ contextSchema: langchainParams.contextSchema,
23
+ includeAgentName: langchainParams.includeAgentName,
24
+ version: langchainParams.version,
25
+ name: langchainParams.name,
26
+ description: langchainParams.description,
27
+ },
28
+ resolved: {
29
+ resolvedModel,
30
+ resolvedTools,
31
+ resolvedMiddleware,
32
+ resolvedCheckpointer,
33
+ resolvedStore,
34
+ },
35
+ });
36
+ }
37
+ export function buildDeepAgentRunnableConfig(params) {
38
+ const { compatibleParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedSubagents, resolvedCheckpointer, resolvedStore, resolvedBackend, resolvedInterruptOn, resolvedSkills, } = params;
39
+ return buildResolvedRunnableConfig({
40
+ passthrough: compatibleParams.passthrough ?? {},
41
+ staticConfig: {
42
+ systemPrompt: compatibleParams.systemPrompt,
43
+ responseFormat: compatibleParams.responseFormat,
44
+ contextSchema: compatibleParams.contextSchema,
45
+ name: compatibleParams.name,
46
+ memory: compatibleParams.memory,
47
+ skills: resolvedSkills,
48
+ generalPurposeAgent: compatibleParams.generalPurposeAgent,
49
+ taskDescription: compatibleParams.taskDescription,
50
+ },
51
+ resolved: {
52
+ resolvedModel,
53
+ resolvedTools,
54
+ resolvedMiddleware,
55
+ resolvedCheckpointer,
56
+ resolvedStore,
57
+ },
58
+ extraConfig: {
59
+ subagents: resolvedSubagents,
60
+ backend: resolvedBackend,
61
+ interruptOn: resolvedInterruptOn,
62
+ },
63
+ });
64
+ }
@@ -1,6 +1,5 @@
1
1
  import type { CompiledAgentBinding } from "../../contracts/types.js";
2
2
  export declare function countConfiguredTools(binding: CompiledAgentBinding): number;
3
- export declare function asObject(value: unknown): Record<string, unknown> | undefined;
4
3
  export declare function sleep(ms: number): Promise<void>;
5
4
  export declare function hasConfiguredSubagentSupport(binding: CompiledAgentBinding): boolean;
6
5
  export declare function hasConfiguredMiddlewareKind(binding: CompiledAgentBinding, kind: string): boolean;
@@ -2,9 +2,6 @@ import { getBindingExecutionView } from "../support/compiled-binding.js";
2
2
  export function countConfiguredTools(binding) {
3
3
  return getBindingExecutionView(binding).primaryTools.length;
4
4
  }
5
- export function asObject(value) {
6
- return typeof value === "object" && value ? value : undefined;
7
- }
8
5
  export function sleep(ms) {
9
6
  return new Promise((resolve) => setTimeout(resolve, ms));
10
7
  }
@@ -34,7 +31,7 @@ export function truncateLines(lines, maxChars = 12_000) {
34
31
  export function summarizeBuiltinWriteTodosArgs(args) {
35
32
  const todos = Array.isArray(args.todos) ? args.todos : [];
36
33
  const items = todos.flatMap((todo) => {
37
- if (!isObject(todo)) {
34
+ if (!isRecord(todo)) {
38
35
  return [];
39
36
  }
40
37
  const content = typeof todo.content === "string" && todo.content.trim().length > 0
@@ -30,6 +30,7 @@ export declare class AgentRuntimeAdapter {
30
30
  private resolveFilesystemBackend;
31
31
  private resolveBuiltinMiddlewareBackend;
32
32
  private createDeclaredMiddlewareResolverOptions;
33
+ private createAssemblyResolvers;
33
34
  private invokeBuiltinTaskTool;
34
35
  private resolveBuiltinMiddlewareTools;
35
36
  private resolveAutomaticSummarizationMiddleware;
@@ -8,8 +8,7 @@ import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
8
8
  import { finalizeInvocationResult } from "./adapter/invocation-result.js";
9
9
  import { invokeRuntimeWithLocalTools } from "./adapter/invoke-runtime.js";
10
10
  import { streamRuntimeExecution } from "./adapter/stream-runtime.js";
11
- import { buildDeepAgentRunnableConfig } from "./adapter/deepagent-runnable-config.js";
12
- import { buildLangChainRunnableConfig } from "./adapter/langchain-runnable-config.js";
11
+ import { buildDeepAgentRunnableConfig, buildLangChainRunnableConfig } from "./adapter/runnable-config.js";
13
12
  import { applyStrictToolJsonInstruction as applyStrictToolJsonInstructionHelper, callRuntimeWithToolParseRecovery as callRuntimeWithToolParseRecoveryHelper, createModelFallbackRunnable as createModelFallbackRunnableHelper, invokeWithProviderRetry as invokeWithProviderRetryHelper, iterateWithTimeout as iterateWithTimeoutHelper, materializeModelStream as materializeModelStreamHelper, RuntimeOperationTimeoutError, withRuntimeTimeout, } from "./adapter/runtime-shell.js";
14
13
  import { invokeBuiltinTaskTool as invokeBuiltinTaskToolHelper, resolveAutomaticSummarizationMiddleware as resolveAutomaticSummarizationMiddlewareHelper, resolveBuiltinMiddlewareBackend as resolveBuiltinMiddlewareBackendHelper, resolveBuiltinMiddlewareTools as resolveBuiltinMiddlewareToolsHelper, resolveLangChainAutomaticMiddleware as resolveLangChainAutomaticMiddlewareHelper, resolveMiddleware as resolveMiddlewareHelper, resolveSubagents as resolveSubagentsHelper, } from "./adapter/middleware-assembly.js";
15
14
  import { computeRemainingTimeoutMs, resolveBindingTimeout, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
@@ -18,7 +17,7 @@ import { buildInvocationRequest, } from "./adapter/model/invocation-request.js";
18
17
  import { compileInterruptOn } from "./adapter/tool/interrupt-policy.js";
19
18
  import { countConfiguredTools, } from "./adapter/runtime-adapter-support.js";
20
19
  import { resolveAdapterTools } from "./adapter/tool-resolution.js";
21
- import { buildBindingToolExecutionContext, resolveLangChainStreamContext } from "./adapter/execution-context.js";
20
+ import { buildBindingToolCatalog, buildBindingToolExecutionContext, resolveLangChainStreamContext, } from "./adapter/execution-context.js";
22
21
  export { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths, relativizeDeepAgentSkillSourcePaths, shouldRelaxDeepAgentDelegationPrompt, } from "./adapter/compat/deepagent-compat.js";
23
22
  export { buildAuthOmittingFetch, normalizeOpenAICompatibleInit } from "./adapter/compat/openai-compatible.js";
24
23
  export { buildToolNameMapping, createModelFacingToolNameCandidates, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, sanitizeToolNameForModel, } from "./adapter/tool/tool-name-mapping.js";
@@ -150,57 +149,76 @@ export class AgentRuntimeAdapter {
150
149
  binding,
151
150
  };
152
151
  }
152
+ createAssemblyResolvers(binding, options = {}) {
153
+ return {
154
+ resolveModel: (model) => this.resolveModel(model),
155
+ resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
156
+ resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding),
157
+ createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
158
+ resolveBuiltinMiddlewareBackend: (currentBinding, currentOptions = {}) => this.resolveBuiltinMiddlewareBackend(currentBinding, currentOptions),
159
+ resolveSubagents: (subagents, currentBinding) => this.resolveSubagents(subagents, currentBinding),
160
+ invokeBuiltinTaskTool: (currentBinding, toolInput, currentOptions = {}) => this.invokeBuiltinTaskTool(currentBinding, toolInput, currentOptions),
161
+ binding,
162
+ options,
163
+ };
164
+ }
153
165
  async invokeBuiltinTaskTool(binding, input, options = {}) {
166
+ const assembly = this.createAssemblyResolvers(binding, options);
154
167
  return invokeBuiltinTaskToolHelper({
155
168
  binding,
156
169
  toolInput: input,
157
170
  options,
158
- resolveBuiltinMiddlewareBackend: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareBackend(currentBinding, currentOptions),
159
- resolveSubagents: (subagents, currentBinding) => this.resolveSubagents(subagents, currentBinding),
160
- resolveModel: (model) => this.resolveModel(model),
161
- resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
171
+ resolveBuiltinMiddlewareBackend: assembly.resolveBuiltinMiddlewareBackend,
172
+ resolveSubagents: assembly.resolveSubagents,
173
+ resolveModel: assembly.resolveModel,
174
+ resolveTools: assembly.resolveTools,
162
175
  });
163
176
  }
164
177
  async resolveBuiltinMiddlewareTools(binding, options = {}) {
178
+ const assembly = this.createAssemblyResolvers(binding, options);
165
179
  return resolveBuiltinMiddlewareToolsHelper({
166
180
  binding,
167
181
  options,
168
- resolveBuiltinMiddlewareBackend: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareBackend(currentBinding, currentOptions),
169
- invokeBuiltinTaskTool: (currentBinding, toolInput, currentOptions) => this.invokeBuiltinTaskTool(currentBinding, toolInput, currentOptions),
182
+ resolveBuiltinMiddlewareBackend: assembly.resolveBuiltinMiddlewareBackend,
183
+ invokeBuiltinTaskTool: assembly.invokeBuiltinTaskTool,
170
184
  });
171
185
  }
172
186
  async resolveAutomaticSummarizationMiddleware(binding) {
187
+ const assembly = this.createAssemblyResolvers(binding);
173
188
  return resolveAutomaticSummarizationMiddlewareHelper({
174
189
  binding,
175
- createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
190
+ createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
176
191
  });
177
192
  }
178
193
  async resolveLangChainAutomaticMiddleware(binding) {
194
+ const assembly = this.createAssemblyResolvers(binding);
179
195
  return resolveLangChainAutomaticMiddlewareHelper({
180
196
  binding,
181
197
  resolveAutomaticSummarizationMiddleware: (currentBinding) => this.resolveAutomaticSummarizationMiddleware(currentBinding),
182
- resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding),
183
- resolveModel: (model) => this.resolveModel(model),
184
- resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
185
- resolveSubagents: (subagents, currentBinding) => this.resolveSubagents(subagents, currentBinding),
198
+ resolveFilesystemBackend: assembly.resolveFilesystemBackend,
199
+ resolveModel: assembly.resolveModel,
200
+ resolveTools: assembly.resolveTools,
201
+ resolveSubagents: assembly.resolveSubagents,
186
202
  });
187
203
  }
188
204
  async resolveMiddleware(binding, interruptOn) {
205
+ const assembly = this.createAssemblyResolvers(binding);
189
206
  return resolveMiddlewareHelper({
190
207
  binding,
191
208
  interruptOn,
192
209
  runtimeAdapterOptions: this.options,
193
- createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
210
+ createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
194
211
  resolveLangChainAutomaticMiddleware: (currentBinding) => this.resolveLangChainAutomaticMiddleware(currentBinding),
195
212
  });
196
213
  }
197
214
  async resolveSubagents(subagents, binding) {
215
+ const assembly = this.createAssemblyResolvers(binding);
198
216
  return resolveSubagentsHelper({
199
217
  subagents,
200
218
  binding,
201
- resolveModel: (model) => this.resolveModel(model),
202
- resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
203
- createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
219
+ resolveModel: assembly.resolveModel,
220
+ resolveTools: assembly.resolveTools,
221
+ createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
204
222
  });
205
223
  }
206
224
  async createLangChainRunnable(binding, options = {}) {
@@ -324,9 +342,8 @@ export class AgentRuntimeAdapter {
324
342
  const invokeTimeoutMs = resolveBindingTimeout(binding);
325
343
  const streamIdleTimeoutMs = resolveStreamIdleTimeout(binding);
326
344
  const streamDeadlineAt = invokeTimeoutMs ? Date.now() + invokeTimeoutMs : undefined;
327
- const { primaryTools, toolNameMapping } = buildBindingToolExecutionContext({
345
+ const { primaryTools, toolNameMapping } = buildBindingToolCatalog({
328
346
  binding,
329
- resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
330
347
  getToolNameMapping: (currentBinding) => this.getToolNameMapping(currentBinding),
331
348
  });
332
349
  const { forceInvokeFallback, canUseDirectModelStream, langChainStreamModel, } = await resolveLangChainStreamContext({
@@ -0,0 +1,18 @@
1
+ import type { HarnessStreamItem, RunListeners, RunResult } from "../../../contracts/types.js";
2
+ export declare function createListenerDispatchRuntime(input: {
3
+ notifyListener: <T>(listener: ((value: T) => void | Promise<void>) | undefined, value: T) => Promise<void>;
4
+ getThread: (threadId: string) => Promise<{
5
+ currentState: RunResult["state"];
6
+ latestRunId: string;
7
+ entryAgentId: string;
8
+ runs: Array<{
9
+ agentId: string;
10
+ }>;
11
+ pendingDecision?: {
12
+ approvalId?: string;
13
+ pendingActionId?: string;
14
+ };
15
+ } | null>;
16
+ }): {
17
+ dispatchRunListeners: (stream: AsyncGenerator<HarnessStreamItem>, listeners: RunListeners) => Promise<RunResult>;
18
+ };
@@ -0,0 +1,9 @@
1
+ import { dispatchRunListeners as dispatchStreamingRunListeners } from "./streaming.js";
2
+ export function createListenerDispatchRuntime(input) {
3
+ return {
4
+ dispatchRunListeners: (stream, listeners) => dispatchStreamingRunListeners(stream, listeners, {
5
+ notifyListener: (listener, value) => input.notifyListener(listener, value),
6
+ getThread: (threadId) => input.getThread(threadId),
7
+ }),
8
+ };
9
+ }
@@ -0,0 +1,17 @@
1
+ import type { HarnessEvent, MessageContent, RunResult } from "../../../contracts/types.js";
2
+ import { emitRunCreatedEvent } from "./events.js";
3
+ type EventRuntime = Parameters<typeof emitRunCreatedEvent>[0];
4
+ export declare function createRuntimeEventOperations(runtime: EventRuntime): {
5
+ emitRunCreated: (threadId: string, runId: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
6
+ setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
7
+ previousState: string | null;
8
+ checkpointRef?: string | null;
9
+ error?: string;
10
+ }) => Promise<HarnessEvent>;
11
+ requestApprovalAndEmit: (threadId: string, runId: string, input: MessageContent, interruptContent: string | undefined, checkpointRef: string, sequence: number) => Promise<{
12
+ approval: import("../../../contracts/runtime.js").InternalApprovalRecord;
13
+ event: HarnessEvent;
14
+ }>;
15
+ emitSyntheticFallback: (threadId: string, runId: string, selectedAgentId: string, error: unknown, sequence?: number) => Promise<void>;
16
+ };
17
+ export {};
@@ -0,0 +1,9 @@
1
+ import { emitRunCreatedEvent, emitSyntheticFallbackEvent, requestApprovalAndEmitEvent, setRunStateAndEmitEvent } from "./events.js";
2
+ export function createRuntimeEventOperations(runtime) {
3
+ return {
4
+ emitRunCreated: (threadId, runId, payload) => emitRunCreatedEvent(runtime, threadId, runId, payload),
5
+ setRunStateAndEmit: (threadId, runId, sequence, state, options) => setRunStateAndEmitEvent(runtime, threadId, runId, sequence, state, options),
6
+ requestApprovalAndEmit: (threadId, runId, input, interruptContent, checkpointRef, sequence) => requestApprovalAndEmitEvent(runtime, threadId, runId, input, interruptContent, checkpointRef, sequence),
7
+ emitSyntheticFallback: (threadId, runId, selectedAgentId, error, sequence) => emitSyntheticFallbackEvent(runtime, threadId, runId, selectedAgentId, error, sequence),
8
+ };
9
+ }
@@ -3,7 +3,7 @@ import type { RuntimePersistence } from "../../../persistence/types.js";
3
3
  import type { AgentRuntimeAdapter } from "../../agent-runtime-adapter.js";
4
4
  import type { ConcurrencyConfig, RecoveryConfig } from "../../../workspace/support/workspace-ref-utils.js";
5
5
  type RecoveryBinding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
6
- type StartupRecoveryContext = {
6
+ export type StartupRecoveryContext = {
7
7
  persistence: RuntimePersistence;
8
8
  workspace: WorkspaceBundle;
9
9
  runtimeAdapter: AgentRuntimeAdapter;
@@ -1,28 +1,37 @@
1
1
  import { normalizeRunPriority } from "./helpers.js";
2
- export async function recoverQueuedStartupRun(context, thread) {
3
- if (thread.status !== "queued") {
4
- return false;
2
+ async function failRecovery(context, thread, previousState, error, options = {}) {
3
+ await context.setRunStateAndEmit(thread.threadId, thread.latestRunId, 100, "failed", {
4
+ previousState,
5
+ error,
6
+ });
7
+ if (options.releaseRunClaim) {
8
+ await context.persistence.releaseRunClaim(thread.latestRunId);
5
9
  }
10
+ return true;
11
+ }
12
+ async function resolveRecoveryBinding(context, thread) {
6
13
  const runMeta = await context.persistence.getRunMeta(thread.threadId, thread.latestRunId);
7
14
  const binding = context.getBinding(runMeta.agentId);
8
15
  if (!binding) {
9
- return true;
10
- }
11
- const request = await context.persistence.getRunRequest(thread.threadId, thread.latestRunId);
12
- if (!request) {
13
- await context.setRunStateAndEmit(thread.threadId, thread.latestRunId, 100, "failed", {
14
- previousState: "queued",
15
- error: "missing persisted run request for queued run recovery",
16
- });
17
- return true;
16
+ return null;
18
17
  }
18
+ return {
19
+ binding,
20
+ agentId: runMeta.agentId,
21
+ };
22
+ }
23
+ async function executeRecoveredRun(context, input) {
24
+ const { thread, binding, agentId, request, previousState, emitResumeEvent } = input;
19
25
  const releaseRunSlot = await context.acquireRunSlot(thread.threadId, thread.latestRunId, "running", normalizeRunPriority(request.priority));
20
26
  try {
21
- await context.executeQueuedRun(binding, request.input, thread.threadId, thread.latestRunId, runMeta.agentId, {
27
+ if (emitResumeEvent) {
28
+ await context.emit(thread.threadId, thread.latestRunId, emitResumeEvent.sequence, emitResumeEvent.eventType, emitResumeEvent.payload);
29
+ }
30
+ await context.executeQueuedRun(binding, request.input, thread.threadId, thread.latestRunId, agentId, {
22
31
  context: request.invocation?.context,
23
32
  state: request.invocation?.inputs,
24
33
  files: request.invocation?.attachments,
25
- previousState: "queued",
34
+ previousState,
26
35
  stateSequence: 103,
27
36
  approvalSequence: 104,
28
37
  });
@@ -32,6 +41,26 @@ export async function recoverQueuedStartupRun(context, thread) {
32
41
  }
33
42
  return true;
34
43
  }
44
+ export async function recoverQueuedStartupRun(context, thread) {
45
+ if (thread.status !== "queued") {
46
+ return false;
47
+ }
48
+ const resolved = await resolveRecoveryBinding(context, thread);
49
+ if (!resolved) {
50
+ return true;
51
+ }
52
+ const request = await context.persistence.getRunRequest(thread.threadId, thread.latestRunId);
53
+ if (!request) {
54
+ return failRecovery(context, thread, "queued", "missing persisted run request for queued run recovery");
55
+ }
56
+ return executeRecoveredRun(context, {
57
+ thread,
58
+ binding: resolved.binding,
59
+ agentId: resolved.agentId,
60
+ request,
61
+ previousState: "queued",
62
+ });
63
+ }
35
64
  export async function recoverRunningStartupRun(context, thread) {
36
65
  if (thread.status !== "running") {
37
66
  return false;
@@ -40,47 +69,36 @@ export async function recoverRunningStartupRun(context, thread) {
40
69
  if (!isStale) {
41
70
  return true;
42
71
  }
43
- const runMeta = await context.persistence.getRunMeta(thread.threadId, thread.latestRunId);
44
- const binding = context.getBinding(runMeta.agentId);
45
- if (!binding) {
72
+ const resolved = await resolveRecoveryBinding(context, thread);
73
+ if (!resolved) {
46
74
  return true;
47
75
  }
48
- if (!context.supportsRunningReplay(binding)) {
49
- await context.setRunStateAndEmit(thread.threadId, thread.latestRunId, 100, "failed", {
50
- previousState: "running",
51
- error: "stale running run cannot be replayed safely",
76
+ if (!context.supportsRunningReplay(resolved.binding)) {
77
+ return failRecovery(context, thread, "running", "stale running run cannot be replayed safely", {
78
+ releaseRunClaim: true,
52
79
  });
53
- await context.persistence.releaseRunClaim(thread.latestRunId);
54
- return true;
55
80
  }
56
81
  const request = await context.persistence.getRunRequest(thread.threadId, thread.latestRunId);
57
82
  if (!request) {
58
- await context.setRunStateAndEmit(thread.threadId, thread.latestRunId, 100, "failed", {
59
- previousState: "running",
60
- error: "missing persisted run request for stale running run recovery",
83
+ return failRecovery(context, thread, "running", "missing persisted run request for stale running run recovery", {
84
+ releaseRunClaim: true,
61
85
  });
62
- await context.persistence.releaseRunClaim(thread.latestRunId);
63
- return true;
64
86
  }
65
- const releaseRunSlot = await context.acquireRunSlot(thread.threadId, thread.latestRunId, "running", normalizeRunPriority(request.priority));
66
- try {
67
- await context.emit(thread.threadId, thread.latestRunId, 100, "run.resumed", {
68
- resumeKind: "startup-running-recovery",
69
- state: "running",
70
- });
71
- await context.executeQueuedRun(binding, request.input, thread.threadId, thread.latestRunId, runMeta.agentId, {
72
- context: request.invocation?.context,
73
- state: request.invocation?.inputs,
74
- files: request.invocation?.attachments,
75
- previousState: "running",
76
- stateSequence: 103,
77
- approvalSequence: 104,
78
- });
79
- }
80
- finally {
81
- await releaseRunSlot();
82
- }
83
- return true;
87
+ return executeRecoveredRun(context, {
88
+ thread,
89
+ binding: resolved.binding,
90
+ agentId: resolved.agentId,
91
+ request,
92
+ previousState: "running",
93
+ emitResumeEvent: {
94
+ sequence: 100,
95
+ eventType: "run.resumed",
96
+ payload: {
97
+ resumeKind: "startup-running-recovery",
98
+ state: "running",
99
+ },
100
+ },
101
+ });
84
102
  }
85
103
  export async function recoverResumingStartupRun(context, thread) {
86
104
  if (thread.status !== "resuming" || !context.recoveryConfig.resumeResumingRunsOnStartup) {
@@ -1,4 +1,5 @@
1
1
  import { type MessageContent, type ThreadSummary, type WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
2
3
  export declare function getDefaultHostAgentId(workspace: WorkspaceBundle, preferredHostAgentId?: string): string;
3
4
  export declare function resolveSelectedAgentId(options: {
4
5
  workspace: WorkspaceBundle;
@@ -8,3 +9,10 @@ export declare function resolveSelectedAgentId(options: {
8
9
  preferredHostAgentId?: string;
9
10
  getThreadSummary: (threadId: string) => Promise<ThreadSummary | null>;
10
11
  }): Promise<string>;
12
+ export declare function routeAgentId(options: {
13
+ workspace: WorkspaceBundle;
14
+ input: MessageContent;
15
+ routingRules: RoutingRule[];
16
+ routingDefaultAgentId?: string;
17
+ threadId?: string;
18
+ }): string;
@@ -1,4 +1,7 @@
1
1
  import { AUTO_AGENT_ID } from "../../../contracts/types.js";
2
+ import { extractMessageText } from "../../../utils/message-content.js";
3
+ import { matchRoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
4
+ import { getWorkspaceBinding } from "../bindings.js";
2
5
  import { inferRoutingBindings } from "../../support/harness-support.js";
3
6
  export function getDefaultHostAgentId(workspace, preferredHostAgentId) {
4
7
  const preferredBinding = preferredHostAgentId ? workspace.bindings.get(preferredHostAgentId) : undefined;
@@ -21,3 +24,21 @@ export async function resolveSelectedAgentId(options) {
21
24
  }
22
25
  return requestedAgentId;
23
26
  }
27
+ export function routeAgentId(options) {
28
+ const { workspace, input, routingRules, routingDefaultAgentId, threadId } = options;
29
+ const rawInput = extractMessageText(input);
30
+ const configuredRule = routingRules.find((rule) => matchRoutingRule(rawInput, rule, { threadId }));
31
+ if (configuredRule) {
32
+ const configuredBinding = getWorkspaceBinding(workspace, configuredRule.agentId);
33
+ if (configuredBinding) {
34
+ return configuredBinding.agent.id;
35
+ }
36
+ }
37
+ const defaultBinding = routingDefaultAgentId
38
+ ? getWorkspaceBinding(workspace, routingDefaultAgentId)
39
+ : undefined;
40
+ if (defaultBinding) {
41
+ return defaultBinding.agent.id;
42
+ }
43
+ return getDefaultHostAgentId(workspace, routingDefaultAgentId);
44
+ }