@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.
Files changed (36) 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.js +3 -5
  11. package/dist/runtime/harness/events/listener-runtime.d.ts +18 -0
  12. package/dist/runtime/harness/events/listener-runtime.js +9 -0
  13. package/dist/runtime/harness/events/runtime-event-operations.d.ts +17 -0
  14. package/dist/runtime/harness/events/runtime-event-operations.js +9 -0
  15. package/dist/runtime/harness/run/recovery.d.ts +1 -1
  16. package/dist/runtime/harness/run/resume-runtime.d.ts +55 -0
  17. package/dist/runtime/harness/run/resume-runtime.js +26 -0
  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 +67 -0
  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/run/stream-runtime.d.ts +48 -0
  27. package/dist/runtime/harness/run/stream-runtime.js +14 -0
  28. package/dist/runtime/harness.d.ts +4 -3
  29. package/dist/runtime/harness.js +177 -252
  30. package/dist/runtime/support/runtime-adapter-options.d.ts +17 -0
  31. package/dist/runtime/support/runtime-adapter-options.js +29 -0
  32. package/package.json +1 -1
  33. package/dist/runtime/adapter/deepagent-runnable-config.d.ts +0 -13
  34. package/dist/runtime/adapter/deepagent-runnable-config.js +0 -29
  35. package/dist/runtime/adapter/langchain-runnable-config.d.ts +0 -11
  36. 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.108";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.107";
1
+ export const AGENT_HARNESS_VERSION = "0.0.108";
@@ -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
@@ -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";
@@ -324,9 +323,8 @@ export class AgentRuntimeAdapter {
324
323
  const invokeTimeoutMs = resolveBindingTimeout(binding);
325
324
  const streamIdleTimeoutMs = resolveStreamIdleTimeout(binding);
326
325
  const streamDeadlineAt = invokeTimeoutMs ? Date.now() + invokeTimeoutMs : undefined;
327
- const { primaryTools, toolNameMapping } = buildBindingToolExecutionContext({
326
+ const { primaryTools, toolNameMapping } = buildBindingToolCatalog({
328
327
  binding,
329
- resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
330
328
  getToolNameMapping: (currentBinding) => this.getToolNameMapping(currentBinding),
331
329
  });
332
330
  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;
@@ -0,0 +1,55 @@
1
+ import type { CompiledAgentBinding, InternalApprovalRecord, MessageContent, ResumeOptions, RunResult, ThreadSummary, TranscriptMessage, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
+ import type { AgentRuntimeAdapter } from "../../agent-runtime-adapter.js";
4
+ type Binding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
5
+ export declare function createResumeRunRuntime(input: {
6
+ persistence: RuntimePersistence;
7
+ workspace: WorkspaceBundle;
8
+ runtimeAdapter: AgentRuntimeAdapter;
9
+ getSession: (threadId: string) => Promise<ThreadSummary | null>;
10
+ getRunCancellation: (runId: string) => Promise<{
11
+ requested: boolean;
12
+ reason?: string;
13
+ }>;
14
+ finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
15
+ acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
16
+ resolvePersistedRunPriority: (threadId: string, runId: string) => Promise<number>;
17
+ emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
18
+ loadRunInput: (threadId: string, runId: string) => Promise<MessageContent>;
19
+ recordLlmSuccess: (startedAt: number) => void;
20
+ recordLlmFailure: (startedAt: number) => void;
21
+ finalizeContinuedRun: (binding: Binding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
22
+ previousState: RunResult["state"] | null;
23
+ stateSequence: number;
24
+ approvalSequence?: number;
25
+ }) => Promise<RunResult>;
26
+ }): {
27
+ getApprovalById: (approvalId: string) => Promise<InternalApprovalRecord | null>;
28
+ getSession: (threadId: string) => Promise<ThreadSummary | null>;
29
+ resolveApprovalRecord: (resumeOptions: ResumeOptions, thread: ThreadSummary) => Promise<InternalApprovalRecord>;
30
+ getBinding: (agentId: string) => CompiledAgentBinding | undefined;
31
+ buildResumePayload: (binding: CompiledAgentBinding, approval: InternalApprovalRecord, resumeOptions: ResumeOptions) => unknown;
32
+ getRunCancellation: (runId: string) => Promise<{
33
+ requested: boolean;
34
+ reason?: string;
35
+ }>;
36
+ finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
37
+ setRunState: (threadId: string, runId: string, state: RunResult["state"], checkpointRef: string | null) => Promise<void>;
38
+ acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
39
+ resolvePersistedRunPriority: (threadId: string, runId: string) => Promise<number>;
40
+ saveRecoveryIntent: (threadId: string, runId: string, payload: Record<string, unknown>) => Promise<void>;
41
+ emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
42
+ resolveApproval: (threadId: string, runId: string, approvalId: string, resolution: "approved" | "edited" | "rejected" | "expired") => Promise<InternalApprovalRecord>;
43
+ listThreadMessages: (threadId: string) => Promise<TranscriptMessage[]>;
44
+ loadRunInput: (threadId: string, runId: string) => Promise<MessageContent>;
45
+ invoke: (binding: CompiledAgentBinding, message: MessageContent, threadId: string, runId: string, resumePayload: unknown, priorHistory: TranscriptMessage[]) => Promise<RunResult>;
46
+ recordLlmSuccess: (startedAt: number) => void;
47
+ recordLlmFailure: (startedAt: number) => void;
48
+ clearRecoveryIntent: (threadId: string, runId: string) => Promise<void>;
49
+ finalizeContinuedRun: (binding: Binding, threadId: string, runId: string, message: MessageContent, actual: RunResult, options: {
50
+ previousState: RunResult["state"] | null;
51
+ stateSequence: number;
52
+ approvalSequence?: number;
53
+ }) => Promise<RunResult>;
54
+ };
55
+ export {};
@@ -0,0 +1,26 @@
1
+ import { getWorkspaceBinding } from "../bindings.js";
2
+ import { buildResumePayload as buildHarnessResumePayload, resolveApprovalRecord as resolveHarnessApprovalRecord } from "./resume.js";
3
+ export function createResumeRunRuntime(input) {
4
+ return {
5
+ getApprovalById: (approvalId) => input.persistence.getApproval(approvalId),
6
+ getSession: (threadId) => input.getSession(threadId),
7
+ resolveApprovalRecord: (resumeOptions, thread) => resolveHarnessApprovalRecord(input.persistence, resumeOptions, thread),
8
+ getBinding: (agentId) => getWorkspaceBinding(input.workspace, agentId),
9
+ buildResumePayload: (binding, approval, resumeOptions) => buildHarnessResumePayload(binding, approval, resumeOptions),
10
+ getRunCancellation: (runId) => input.getRunCancellation(runId),
11
+ finalizeCancelledRun: (threadId, runId, previousState, reason) => input.finalizeCancelledRun(threadId, runId, previousState, reason),
12
+ setRunState: (threadId, runId, state, checkpointRef) => input.persistence.setRunState(threadId, runId, state, checkpointRef),
13
+ acquireRunSlot: (threadId, runId, activeState, priority) => input.acquireRunSlot(threadId, runId, activeState, priority),
14
+ resolvePersistedRunPriority: (threadId, runId) => input.resolvePersistedRunPriority(threadId, runId),
15
+ saveRecoveryIntent: (threadId, runId, payload) => input.persistence.saveRecoveryIntent(threadId, runId, payload),
16
+ emit: (threadId, runId, sequence, eventType, payload) => input.emit(threadId, runId, sequence, eventType, payload),
17
+ resolveApproval: (threadId, runId, approvalId, resolution) => input.persistence.resolveApproval(threadId, runId, approvalId, resolution),
18
+ listThreadMessages: (threadId) => input.persistence.listThreadMessages(threadId),
19
+ loadRunInput: (threadId, runId) => input.loadRunInput(threadId, runId),
20
+ invoke: (binding, message, threadId, runId, resumePayload, priorHistory) => input.runtimeAdapter.invoke(binding, message, threadId, runId, resumePayload, priorHistory),
21
+ recordLlmSuccess: (startedAt) => input.recordLlmSuccess(startedAt),
22
+ recordLlmFailure: (startedAt) => input.recordLlmFailure(startedAt),
23
+ clearRecoveryIntent: (threadId, runId) => input.persistence.clearRecoveryIntent(threadId, runId),
24
+ finalizeContinuedRun: (binding, threadId, runId, message, actual, options) => input.finalizeContinuedRun(binding, threadId, runId, message, actual, options),
25
+ };
26
+ }
@@ -1,4 +1,5 @@
1
1
  import { type MessageContent, type ThreadSummary, type WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
2
3
  export declare function getDefaultHostAgentId(workspace: WorkspaceBundle, preferredHostAgentId?: string): string;
3
4
  export declare function resolveSelectedAgentId(options: {
4
5
  workspace: WorkspaceBundle;
@@ -8,3 +9,10 @@ export declare function resolveSelectedAgentId(options: {
8
9
  preferredHostAgentId?: string;
9
10
  getThreadSummary: (threadId: string) => Promise<ThreadSummary | null>;
10
11
  }): Promise<string>;
12
+ export declare function routeAgentId(options: {
13
+ workspace: WorkspaceBundle;
14
+ input: MessageContent;
15
+ routingRules: RoutingRule[];
16
+ routingDefaultAgentId?: string;
17
+ threadId?: string;
18
+ }): string;
@@ -1,4 +1,7 @@
1
1
  import { AUTO_AGENT_ID } from "../../../contracts/types.js";
2
+ import { extractMessageText } from "../../../utils/message-content.js";
3
+ import { matchRoutingRule } from "../../../workspace/support/workspace-ref-utils.js";
4
+ import { getWorkspaceBinding } from "../bindings.js";
2
5
  import { inferRoutingBindings } from "../../support/harness-support.js";
3
6
  export function getDefaultHostAgentId(workspace, preferredHostAgentId) {
4
7
  const preferredBinding = preferredHostAgentId ? workspace.bindings.get(preferredHostAgentId) : undefined;
@@ -21,3 +24,21 @@ export async function resolveSelectedAgentId(options) {
21
24
  }
22
25
  return requestedAgentId;
23
26
  }
27
+ export function routeAgentId(options) {
28
+ const { workspace, input, routingRules, routingDefaultAgentId, threadId } = options;
29
+ const rawInput = extractMessageText(input);
30
+ const configuredRule = routingRules.find((rule) => matchRoutingRule(rawInput, rule, { threadId }));
31
+ if (configuredRule) {
32
+ const configuredBinding = getWorkspaceBinding(workspace, configuredRule.agentId);
33
+ if (configuredBinding) {
34
+ return configuredBinding.agent.id;
35
+ }
36
+ }
37
+ const defaultBinding = routingDefaultAgentId
38
+ ? getWorkspaceBinding(workspace, routingDefaultAgentId)
39
+ : undefined;
40
+ if (defaultBinding) {
41
+ return defaultBinding.agent.id;
42
+ }
43
+ return getDefaultHostAgentId(workspace, routingDefaultAgentId);
44
+ }
@@ -45,6 +45,53 @@ type CancelOperationRuntime = {
45
45
  error?: string;
46
46
  }) => Promise<unknown>;
47
47
  };
48
+ type ExecuteQueuedRunOperationRuntime = {
49
+ persistence: {
50
+ getRun: (runId: string) => Promise<{
51
+ state: RunResult["state"];
52
+ } | null>;
53
+ clearRunRequest: (threadId: string, runId: string) => Promise<void>;
54
+ };
55
+ getRunCancellation: (runId: string) => Promise<{
56
+ requested: boolean;
57
+ reason?: string;
58
+ }>;
59
+ finalizeCancelledRun: (threadId: string, runId: string, previousState: RunResult["state"] | null, reason?: string) => Promise<RunResult>;
60
+ emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
61
+ setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
62
+ previousState: string | null;
63
+ checkpointRef?: string | null;
64
+ error?: string;
65
+ }) => Promise<unknown>;
66
+ invokeWithHistory: (binding: CompiledAgentBinding, input: MessageContent, threadId: string, runId: string, resumePayload?: unknown, priorHistory?: TranscriptMessage[], options?: {
67
+ context?: Record<string, unknown>;
68
+ state?: Record<string, unknown>;
69
+ files?: Record<string, unknown>;
70
+ }) => Promise<RunResult>;
71
+ finalizeContinuedRun: (binding: CompiledAgentBinding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
72
+ previousState: RunResult["state"] | null;
73
+ stateSequence: number;
74
+ approvalSequence?: number;
75
+ }) => Promise<RunResult>;
76
+ emitSyntheticFallback: (threadId: string, runId: string, agentId: string, error: unknown) => Promise<void>;
77
+ renderRuntimeFailure: (error: unknown) => string;
78
+ };
48
79
  export declare function resumeRun(runtime: ResumeOperationRuntime, options: ResumeOptions): Promise<RunResult>;
49
80
  export declare function cancelRunOperation(runtime: CancelOperationRuntime, options: CancelOptions): Promise<RunResult>;
81
+ export declare function executeQueuedRunOperation(runtime: ExecuteQueuedRunOperationRuntime, input: {
82
+ binding: CompiledAgentBinding;
83
+ message: MessageContent;
84
+ threadId: string;
85
+ runId: string;
86
+ agentId: string;
87
+ options?: {
88
+ context?: Record<string, unknown>;
89
+ state?: Record<string, unknown>;
90
+ files?: Record<string, unknown>;
91
+ priorHistory?: TranscriptMessage[];
92
+ previousState?: RunResult["state"];
93
+ stateSequence?: number;
94
+ approvalSequence?: number;
95
+ };
96
+ }): Promise<RunResult>;
50
97
  export {};
@@ -111,3 +111,70 @@ export async function cancelRunOperation(runtime, options) {
111
111
  output: options.reason ? `cancelling: ${options.reason}` : "cancelling",
112
112
  };
113
113
  }
114
+ export async function executeQueuedRunOperation(runtime, input) {
115
+ const { binding, message, threadId, runId, agentId } = input;
116
+ const options = input.options ?? {};
117
+ const previousState = options.previousState ?? "running";
118
+ const currentRun = await runtime.persistence.getRun(runId);
119
+ if (currentRun?.state === "cancelled") {
120
+ return {
121
+ threadId,
122
+ runId,
123
+ agentId,
124
+ state: "cancelled",
125
+ output: "cancelled",
126
+ };
127
+ }
128
+ const cancellation = await runtime.getRunCancellation(runId);
129
+ if (cancellation.requested) {
130
+ return runtime.finalizeCancelledRun(threadId, runId, previousState, cancellation.reason);
131
+ }
132
+ if (previousState === "queued") {
133
+ await runtime.emit(threadId, runId, 101, "run.dequeued", {
134
+ queuePosition: 0,
135
+ activeRunCount: 0,
136
+ maxConcurrentRuns: 0,
137
+ recoveredOnStartup: true,
138
+ });
139
+ await runtime.setRunStateAndEmit(threadId, runId, 102, "running", {
140
+ previousState: "queued",
141
+ });
142
+ }
143
+ try {
144
+ const actual = await runtime.invokeWithHistory(binding, message, threadId, runId, undefined, options.priorHistory, {
145
+ context: options.context,
146
+ state: options.state,
147
+ files: options.files,
148
+ });
149
+ const cancelledAfterInvoke = await runtime.getRunCancellation(runId);
150
+ if (cancelledAfterInvoke.requested) {
151
+ return runtime.finalizeCancelledRun(threadId, runId, previousState === "queued" ? "running" : previousState, cancelledAfterInvoke.reason);
152
+ }
153
+ const finalized = await runtime.finalizeContinuedRun(binding, threadId, runId, message, actual, {
154
+ previousState: previousState === "queued" ? "running" : previousState,
155
+ stateSequence: options.stateSequence ?? 103,
156
+ approvalSequence: options.approvalSequence ?? 104,
157
+ });
158
+ return {
159
+ ...finalized,
160
+ agentId,
161
+ };
162
+ }
163
+ catch (error) {
164
+ await runtime.emitSyntheticFallback(threadId, runId, agentId, error);
165
+ await runtime.setRunStateAndEmit(threadId, runId, 104, "failed", {
166
+ previousState: previousState === "queued" ? "running" : previousState,
167
+ error: error instanceof Error ? error.message : String(error),
168
+ });
169
+ return {
170
+ threadId,
171
+ runId,
172
+ agentId,
173
+ state: "failed",
174
+ output: runtime.renderRuntimeFailure(error),
175
+ };
176
+ }
177
+ finally {
178
+ await runtime.persistence.clearRunRequest(threadId, runId);
179
+ }
180
+ }
@@ -0,0 +1,82 @@
1
+ import type { HarnessEvent, InvocationEnvelope, MessageContent, RunResult, RunStartOptions, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { PersistedRunRequest } from "../../../persistence/types.js";
3
+ import type { PolicyEngine } from "../system/policy-engine.js";
4
+ type Binding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
5
+ type EnsureThreadStartedRuntime = {
6
+ persistence: {
7
+ bootstrapRun?: (input: {
8
+ threadId: string;
9
+ agentId: string;
10
+ runId: string;
11
+ status: RunResult["state"];
12
+ createdAt: string;
13
+ executionMode: string;
14
+ adapterKind: string;
15
+ userMessage: {
16
+ role: "user";
17
+ content: MessageContent;
18
+ runId: string;
19
+ createdAt: string;
20
+ };
21
+ runRequest: PersistedRunRequest;
22
+ createThread: boolean;
23
+ }) => Promise<void>;
24
+ createThread: (input: {
25
+ threadId: string;
26
+ agentId: string;
27
+ runId: string;
28
+ status: RunResult["state"];
29
+ createdAt: string;
30
+ }) => Promise<void>;
31
+ appendThreadMessage: (threadId: string, message: {
32
+ role: "user";
33
+ content: MessageContent;
34
+ runId: string;
35
+ createdAt: string;
36
+ }) => Promise<void>;
37
+ createRun: (input: {
38
+ threadId: string;
39
+ runId: string;
40
+ agentId: string;
41
+ executionMode: string;
42
+ adapterKind: string;
43
+ createdAt: string;
44
+ }) => Promise<void>;
45
+ saveRunRequest: (threadId: string, runId: string, runRequest: PersistedRunRequest) => Promise<void>;
46
+ };
47
+ };
48
+ type PrepareRunStartRuntime = EnsureThreadStartedRuntime & {
49
+ workspace: WorkspaceBundle;
50
+ policyEngine: PolicyEngine;
51
+ resolveSelectedAgentId: (input: MessageContent, requestedAgentId?: string, threadId?: string) => Promise<string>;
52
+ emitRunCreated: (threadId: string, runId: string, payload: Record<string, unknown>) => Promise<HarnessEvent>;
53
+ acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
54
+ };
55
+ export declare function ensureThreadStarted(runtime: EnsureThreadStartedRuntime, input: {
56
+ selectedAgentId: string;
57
+ binding: Binding;
58
+ message: MessageContent;
59
+ runRequest: PersistedRunRequest;
60
+ existingThreadId?: string;
61
+ }): Promise<{
62
+ threadId: string;
63
+ runId: string;
64
+ createdAt: string;
65
+ isNewThread: boolean;
66
+ }>;
67
+ export declare function prepareRunStart(runtime: PrepareRunStartRuntime, input: {
68
+ options: Pick<RunStartOptions, "input" | "agentId" | "threadId" | "priority">;
69
+ invocation: InvocationEnvelope;
70
+ runCreatedPayload: (binding: Binding, selectedAgentId: string) => Record<string, unknown>;
71
+ }): Promise<{
72
+ binding: Binding;
73
+ selectedAgentId: string;
74
+ priority: number;
75
+ threadId: string;
76
+ runId: string;
77
+ isNewThread: boolean;
78
+ runCreatedEventPromise: Promise<HarnessEvent>;
79
+ releaseRunSlotPromise: Promise<() => Promise<void>>;
80
+ }>;
81
+ export declare function defaultRequestedAgentId(agentId?: string): string;
82
+ export {};