@botbotgo/agent-harness 0.0.95 → 0.0.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +1 -114
  2. package/README.zh.md +1 -70
  3. package/dist/api.d.ts +5 -5
  4. package/dist/config/workflows/langgraph-workflows.yaml +363 -111
  5. package/dist/config/workflows/runtime-profiles.yaml +94 -0
  6. package/dist/contracts/core.d.ts +9 -0
  7. package/dist/contracts/core.js +1 -0
  8. package/dist/contracts/runtime.d.ts +421 -0
  9. package/dist/contracts/runtime.js +1 -0
  10. package/dist/contracts/types.d.ts +3 -571
  11. package/dist/contracts/types.js +3 -1
  12. package/dist/contracts/workspace.d.ts +229 -0
  13. package/dist/contracts/workspace.js +1 -0
  14. package/dist/package-version.d.ts +1 -1
  15. package/dist/package-version.js +1 -1
  16. package/dist/runtime/adapter/compat/deepagent-compat.d.ts +16 -0
  17. package/dist/runtime/adapter/compat/deepagent-compat.js +45 -0
  18. package/dist/runtime/adapter/compat/openai-compatible.d.ts +2 -0
  19. package/dist/runtime/adapter/compat/openai-compatible.js +43 -0
  20. package/dist/runtime/adapter/index.d.ts +15 -0
  21. package/dist/runtime/adapter/index.js +15 -0
  22. package/dist/runtime/adapter/langgraph/presets.js +165 -0
  23. package/dist/runtime/{langgraph-profiles.d.ts → adapter/langgraph/profiles.d.ts} +1 -1
  24. package/dist/runtime/adapter/langgraph/profiles.js +206 -0
  25. package/dist/runtime/adapter/model/invocation-request.d.ts +10 -0
  26. package/dist/runtime/adapter/model/invocation-request.js +46 -0
  27. package/dist/runtime/adapter/model/message-assembly.d.ts +6 -0
  28. package/dist/runtime/adapter/model/message-assembly.js +21 -0
  29. package/dist/runtime/adapter/model/model-providers.d.ts +2 -0
  30. package/dist/runtime/adapter/model/model-providers.js +27 -0
  31. package/dist/runtime/adapter/resilience.d.ts +12 -0
  32. package/dist/runtime/adapter/resilience.js +60 -0
  33. package/dist/runtime/{declared-middleware.d.ts → adapter/tool/declared-middleware.d.ts} +1 -1
  34. package/dist/runtime/adapter/tool/interrupt-policy.d.ts +8 -0
  35. package/dist/runtime/adapter/tool/interrupt-policy.js +34 -0
  36. package/dist/runtime/adapter/tool/provider-tool.d.ts +2 -0
  37. package/dist/runtime/adapter/tool/provider-tool.js +25 -0
  38. package/dist/runtime/adapter/tool/resolved-tool.d.ts +18 -0
  39. package/dist/runtime/adapter/tool/resolved-tool.js +62 -0
  40. package/dist/runtime/adapter/tool/tool-arguments.d.ts +7 -0
  41. package/dist/runtime/adapter/tool/tool-arguments.js +87 -0
  42. package/dist/runtime/{tool-hitl.d.ts → adapter/tool/tool-hitl.d.ts} +2 -2
  43. package/dist/runtime/adapter/tool/tool-name-mapping.d.ts +13 -0
  44. package/dist/runtime/adapter/tool/tool-name-mapping.js +101 -0
  45. package/dist/runtime/agent-runtime-adapter.d.ts +5 -20
  46. package/dist/runtime/agent-runtime-adapter.js +42 -544
  47. package/dist/runtime/checkpoint-maintenance.d.ts +1 -45
  48. package/dist/runtime/checkpoint-maintenance.js +1 -259
  49. package/dist/runtime/file-checkpoint-saver.d.ts +1 -20
  50. package/dist/runtime/file-checkpoint-saver.js +1 -106
  51. package/dist/runtime/{event-bus.d.ts → harness/events/event-bus.d.ts} +1 -1
  52. package/dist/runtime/{event-sink.d.ts → harness/events/event-sink.d.ts} +1 -1
  53. package/dist/runtime/{event-sink.js → harness/events/event-sink.js} +1 -1
  54. package/dist/runtime/harness/events/events.d.ts +23 -0
  55. package/dist/runtime/harness/events/events.js +61 -0
  56. package/dist/runtime/harness/events/streaming.d.ts +19 -0
  57. package/dist/runtime/harness/events/streaming.js +96 -0
  58. package/dist/runtime/harness/index.d.ts +16 -0
  59. package/dist/runtime/harness/index.js +16 -0
  60. package/dist/runtime/harness/run/helpers.d.ts +33 -0
  61. package/dist/runtime/harness/run/helpers.js +74 -0
  62. package/dist/runtime/harness/run/resources.d.ts +7 -0
  63. package/dist/runtime/harness/run/resources.js +58 -0
  64. package/dist/runtime/harness/run/resume.d.ts +6 -0
  65. package/dist/runtime/harness/run/resume.js +56 -0
  66. package/dist/runtime/harness/run/routing.d.ts +12 -0
  67. package/dist/runtime/harness/run/routing.js +47 -0
  68. package/dist/runtime/harness/run/run-lifecycle.d.ts +37 -0
  69. package/dist/runtime/harness/run/run-lifecycle.js +109 -0
  70. package/dist/runtime/harness/run/run-queue.d.ts +17 -0
  71. package/dist/runtime/harness/run/run-queue.js +43 -0
  72. package/dist/runtime/{health-monitor.d.ts → harness/system/health-monitor.d.ts} +3 -3
  73. package/dist/runtime/{health-monitor.js → harness/system/health-monitor.js} +2 -2
  74. package/dist/runtime/{inventory.d.ts → harness/system/inventory.d.ts} +2 -2
  75. package/dist/runtime/{inventory.js → harness/system/inventory.js} +4 -4
  76. package/dist/runtime/{policy-engine.d.ts → harness/system/policy-engine.d.ts} +1 -1
  77. package/dist/runtime/{policy-engine.js → harness/system/policy-engine.js} +1 -1
  78. package/dist/runtime/{skill-requirements.d.ts → harness/system/skill-requirements.d.ts} +1 -1
  79. package/dist/runtime/{skill-requirements.js → harness/system/skill-requirements.js} +1 -1
  80. package/dist/runtime/{thread-memory-sync.d.ts → harness/system/thread-memory-sync.d.ts} +2 -2
  81. package/dist/runtime/{thread-memory-sync.js → harness/system/thread-memory-sync.js} +1 -1
  82. package/dist/runtime/harness.d.ts +2 -7
  83. package/dist/runtime/harness.js +158 -477
  84. package/dist/runtime/index.d.ts +7 -7
  85. package/dist/runtime/index.js +7 -7
  86. package/dist/runtime/maintenance/checkpoint-maintenance.d.ts +45 -0
  87. package/dist/runtime/maintenance/checkpoint-maintenance.js +259 -0
  88. package/dist/runtime/maintenance/file-checkpoint-saver.d.ts +20 -0
  89. package/dist/runtime/maintenance/file-checkpoint-saver.js +106 -0
  90. package/dist/runtime/maintenance/index.d.ts +4 -0
  91. package/dist/runtime/maintenance/index.js +4 -0
  92. package/dist/runtime/{runtime-record-maintenance.d.ts → maintenance/runtime-record-maintenance.d.ts} +1 -1
  93. package/dist/runtime/{runtime-record-maintenance.js → maintenance/runtime-record-maintenance.js} +2 -2
  94. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.d.ts +9 -0
  95. package/dist/runtime/maintenance/sqlite-maintained-checkpoint-saver.js +39 -0
  96. package/dist/runtime/parsing/stream-event-parsing.d.ts +6 -0
  97. package/dist/runtime/parsing/stream-event-parsing.js +231 -0
  98. package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +1 -9
  99. package/dist/runtime/sqlite-maintained-checkpoint-saver.js +1 -39
  100. package/dist/runtime/support/harness-support.d.ts +4 -4
  101. package/dist/runtime/support/harness-support.js +14 -3
  102. package/dist/runtime/support/runtime-factories.d.ts +1 -1
  103. package/dist/runtime/support/runtime-factories.js +1 -1
  104. package/dist/workspace/agent-binding-compiler.js +39 -3
  105. package/dist/workspace/object-loader.js +5 -1
  106. package/package.json +4 -4
  107. package/dist/runtime/langgraph-presets.js +0 -165
  108. package/dist/runtime/langgraph-profiles.js +0 -206
  109. /package/dist/runtime/{langgraph-presets.d.ts → adapter/langgraph/presets.d.ts} +0 -0
  110. /package/dist/runtime/{declared-middleware.js → adapter/tool/declared-middleware.js} +0 -0
  111. /package/dist/runtime/{tool-hitl.js → adapter/tool/tool-hitl.js} +0 -0
  112. /package/dist/runtime/{event-bus.js → harness/events/event-bus.js} +0 -0
  113. /package/dist/runtime/{store.d.ts → harness/system/store.d.ts} +0 -0
  114. /package/dist/runtime/{store.js → harness/system/store.js} +0 -0
@@ -1,32 +1,37 @@
1
1
  import path from "node:path";
2
2
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
3
3
  import { Command, MemorySaver } from "@langchain/langgraph";
4
- import { tool as createLangChainTool } from "@langchain/core/tools";
5
4
  import { HumanMessage, ToolMessage } from "@langchain/core/messages";
6
5
  import { DEFAULT_SUBAGENT_PROMPT, createDeepAgent, createMemoryMiddleware, createPatchToolCallsMiddleware, createSkillsMiddleware, createSummarizationMiddleware, createSubAgentMiddleware, FilesystemBackend, StateBackend, isSandboxBackend, } from "deepagents";
7
- import { ChatAnthropic } from "@langchain/anthropic";
8
- import { tools as anthropicProviderTools } from "@langchain/anthropic";
9
- import { ChatGoogle } from "@langchain/google";
10
- import { ChatOllama } from "@langchain/ollama";
11
- import { ChatOpenAI } from "@langchain/openai";
12
- import { tools as openAIProviderTools } from "@langchain/openai";
13
- import { createAgent, humanInTheLoopMiddleware, initChatModel } from "langchain";
6
+ import { createAgent, humanInTheLoopMiddleware } from "langchain";
14
7
  import { z } from "zod";
15
- import { extractEmptyAssistantMessageFailure, extractContentBlocks, extractOutputContent, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, salvageToolArgs, isLikelyToolArgsObject, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION, sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
16
- import { computeIncrementalOutput, extractAgentStep, extractInterruptPayload, extractReasoningStreamOutput, extractStateStreamOutput, extractVisibleStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
17
- import { wrapToolForExecution } from "./tool-hitl.js";
18
- import { resolveDeclaredMiddleware } from "./declared-middleware.js";
19
- import { extractMessageText, normalizeMessageContent } from "../utils/message-content.js";
20
- import { getBindingAdapterKind, getBindingDeepAgentParams, getBindingAdapterConfig, getBindingInterruptCompatibilityRules, getBindingLangChainParams, getBindingLangGraphPreset, getBindingLangGraphWorkflow, getBindingMiddlewareConfigs, getBindingModelInit, getBindingPrimaryModel, getBindingRuntimeModel, getBindingPrimaryTools, getBindingSystemPrompt, isDeepAgentBinding, isLangChainBinding, } from "./support/compiled-binding.js";
21
- import { readSkillMetadata } from "./support/skill-metadata.js";
22
- import { resolveLangGraphProfileWorkflow } from "./langgraph-profiles.js";
23
- import { resolveLangGraphPresetWorkflow } from "./langgraph-presets.js";
8
+ import { extractEmptyAssistantMessageFailure, extractContentBlocks, extractOutputContent, extractReasoningText, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION, sanitizeVisibleText, tryParseJson, wrapResolvedModel, } from "./parsing/output-parsing.js";
9
+ import { computeIncrementalOutput, extractAgentStep, extractInterruptPayload, normalizeUpstreamRuntimeEvent, extractReasoningStreamOutput, extractStateStreamOutput, extractVisibleStreamOutput, extractTerminalStreamOutput, extractToolResult, normalizeTerminalOutputKey, readStreamDelta, } from "./parsing/stream-event-parsing.js";
10
+ import { wrapToolForExecution } from "./adapter/tool/tool-hitl.js";
11
+ import { resolveDeclaredMiddleware } from "./adapter/tool/declared-middleware.js";
12
+ import { extractMessageText } from "../utils/message-content.js";
13
+ import { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
14
+ import { buildToolNameMapping, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, } from "./adapter/tool/tool-name-mapping.js";
15
+ import { computeRemainingTimeoutMs, isRetryableProviderError, resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
16
+ import { createResolvedModel } from "./adapter/model/model-providers.js";
17
+ import { buildInvocationRequest, buildSlashCommandSkillInstruction, } from "./adapter/model/invocation-request.js";
18
+ import { compileInterruptOn } from "./adapter/tool/interrupt-policy.js";
19
+ import { buildRawModelMessages, buildStateSnapshot } from "./adapter/model/message-assembly.js";
20
+ import { asRecord, asStructuredExecutableTool, hasCallableToolHandler, normalizeResolvedToolSchema, wrapResolvedToolWithModelFacingName, } from "./adapter/tool/resolved-tool.js";
21
+ import { instantiateProviderTool } from "./adapter/tool/provider-tool.js";
22
+ import { extractToolCallsFromResult, normalizeToolArgsForSchema, stringifyToolOutput } from "./adapter/tool/tool-arguments.js";
23
+ export { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths, relativizeDeepAgentSkillSourcePaths, shouldRelaxDeepAgentDelegationPrompt, } from "./adapter/compat/deepagent-compat.js";
24
+ export { buildAuthOmittingFetch, normalizeOpenAICompatibleInit } from "./adapter/compat/openai-compatible.js";
25
+ export { buildToolNameMapping, createModelFacingToolNameCandidates, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, sanitizeToolNameForModel, } from "./adapter/tool/tool-name-mapping.js";
26
+ export { computeRemainingTimeoutMs, isRetryableProviderError, resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout, resolveTimeoutMs, } from "./adapter/resilience.js";
27
+ import { getBindingAdapterKind, getBindingDeepAgentParams, getBindingAdapterConfig, getBindingInterruptCompatibilityRules, getBindingLangChainParams, getBindingLangGraphPreset, getBindingLangGraphWorkflow, getBindingMiddlewareConfigs, getBindingPrimaryModel, getBindingRuntimeModel, getBindingPrimaryTools, getBindingSystemPrompt, isDeepAgentBinding, isLangChainBinding, } from "./support/compiled-binding.js";
28
+ import { resolveLangGraphProfileWorkflow } from "./adapter/langgraph/profiles.js";
29
+ import { resolveLangGraphPresetWorkflow } from "./adapter/langgraph/presets.js";
24
30
  const SUPPORTED_LANGGRAPH_WORKFLOW_NODE_KINDS = new Set(["llm", "agent", "tool", "approval", "condition"]);
25
31
  function countConfiguredTools(binding) {
26
32
  return getBindingPrimaryTools(binding).length;
27
33
  }
28
34
  const AGENT_INTERRUPT_SENTINEL_PREFIX = "__agent_harness_interrupt__:";
29
- const MODEL_SAFE_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
30
35
  const UPSTREAM_BUILTIN_MIDDLEWARE_TOOL_NAMES = Object.freeze([
31
36
  "write_todos",
32
37
  "ls",
@@ -53,111 +58,9 @@ class RuntimeOperationTimeoutError extends Error {
53
58
  function asObject(value) {
54
59
  return typeof value === "object" && value ? value : undefined;
55
60
  }
56
- function resolveTimeoutMs(value) {
57
- return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
58
- }
59
- function computeRemainingTimeoutMs(deadlineAt, fallbackTimeoutMs) {
60
- if (!deadlineAt) {
61
- return fallbackTimeoutMs;
62
- }
63
- const remaining = deadlineAt - Date.now();
64
- if (remaining <= 0) {
65
- return 0;
66
- }
67
- return fallbackTimeoutMs ? Math.min(fallbackTimeoutMs, remaining) : remaining;
68
- }
69
61
  function sleep(ms) {
70
62
  return new Promise((resolve) => setTimeout(resolve, ms));
71
63
  }
72
- function isPlaceholderApiKey(value) {
73
- return typeof value === "string" && value.trim().toLowerCase() === "dummy";
74
- }
75
- export function relativizeDeepAgentSkillSourcePaths(workspaceRoot, skillPaths) {
76
- if (!workspaceRoot || !skillPaths) {
77
- return skillPaths;
78
- }
79
- return skillPaths.map((skillPath) => {
80
- if (!path.isAbsolute(skillPath)) {
81
- return skillPath;
82
- }
83
- const relative = path.relative(workspaceRoot, skillPath);
84
- if (!relative || relative.startsWith("..")) {
85
- return skillPath;
86
- }
87
- return relative.split(path.sep).join("/");
88
- });
89
- }
90
- export async function materializeDeepAgentSkillSourcePaths(options) {
91
- const { workspaceRoot, skillPaths } = options;
92
- if (!skillPaths) {
93
- return skillPaths;
94
- }
95
- return relativizeDeepAgentSkillSourcePaths(workspaceRoot, skillPaths) ?? skillPaths;
96
- }
97
- function buildAuthOmittingFetch(baseFetch = fetch) {
98
- return async (input, init) => {
99
- const sanitizedHeaders = new Headers(input instanceof Request ? input.headers : undefined);
100
- const initHeaders = new Headers(init?.headers);
101
- initHeaders.forEach((value, key) => {
102
- sanitizedHeaders.set(key, value);
103
- });
104
- sanitizedHeaders.delete("authorization");
105
- if (input instanceof Request) {
106
- return baseFetch(new Request(input, {
107
- ...init,
108
- headers: sanitizedHeaders,
109
- }));
110
- }
111
- return baseFetch(input, {
112
- ...init,
113
- headers: sanitizedHeaders,
114
- });
115
- };
116
- }
117
- function normalizeOpenAICompatibleInit(init) {
118
- const normalized = { ...init };
119
- const configuration = asObject(init.configuration) ?? {};
120
- const baseUrl = typeof init.baseUrl === "string" && init.baseUrl.trim() ? init.baseUrl.trim() : undefined;
121
- const omitAuthHeader = init.omitAuthHeader === true || isPlaceholderApiKey(init.apiKey);
122
- const nextConfiguration = { ...configuration };
123
- if (baseUrl && typeof nextConfiguration.baseURL !== "string") {
124
- nextConfiguration.baseURL = baseUrl;
125
- }
126
- if (omitAuthHeader) {
127
- nextConfiguration.fetch = buildAuthOmittingFetch(typeof configuration.fetch === "function" ? configuration.fetch : fetch);
128
- }
129
- normalized.configuration = nextConfiguration;
130
- delete normalized.baseUrl;
131
- delete normalized.omitAuthHeader;
132
- return normalized;
133
- }
134
- function sanitizeToolNameForModel(name) {
135
- const withoutNamespace = name.includes(".") ? name.split(".").at(-1) ?? name : name;
136
- const sanitized = withoutNamespace
137
- .replaceAll(".", "__")
138
- .replace(/[^a-zA-Z0-9_-]+/g, "_")
139
- .replace(/^_+|_+$/g, "");
140
- return sanitized || "tool";
141
- }
142
- function buildToolNameMapping(tools) {
143
- const originalToModelFacing = new Map();
144
- const modelFacingToOriginal = new Map();
145
- const seen = new Set();
146
- for (const tool of tools) {
147
- const originalName = tool.name;
148
- const baseName = MODEL_SAFE_TOOL_NAME_PATTERN.test(originalName) ? originalName : sanitizeToolNameForModel(originalName);
149
- let candidate = baseName;
150
- let suffix = 2;
151
- while (seen.has(candidate)) {
152
- candidate = `${baseName}_${suffix}`;
153
- suffix += 1;
154
- }
155
- seen.add(candidate);
156
- originalToModelFacing.set(originalName, candidate);
157
- modelFacingToOriginal.set(candidate, originalName);
158
- }
159
- return { originalToModelFacing, modelFacingToOriginal };
160
- }
161
64
  function hasConfiguredSubagentSupport(binding) {
162
65
  const params = getBindingLangChainParams(binding);
163
66
  if (!params) {
@@ -165,185 +68,15 @@ function hasConfiguredSubagentSupport(binding) {
165
68
  }
166
69
  return (params.subagents?.length ?? 0) > 0 || params.generalPurposeAgent === true || Boolean(params.taskDescription?.trim());
167
70
  }
168
- function isOpenAICompatibleGptOssModel(model) {
169
- return model?.provider === "openai-compatible" && model.model.trim().toLowerCase().startsWith("gpt-oss");
170
- }
171
- export function shouldRelaxDeepAgentDelegationPrompt(model, params) {
172
- if (!isOpenAICompatibleGptOssModel(model)) {
173
- return false;
174
- }
175
- if ((params.subagents?.length ?? 0) === 0) {
176
- return false;
177
- }
178
- return params.generalPurposeAgent === true || Boolean(params.taskDescription?.trim());
179
- }
180
- function applyDeepAgentDelegationPromptCompatibility(model, params) {
181
- if (!shouldRelaxDeepAgentDelegationPrompt(model, params)) {
182
- return params;
183
- }
184
- return {
185
- ...params,
186
- generalPurposeAgent: undefined,
187
- taskDescription: undefined,
188
- };
189
- }
190
71
  function hasConfiguredMiddlewareKind(binding, kind) {
191
72
  return getBindingMiddlewareConfigs(binding)?.some((entry) => entry.kind === kind) ?? false;
192
73
  }
193
- function instantiateProviderTool(compiledTool) {
194
- const providerTool = asRecord(compiledTool.config?.providerTool);
195
- const provider = typeof providerTool?.provider === "string" ? providerTool.provider.trim().toLowerCase() : "";
196
- const toolName = typeof providerTool?.tool === "string" ? providerTool.tool.trim() : "";
197
- const args = asRecord(providerTool?.args) ?? {};
198
- if (!provider || !toolName) {
199
- throw new Error(`Provider tool ${compiledTool.id} must define providerTool.provider and providerTool.tool`);
200
- }
201
- const registry = provider === "openai"
202
- ? openAIProviderTools
203
- : provider === "anthropic"
204
- ? anthropicProviderTools
205
- : undefined;
206
- if (!registry) {
207
- throw new Error(`Provider tool ${compiledTool.id} uses unsupported provider ${provider}`);
208
- }
209
- const factory = registry[toolName];
210
- if (typeof factory !== "function") {
211
- throw new Error(`Provider tool ${compiledTool.id} references unknown ${provider} tool ${toolName}`);
212
- }
213
- return factory(args);
214
- }
215
- function wrapResolvedToolWithModelFacingName(resolvedTool, modelFacingName) {
216
- if (typeof resolvedTool !== "object" || resolvedTool === null) {
217
- return resolvedTool;
218
- }
219
- return new Proxy(resolvedTool, {
220
- get(target, prop, receiver) {
221
- if (prop === "name") {
222
- return modelFacingName;
223
- }
224
- return Reflect.get(target, prop, receiver);
225
- },
226
- getOwnPropertyDescriptor(target, prop) {
227
- if (prop === "name") {
228
- return {
229
- configurable: true,
230
- enumerable: true,
231
- writable: false,
232
- value: modelFacingName,
233
- };
234
- }
235
- return Reflect.getOwnPropertyDescriptor(target, prop);
236
- },
237
- });
238
- }
239
- function hasCallableToolHandler(value) {
240
- if (typeof value !== "object" || value === null) {
241
- return false;
242
- }
243
- const typed = value;
244
- return typeof typed.invoke === "function" || typeof typed.call === "function" || typeof typed.func === "function";
245
- }
246
- function asRecord(value) {
247
- return typeof value === "object" && value !== null && !Array.isArray(value)
248
- ? { ...value }
249
- : undefined;
250
- }
251
- function normalizeResolvedToolSchema(resolvedTool) {
252
- const schema = resolvedTool.schema;
253
- if (schema && typeof schema.parse === "function" && "_def" in schema) {
254
- return resolvedTool.schema;
255
- }
256
- if (schema && (schema.type === "object" || typeof schema.properties === "object")) {
257
- return schema;
258
- }
259
- return z.object({}).passthrough();
260
- }
261
74
  function isRecord(value) {
262
75
  return typeof value === "object" && value !== null && !Array.isArray(value);
263
76
  }
264
77
  function isObject(value) {
265
78
  return isRecord(value);
266
79
  }
267
- function stringifyToolOutput(output) {
268
- if (typeof output === "string") {
269
- return output;
270
- }
271
- try {
272
- return JSON.stringify(output);
273
- }
274
- catch {
275
- return `${String(output)}`;
276
- }
277
- }
278
- function normalizeToolArgsForSchema(args, schema) {
279
- const schemaDef = isObject(schema) ? schema._def : undefined;
280
- const shape = schemaDef
281
- ? isRecord(schemaDef.shape)
282
- ? schemaDef.shape
283
- : typeof schemaDef.shape === "function"
284
- ? schemaDef.shape()
285
- : undefined
286
- : undefined;
287
- if (!shape || !isRecord(shape)) {
288
- return args;
289
- }
290
- const keys = Object.keys(shape);
291
- if (keys.length !== 1) {
292
- return args;
293
- }
294
- const [expectedKey] = keys;
295
- if (expectedKey in args) {
296
- return args;
297
- }
298
- const aliasesByExpected = {
299
- city: ["location", "locality", "place"],
300
- location: ["city", "city_name"],
301
- };
302
- const aliases = aliasesByExpected[expectedKey] ?? [];
303
- const aliasKey = aliases.find((candidate) => candidate in args);
304
- if (!aliasKey || !(aliasKey in args)) {
305
- return args;
306
- }
307
- return {
308
- ...args,
309
- [expectedKey]: args[aliasKey],
310
- };
311
- }
312
- function extractToolCallsFromResult(result) {
313
- const messages = isRecord(result) && Array.isArray(result.messages) ? result.messages : [];
314
- const lastMessage = messages.at(-1);
315
- if (!isObject(lastMessage)) {
316
- return [];
317
- }
318
- const messageKwargs = isObject(lastMessage.kwargs) ? lastMessage.kwargs : undefined;
319
- const rawToolCalls = Array.isArray(lastMessage.tool_calls)
320
- ? (lastMessage.tool_calls ?? [])
321
- : Array.isArray(messageKwargs?.tool_calls)
322
- ? messageKwargs.tool_calls
323
- : [];
324
- return rawToolCalls
325
- .map((toolCall) => {
326
- if (!isObject(toolCall)) {
327
- return null;
328
- }
329
- const functionPayload = isObject(toolCall.function) ? toolCall.function : undefined;
330
- const name = typeof toolCall.name === "string"
331
- ? toolCall.name
332
- : typeof functionPayload?.name === "string"
333
- ? functionPayload.name
334
- : null;
335
- if (!name) {
336
- return null;
337
- }
338
- const rawArgs = salvageToolArgs(toolCall.args ?? functionPayload?.arguments) ?? {};
339
- if (!isObject(rawArgs)) {
340
- return null;
341
- }
342
- const id = typeof toolCall.id === "string" ? toolCall.id : undefined;
343
- return { id, name, args: rawArgs };
344
- })
345
- .filter((item) => item !== null);
346
- }
347
80
  function truncateLines(lines, maxChars = 12_000) {
348
81
  const joined = lines.join("\n");
349
82
  if (joined.length <= maxChars) {
@@ -372,93 +105,6 @@ function summarizeBuiltinWriteTodosArgs(args) {
372
105
  items,
373
106
  };
374
107
  }
375
- function createModelFacingToolNameCandidates(toolName) {
376
- const trimmed = toolName.trim();
377
- if (!trimmed) {
378
- return [];
379
- }
380
- const lastSegment = trimmed.split(".").at(-1) ?? "";
381
- const candidates = new Set([
382
- trimmed,
383
- sanitizeToolNameForModel(trimmed),
384
- lastSegment,
385
- lastSegment.trim() ? sanitizeToolNameForModel(lastSegment) : "",
386
- trimmed.replace(/[^a-zA-Z0-9_]+/g, ""),
387
- ]);
388
- candidates.delete("");
389
- return [...candidates];
390
- }
391
- function createModelFacingToolNameLookupCandidates(toolName) {
392
- const trimmed = toolName.trim();
393
- if (!trimmed) {
394
- return [];
395
- }
396
- const candidates = new Set();
397
- const add = (value) => {
398
- for (const candidate of createModelFacingToolNameCandidates(value)) {
399
- candidates.add(candidate);
400
- }
401
- };
402
- const addSuffixStripped = (value) => {
403
- const stripped = value.includes(".") ? value.split(".").at(-1) ?? value : value;
404
- if (stripped !== value) {
405
- add(stripped);
406
- }
407
- };
408
- add(trimmed);
409
- if (trimmed.startsWith("functions.")) {
410
- const stripped = trimmed.substring("functions.".length);
411
- add(stripped);
412
- addSuffixStripped(stripped);
413
- }
414
- else if (trimmed.startsWith("function.")) {
415
- const stripped = trimmed.substring("function.".length);
416
- add(stripped);
417
- addSuffixStripped(stripped);
418
- }
419
- else {
420
- addSuffixStripped(trimmed);
421
- }
422
- return [...candidates];
423
- }
424
- function resolveModelFacingToolName(toolName, mapping, tools) {
425
- const candidateNames = createModelFacingToolNameLookupCandidates(toolName);
426
- const candidateSet = new Set(candidateNames);
427
- for (const candidate of candidateNames) {
428
- const mappedToolName = mapping.modelFacingToOriginal.get(candidate);
429
- if (mappedToolName) {
430
- return mappedToolName;
431
- }
432
- }
433
- for (const candidate of candidateNames) {
434
- const directMatch = tools.find((tool) => tool.name === candidate);
435
- if (directMatch) {
436
- return directMatch.name;
437
- }
438
- }
439
- const candidateMatches = tools.filter((tool) => {
440
- const modelFacingCandidates = createModelFacingToolNameCandidates(tool.name);
441
- return modelFacingCandidates.some((candidate) => candidateSet.has(candidate));
442
- });
443
- if (candidateMatches.length === 1) {
444
- return candidateMatches[0].name;
445
- }
446
- return toolName;
447
- }
448
- function asStructuredExecutableTool(resolvedTool, modelFacingName, description) {
449
- if (!hasCallableToolHandler(resolvedTool)) {
450
- return resolvedTool;
451
- }
452
- const handler = resolvedTool.invoke ?? resolvedTool.call ?? resolvedTool.func;
453
- if (typeof handler !== "function") {
454
- return resolvedTool;
455
- }
456
- return createLangChainTool(async (input, config) => handler(input, config), {
457
- name: modelFacingName,
458
- description,
459
- schema: normalizeResolvedToolSchema(resolvedTool),
460
- });
461
- }
462
108
  export class AgentRuntimeAdapter {
463
109
  options;
464
110
  modelCache = new Map();
@@ -475,54 +121,8 @@ export class AgentRuntimeAdapter {
475
121
  clientRef: model.clientRef,
476
122
  });
477
123
  }
478
- resolveBindingTimeout(binding) {
479
- return resolveTimeoutMs(getBindingModelInit(binding)?.timeout);
480
- }
481
- resolveStreamIdleTimeout(binding) {
482
- const configuredIdleTimeout = resolveTimeoutMs(getBindingModelInit(binding)?.streamIdleTimeout);
483
- if (configuredIdleTimeout) {
484
- return configuredIdleTimeout;
485
- }
486
- const invokeTimeout = this.resolveBindingTimeout(binding);
487
- if (invokeTimeout) {
488
- return Math.min(invokeTimeout, 15_000);
489
- }
490
- return 15_000;
491
- }
492
- resolveProviderRetryPolicy(binding) {
493
- const resilience = typeof binding.harnessRuntime.resilience === "object" && binding.harnessRuntime.resilience
494
- ? binding.harnessRuntime.resilience
495
- : {};
496
- const providerRetries = typeof resilience.providerRetries === "object" && resilience.providerRetries
497
- ? resilience.providerRetries
498
- : {};
499
- const maxAttempts = typeof providerRetries.maxAttempts === "number" &&
500
- Number.isFinite(providerRetries.maxAttempts) &&
501
- providerRetries.maxAttempts > 0
502
- ? Math.floor(providerRetries.maxAttempts)
503
- : 2;
504
- const backoffMs = typeof providerRetries.backoffMs === "number" &&
505
- Number.isFinite(providerRetries.backoffMs) &&
506
- providerRetries.backoffMs >= 0
507
- ? Math.floor(providerRetries.backoffMs)
508
- : 1_000;
509
- const retryableMessages = Array.isArray(providerRetries.retryableMessages)
510
- ? providerRetries.retryableMessages.filter((value) => typeof value === "string" && value.trim().length > 0)
511
- : [];
512
- return {
513
- maxAttempts,
514
- backoffMs,
515
- retryableMessages,
516
- };
517
- }
518
- isRetryableProviderError(binding, error) {
519
- const message = error instanceof Error ? error.message : String(error);
520
- const normalized = message.toLowerCase();
521
- const { retryableMessages } = this.resolveProviderRetryPolicy(binding);
522
- return retryableMessages.some((candidate) => normalized.includes(candidate.toLowerCase()));
523
- }
524
124
  async invokeWithProviderRetry(binding, operation) {
525
- const retryPolicy = this.resolveProviderRetryPolicy(binding);
125
+ const retryPolicy = resolveProviderRetryPolicy(binding);
526
126
  let lastError;
527
127
  for (let attempt = 1; attempt <= retryPolicy.maxAttempts; attempt += 1) {
528
128
  try {
@@ -530,7 +130,7 @@ export class AgentRuntimeAdapter {
530
130
  }
531
131
  catch (error) {
532
132
  lastError = error;
533
- if (attempt >= retryPolicy.maxAttempts || !this.isRetryableProviderError(binding, error)) {
133
+ if (attempt >= retryPolicy.maxAttempts || !isRetryableProviderError(binding, error)) {
534
134
  throw error;
535
135
  }
536
136
  if (retryPolicy.backoffMs > 0) {
@@ -668,25 +268,7 @@ export class AgentRuntimeAdapter {
668
268
  return cached;
669
269
  }
670
270
  const pending = (async () => {
671
- if (this.options.modelResolver) {
672
- return wrapResolvedModel(await this.options.modelResolver(model.id));
673
- }
674
- if (model.provider === "ollama") {
675
- return wrapResolvedModel(new ChatOllama({ model: model.model, ...model.init }));
676
- }
677
- if (model.provider === "openai-compatible") {
678
- return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...normalizeOpenAICompatibleInit(model.init) }));
679
- }
680
- if (model.provider === "openai") {
681
- return wrapResolvedModel(new ChatOpenAI({ model: model.model, ...model.init }));
682
- }
683
- if (model.provider === "anthropic") {
684
- return wrapResolvedModel(new ChatAnthropic({ model: model.model, ...model.init }));
685
- }
686
- if (model.provider === "google" || model.provider === "google-genai" || model.provider === "gemini") {
687
- return wrapResolvedModel(new ChatGoogle({ model: model.model, ...model.init }));
688
- }
689
- return wrapResolvedModel(await initChatModel(model.model, { modelProvider: model.provider, ...model.init }));
271
+ return wrapResolvedModel(await createResolvedModel(model, this.options.modelResolver));
690
272
  })();
691
273
  this.modelCache.set(cacheKey, pending);
692
274
  try {
@@ -700,69 +282,14 @@ export class AgentRuntimeAdapter {
700
282
  buildToolNameMapping(tools) {
701
283
  return buildToolNameMapping(tools);
702
284
  }
703
- buildAgentMessages(history, input) {
704
- return [
705
- ...history.map((item) => ({ role: item.role, content: normalizeMessageContent(item.content) })),
706
- { role: "user", content: normalizeMessageContent(input) },
707
- ];
708
- }
709
285
  buildSlashCommandSkillInstruction(binding, input) {
710
- const inputText = extractMessageText(input).trim();
711
- const match = inputText.match(/^\/([a-z0-9]+(?:-[a-z0-9]+)*)(?:\s+([\s\S]*))?$/i);
712
- if (!match) {
713
- return undefined;
714
- }
715
- const invokedName = match[1].toLowerCase();
716
- const argumentText = match[2]?.trim() ?? "";
717
- const skillPaths = binding.deepAgentParams?.skills ?? binding.langchainAgentParams?.skills ?? [];
718
- const matchedSkillPath = skillPaths.find((skillPath) => readSkillMetadata(skillPath).name.toLowerCase() === invokedName);
719
- if (!matchedSkillPath) {
720
- return undefined;
721
- }
722
- const metadata = readSkillMetadata(matchedSkillPath);
723
- const skillQualifier = metadata.userInvocable === true ? "user-invocable skill" : "skill";
724
- const dryRunHint = /\s--dry-run(?:\s|$)/.test(` ${argumentText} `)
725
- ? "This invocation includes `--dry-run`. Perform the real fetch or inspection steps needed for dry-run output. Do not return hypothetical or mock results."
726
- : undefined;
727
- return [
728
- `This user message is an explicit command-style invocation of the ${skillQualifier} \`${metadata.name}\`.`,
729
- `Read the skill file for \`${metadata.name}\` before taking action, then follow its documented phases and constraints exactly.`,
730
- `You must use the \`${metadata.name}\` skill for this request and follow its documented workflow.`,
731
- `Treat everything after \`/${metadata.name}\` as the skill argument string: ${argumentText ? JSON.stringify(argumentText) : '""'}.`,
732
- "Do not answer with a generic explanation of what the skill would do. Execute the skill workflow using the available tools unless the skill instructions explicitly require confirmation before acting.",
733
- dryRunHint,
734
- ].filter((line) => typeof line === "string" && line.length > 0).join("\n");
286
+ return buildSlashCommandSkillInstruction(binding, input);
735
287
  }
736
288
  buildInvocationRequest(binding, history, input, options = {}) {
737
- const userInvocableInstruction = this.buildSlashCommandSkillInstruction(binding, input);
738
- const messages = this.buildAgentMessages(history, input);
739
- return {
740
- ...(options.state ?? {}),
741
- ...(options.files ? { files: options.files } : {}),
742
- messages: userInvocableInstruction
743
- ? [{ role: "system", content: userInvocableInstruction }, ...messages]
744
- : messages,
745
- };
746
- }
747
- buildStateSnapshot(result) {
748
- const snapshot = { ...result };
749
- delete snapshot.messages;
750
- delete snapshot.__interrupt__;
751
- delete snapshot.structuredResponse;
752
- delete snapshot.files;
753
- return Object.keys(snapshot).length > 0 ? snapshot : undefined;
289
+ return buildInvocationRequest(binding, history, input, options);
754
290
  }
755
291
  buildRawModelMessages(binding, systemPrompt, history, input) {
756
- const messages = [];
757
- if (systemPrompt) {
758
- messages.push({ role: "system", content: systemPrompt });
759
- }
760
- const userInvocableInstruction = this.buildSlashCommandSkillInstruction(binding, input);
761
- if (userInvocableInstruction) {
762
- messages.push({ role: "system", content: userInvocableInstruction });
763
- }
764
- messages.push(...this.buildAgentMessages(history, input));
765
- return messages;
292
+ return buildRawModelMessages(binding, systemPrompt, history, input);
766
293
  }
767
294
  resolveTools(tools, binding) {
768
295
  const resolved = this.options.toolResolver ? this.options.toolResolver(tools.map((tool) => tool.id), binding) : [];
@@ -781,38 +308,8 @@ export class AgentRuntimeAdapter {
781
308
  return modelFacingName === compiledTool.name ? wrappedTool : wrapResolvedToolWithModelFacingName(wrappedTool, modelFacingName);
782
309
  });
783
310
  }
784
- normalizeInterruptPolicy(rule) {
785
- if (!rule)
786
- return null;
787
- if (rule === true)
788
- return ["approve", "edit", "reject"];
789
- const typed = rule;
790
- if (Array.isArray(typed.allowedDecisions)) {
791
- return typed.allowedDecisions.filter((item) => item === "approve" || item === "edit" || item === "reject");
792
- }
793
- const decisions = [];
794
- if (typed.allowAccept !== false)
795
- decisions.push("approve");
796
- if (typed.allowEdit !== false)
797
- decisions.push("edit");
798
- if (typed.allowReject !== false)
799
- decisions.push("reject");
800
- return decisions.length > 0 ? decisions : null;
801
- }
802
311
  compileInterruptOn(tools, compatibilityRules) {
803
- const toolNameMapping = this.buildToolNameMapping(tools);
804
- const compiled = new Map();
805
- for (const [toolName, rule] of Object.entries(compatibilityRules ?? {})) {
806
- const modelFacingName = toolNameMapping.originalToModelFacing.get(toolName) ?? toolName;
807
- const allowedDecisions = this.normalizeInterruptPolicy(rule);
808
- if (!allowedDecisions) {
809
- compiled.delete(modelFacingName);
810
- }
811
- else {
812
- compiled.set(modelFacingName, { allowedDecisions });
813
- }
814
- }
815
- return compiled.size > 0 ? Object.fromEntries(compiled.entries()) : undefined;
312
+ return compileInterruptOn(tools, compatibilityRules);
816
313
  }
817
314
  resolveInterruptOn(binding) {
818
315
  return this.compileInterruptOn(getBindingPrimaryTools(binding), getBindingInterruptCompatibilityRules(binding));
@@ -1333,13 +830,13 @@ export class AgentRuntimeAdapter {
1333
830
  .map((edge) => this.normalizeLangGraphWorkflowEdge(edge))
1334
831
  .filter((edge) => edge !== null);
1335
832
  }
1336
- shouldFollowLangGraphEdge(edge, state, executorResult) {
833
+ shouldFollowLangGraphEdge(edge, state, currentResult) {
1337
834
  const condition = edge.when?.toLowerCase().trim();
1338
835
  if (!condition || condition === "always") {
1339
836
  return true;
1340
837
  }
1341
838
  const review = state.review?.toLowerCase() ?? "";
1342
- const hasResult = Boolean(executorResult);
839
+ const hasResult = Boolean(currentResult);
1343
840
  switch (condition) {
1344
841
  case "has_plan":
1345
842
  return Boolean(state.plan?.trim());
@@ -1365,9 +862,9 @@ export class AgentRuntimeAdapter {
1365
862
  return false;
1366
863
  }
1367
864
  }
1368
- listLangGraphWorkflowNextNodes(workflow, nodeId, state, executorResult) {
865
+ listLangGraphWorkflowNextNodes(workflow, nodeId, state, currentResult) {
1369
866
  return this.listLangGraphWorkflowEdges(workflow)
1370
- .filter((edge) => edge.from === nodeId && this.shouldFollowLangGraphEdge(edge, state, executorResult))
867
+ .filter((edge) => edge.from === nodeId && this.shouldFollowLangGraphEdge(edge, state, currentResult))
1371
868
  .map((edge) => edge.to);
1372
869
  }
1373
870
  extractInvocationRequestText(request) {
@@ -1631,7 +1128,7 @@ export class AgentRuntimeAdapter {
1631
1128
  `User request:\n${userInputText}`,
1632
1129
  ...(workflowState.plan ? ["", `Workflow plan:\n${workflowState.plan}`] : []),
1633
1130
  ...(workflowState.review ? ["", `Workflow review:\n${workflowState.review}`] : []),
1634
- ...(activeResult ? ["", `Current executor result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`] : []),
1131
+ ...(activeResult ? ["", `Current result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`] : []),
1635
1132
  "",
1636
1133
  "Complete the delegated subagent work and return concise results.",
1637
1134
  ].join("\n");
@@ -1746,7 +1243,7 @@ export class AgentRuntimeAdapter {
1746
1243
  workflowState.review = await this.invokeWorkflowNodeModel(reviewerModel, reviewerPrompt, [
1747
1244
  `User request:\n${userInputText}`,
1748
1245
  "",
1749
- `Executor result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`,
1246
+ `Current result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`,
1750
1247
  ].join("\n"));
1751
1248
  }
1752
1249
  else if ((nodeRole === "finalizer" || nodeRole === "final") && activeResult) {
@@ -1988,7 +1485,7 @@ export class AgentRuntimeAdapter {
1988
1485
  workflowState.review = await this.invokeWorkflowNodeModel(reviewerModel, reviewerPrompt, [
1989
1486
  `User request:\n${userInputText}`,
1990
1487
  "",
1991
- `Executor result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`,
1488
+ `Current result:\n${extractVisibleOutput(activeResult) || JSON.stringify(activeResult, null, 2)}`,
1992
1489
  ].join("\n"));
1993
1490
  if (workflowState.review) {
1994
1491
  yield { kind: "reasoning", content: workflowState.review };
@@ -2329,7 +1826,7 @@ export class AgentRuntimeAdapter {
2329
1826
  const callRuntime = async (activeBinding, activeRequest) => {
2330
1827
  return this.invokeWithProviderRetry(activeBinding, async () => {
2331
1828
  const runnable = await this.create(activeBinding);
2332
- return (await this.withTimeout(() => runnable.invoke(activeRequest, { configurable: { thread_id: threadId, run_id: runId }, ...(options.context ? { context: options.context } : {}) }), this.resolveBindingTimeout(activeBinding), "agent invoke", "invoke"));
1829
+ return (await this.withTimeout(() => runnable.invoke(activeRequest, { configurable: { thread_id: threadId, run_id: runId }, ...(options.context ? { context: options.context } : {}) }), resolveBindingTimeout(activeBinding), "agent invoke", "invoke"));
2333
1830
  });
2334
1831
  };
2335
1832
  const callRuntimeWithToolParseRecovery = async (activeRequest) => {
@@ -2475,7 +1972,7 @@ export class AgentRuntimeAdapter {
2475
1972
  ...(outputContent !== undefined ? { outputContent } : {}),
2476
1973
  ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
2477
1974
  ...(asRecord(result.files) ? { files: asRecord(result.files) } : {}),
2478
- ...(this.buildStateSnapshot(result) ? { stateSnapshot: this.buildStateSnapshot(result) } : {}),
1975
+ ...(buildStateSnapshot(result) ? { stateSnapshot: buildStateSnapshot(result) } : {}),
2479
1976
  upstreamResult: result,
2480
1977
  },
2481
1978
  };
@@ -2483,8 +1980,8 @@ export class AgentRuntimeAdapter {
2483
1980
  async *stream(binding, input, threadId, history = [], options = {}) {
2484
1981
  try {
2485
1982
  const adapterKind = getBindingAdapterKind(binding);
2486
- const invokeTimeoutMs = this.resolveBindingTimeout(binding);
2487
- const streamIdleTimeoutMs = this.resolveStreamIdleTimeout(binding);
1983
+ const invokeTimeoutMs = resolveBindingTimeout(binding);
1984
+ const streamIdleTimeoutMs = resolveStreamIdleTimeout(binding);
2488
1985
  const streamDeadlineAt = invokeTimeoutMs ? Date.now() + invokeTimeoutMs : undefined;
2489
1986
  const primaryTools = getBindingPrimaryTools(binding);
2490
1987
  const toolNameMapping = this.buildToolNameMapping(primaryTools);
@@ -2541,6 +2038,7 @@ export class AgentRuntimeAdapter {
2541
2038
  const seenTerminalOutputs = new Set();
2542
2039
  let lastStep = "";
2543
2040
  for await (const event of this.iterateWithTimeout(events, streamIdleTimeoutMs, "agent streamEvents", streamDeadlineAt, invokeTimeoutMs)) {
2041
+ yield { kind: "upstream-event", event: normalizeUpstreamRuntimeEvent(event) };
2544
2042
  const interruptPayload = extractInterruptPayload(event);
2545
2043
  if (interruptPayload) {
2546
2044
  yield { kind: "interrupt", content: interruptPayload };