@botbotgo/agent-harness 0.0.100 → 0.0.101

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.
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.99";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.100";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.99";
1
+ export const AGENT_HARNESS_VERSION = "0.0.100";
@@ -81,13 +81,14 @@ function listProviderTools(provider) {
81
81
  toolPath: tool.toolPath ?? tool.builtinPath ?? "",
82
82
  }));
83
83
  }
84
+ function preferProviderValue(provider, primary, fallback) {
85
+ return provider ? (primary(provider) ?? fallback(provider)) : undefined;
86
+ }
84
87
  function createProviderToolResolver(provider, workspace, options) {
85
- return (provider?.createResourceToolResolver?.(workspace, options) ??
86
- provider?.createBuiltinToolResolver?.(workspace, options));
88
+ return preferProviderValue(provider, (candidate) => candidate.createResourceToolResolver?.(workspace, options), (candidate) => candidate.createBuiltinToolResolver?.(workspace, options));
87
89
  }
88
90
  function createProviderBackendResolver(provider, workspace) {
89
- return (provider?.createResourceBackendResolver?.(workspace) ??
90
- provider?.createBuiltinBackendResolver?.(workspace));
91
+ return preferProviderValue(provider, (candidate) => candidate.createResourceBackendResolver?.(workspace), (candidate) => candidate.createBuiltinBackendResolver?.(workspace));
91
92
  }
92
93
  class CompatibleCompositeBackend {
93
94
  id;
@@ -133,69 +134,66 @@ class CompatibleCompositeBackend {
133
134
  return this.composite.downloadFiles(paths);
134
135
  }
135
136
  }
137
+ const INLINE_BACKEND_ERROR = 'Unsupported DeepAgent backend kind "%s". Supported inline kinds: LocalShellBackend, VfsSandbox, StateBackend, StoreBackend, CompositeBackend.';
138
+ function unsupportedInlineBackend(kind) {
139
+ throw new Error(INLINE_BACKEND_ERROR.replace("%s", kind));
140
+ }
141
+ function resolveInlineBackendRootDir(workspaceRoot, configuredRootDir) {
142
+ if (typeof configuredRootDir === "string" && configuredRootDir.trim().length > 0) {
143
+ return path.isAbsolute(configuredRootDir)
144
+ ? configuredRootDir
145
+ : path.resolve(workspaceRoot, configuredRootDir);
146
+ }
147
+ return workspaceRoot;
148
+ }
149
+ function createLocalShellStyleBackend(workspaceRoot, config, options) {
150
+ const rootDir = resolveInlineBackendRootDir(workspaceRoot, config?.rootDir);
151
+ mkdirSync(rootDir, { recursive: true });
152
+ const inheritedEnv = config?.inheritEnv === false ? {} : process.env;
153
+ return new LocalShellBackend({
154
+ rootDir,
155
+ virtualMode: options.virtualMode,
156
+ timeout: typeof config?.timeout === "number" ? config.timeout : undefined,
157
+ maxOutputBytes: typeof config?.maxOutputBytes === "number" ? config.maxOutputBytes : undefined,
158
+ env: createRuntimeEnv(readStringRecord(config?.env), inheritedEnv),
159
+ inheritEnv: config?.inheritEnv !== false,
160
+ });
161
+ }
162
+ function createInlineBackendInstance(workspaceRoot, kind, config, runtimeLike) {
163
+ switch (kind) {
164
+ case "LocalShellBackend":
165
+ return createLocalShellStyleBackend(workspaceRoot, config, {
166
+ virtualMode: config?.virtualMode === true,
167
+ });
168
+ case "VfsSandbox":
169
+ return createLocalShellStyleBackend(workspaceRoot, config, {
170
+ virtualMode: config?.virtualMode === false ? false : true,
171
+ });
172
+ case "StateBackend":
173
+ return new StateBackend(runtimeLike);
174
+ case "StoreBackend":
175
+ return new StoreBackend(runtimeLike);
176
+ default:
177
+ return unsupportedInlineBackend(kind);
178
+ }
179
+ }
136
180
  function createInlineBackendResolver(workspace) {
137
181
  return (binding) => {
138
182
  const backendConfig = binding.deepAgentParams?.backend;
139
183
  if (!backendConfig || typeof backendConfig !== "object") {
140
184
  return undefined;
141
185
  }
142
- const resolveBackendRootDir = (configuredRootDir) => {
143
- if (typeof configuredRootDir === "string" && configuredRootDir.trim().length > 0) {
144
- return path.isAbsolute(configuredRootDir)
145
- ? configuredRootDir
146
- : path.resolve(workspace.workspaceRoot, configuredRootDir);
147
- }
148
- return workspace.workspaceRoot;
149
- };
150
- const createBackend = (kind, config, runtimeLike) => {
151
- const configuredEnv = typeof config?.env === "object" && config.env
152
- ? Object.fromEntries(Object.entries(config.env).filter((entry) => typeof entry[1] === "string"))
153
- : undefined;
154
- const inheritedEnv = config?.inheritEnv === false ? {} : process.env;
155
- switch (kind) {
156
- case "LocalShellBackend": {
157
- const rootDir = resolveBackendRootDir(config?.rootDir);
158
- mkdirSync(rootDir, { recursive: true });
159
- return new LocalShellBackend({
160
- rootDir,
161
- virtualMode: config?.virtualMode === true,
162
- timeout: typeof config?.timeout === "number" ? config.timeout : undefined,
163
- maxOutputBytes: typeof config?.maxOutputBytes === "number" ? config.maxOutputBytes : undefined,
164
- env: createRuntimeEnv(configuredEnv, inheritedEnv),
165
- inheritEnv: config?.inheritEnv !== false,
166
- });
167
- }
168
- case "VfsSandbox": {
169
- const rootDir = resolveBackendRootDir(config?.rootDir);
170
- mkdirSync(rootDir, { recursive: true });
171
- return new LocalShellBackend({
172
- rootDir,
173
- virtualMode: config?.virtualMode === false ? false : true,
174
- timeout: typeof config?.timeout === "number" ? config.timeout : undefined,
175
- maxOutputBytes: typeof config?.maxOutputBytes === "number" ? config.maxOutputBytes : undefined,
176
- env: createRuntimeEnv(configuredEnv, inheritedEnv),
177
- inheritEnv: config?.inheritEnv !== false,
178
- });
179
- }
180
- case "StateBackend":
181
- return new StateBackend(runtimeLike);
182
- case "StoreBackend":
183
- return new StoreBackend(runtimeLike);
184
- default:
185
- throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, VfsSandbox, StateBackend, StoreBackend, CompositeBackend.`);
186
- }
187
- };
188
186
  return (runtimeLike) => {
189
187
  const kind = typeof backendConfig.kind === "string" ? backendConfig.kind : "CompositeBackend";
190
188
  switch (kind) {
191
189
  case "LocalShellBackend":
192
- return createBackend("LocalShellBackend", backendConfig, runtimeLike);
190
+ return createInlineBackendInstance(workspace.workspaceRoot, "LocalShellBackend", backendConfig, runtimeLike);
193
191
  case "VfsSandbox":
194
- return createBackend("VfsSandbox", backendConfig, runtimeLike);
192
+ return createInlineBackendInstance(workspace.workspaceRoot, "VfsSandbox", backendConfig, runtimeLike);
195
193
  case "StateBackend":
196
- return new StateBackend(runtimeLike);
194
+ return createInlineBackendInstance(workspace.workspaceRoot, "StateBackend", backendConfig, runtimeLike);
197
195
  case "StoreBackend":
198
- return new StoreBackend(runtimeLike);
196
+ return createInlineBackendInstance(workspace.workspaceRoot, "StoreBackend", backendConfig, runtimeLike);
199
197
  case "CompositeBackend": {
200
198
  const stateConfig = typeof backendConfig.state === "object" && backendConfig.state
201
199
  ? backendConfig.state
@@ -206,12 +204,12 @@ function createInlineBackendResolver(workspace) {
206
204
  : { "/memories/": { kind: "StoreBackend" } };
207
205
  const mappedRoutes = Object.fromEntries(Object.entries(routes).map(([route, routeConfig]) => {
208
206
  const routeKind = typeof routeConfig?.kind === "string" ? routeConfig.kind : "StoreBackend";
209
- return [route, createBackend(routeKind, routeConfig, runtimeLike)];
207
+ return [route, createInlineBackendInstance(workspace.workspaceRoot, routeKind, routeConfig, runtimeLike)];
210
208
  }));
211
- return new CompatibleCompositeBackend(createBackend(defaultBackendKind, stateConfig, runtimeLike), mappedRoutes);
209
+ return new CompatibleCompositeBackend(createInlineBackendInstance(workspace.workspaceRoot, defaultBackendKind, stateConfig, runtimeLike), mappedRoutes);
212
210
  }
213
211
  default:
214
- throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, VfsSandbox, StateBackend, StoreBackend, CompositeBackend.`);
212
+ return unsupportedInlineBackend(kind);
215
213
  }
216
214
  };
217
215
  };
@@ -240,6 +238,23 @@ async function findPackageRoot(startPath) {
240
238
  }
241
239
  const functionToolModuleCache = new Map();
242
240
  const mcpClientCache = new Map();
241
+ function readStringRecord(value) {
242
+ if (typeof value !== "object" || !value) {
243
+ return undefined;
244
+ }
245
+ const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
246
+ return entries.length > 0 ? Object.fromEntries(entries) : undefined;
247
+ }
248
+ function listWorkspaceResourceProviders(workspace) {
249
+ return (workspace.resourceSources ?? [])
250
+ .map((source) => remoteResourceCache.get(source))
251
+ .filter((provider) => Boolean(provider));
252
+ }
253
+ function createWorkspaceProviderResolvers(workspace, factory) {
254
+ return listWorkspaceResourceProviders(workspace)
255
+ .map((provider) => factory(provider))
256
+ .filter((resolver) => Boolean(resolver));
257
+ }
243
258
  async function loadFunctionToolModule(tool) {
244
259
  const cacheKey = `${tool.sourcePath}:${tool.implementationName ?? tool.id}`;
245
260
  const cached = functionToolModuleCache.get(cacheKey);
@@ -294,20 +309,15 @@ function readMcpServerConfig(workspace, tool) {
294
309
  if (!mcpServer) {
295
310
  return null;
296
311
  }
297
- const envRecord = typeof mcpServer.env === "object" && mcpServer.env
298
- ? Object.fromEntries(Object.entries(mcpServer.env).filter((entry) => typeof entry[1] === "string"))
299
- : undefined;
300
312
  return {
301
313
  transport: normalizeMcpTransport(mcpServer.transport) ?? ((typeof mcpServer.url === "string" && mcpServer.url.trim()) ? "http" : "stdio"),
302
314
  command: typeof mcpServer.command === "string" ? mcpServer.command.trim() : undefined,
303
315
  args: Array.isArray(mcpServer.args) ? mcpServer.args.filter((item) => typeof item === "string") : undefined,
304
- env: envRecord,
316
+ env: readStringRecord(mcpServer.env),
305
317
  cwd: typeof mcpServer.cwd === "string" ? mcpServer.cwd : undefined,
306
318
  url: typeof mcpServer.url === "string" ? mcpServer.url.trim() : undefined,
307
319
  token: typeof mcpServer.token === "string" ? mcpServer.token : undefined,
308
- headers: typeof mcpServer.headers === "object" && mcpServer.headers
309
- ? Object.fromEntries(Object.entries(mcpServer.headers).filter((entry) => typeof entry[1] === "string"))
310
- : undefined,
320
+ headers: readStringRecord(mcpServer.headers),
311
321
  };
312
322
  }
313
323
  function createMcpCacheKey(config) {
@@ -514,11 +524,11 @@ export async function ensureResourceSources(sources = [], workspaceRoot = proces
514
524
  }
515
525
  export function defaultResourceSkillsRoot() {
516
526
  const provider = requireLocalResource("default resource skill resolution");
517
- return provider.defaultResourceSkillsRoot?.() ?? provider.builtinSkillsRoot?.() ?? "";
527
+ return preferProviderValue(provider, (candidate) => candidate.defaultResourceSkillsRoot?.(), (candidate) => candidate.builtinSkillsRoot?.()) ?? "";
518
528
  }
519
529
  export function defaultResourceConfigRoot() {
520
530
  const provider = requireLocalResource("default resource config resolution");
521
- return provider.defaultResourceConfigRoot?.() ?? provider.builtinConfigRoot?.() ?? provider.builtinDefaultsRoot?.() ?? "";
531
+ return (preferProviderValue(provider, (candidate) => candidate.defaultResourceConfigRoot?.(), (candidate) => candidate.builtinConfigRoot?.() ?? candidate.builtinDefaultsRoot?.()) ?? "");
522
532
  }
523
533
  export async function listResourceTools(sources = [], workspaceRoot = process.cwd()) {
524
534
  await ensureResourceSources(sources, workspaceRoot);
@@ -539,11 +549,7 @@ export async function listResourceToolsForSource(source, workspaceRoot = process
539
549
  }
540
550
  export function createResourceBackendResolver(workspace) {
541
551
  const localResolver = createProviderBackendResolver(localResource, workspace);
542
- const remoteResolvers = (workspace.resourceSources ?? [])
543
- .map((source) => remoteResourceCache.get(source))
544
- .filter((provider) => Boolean(provider))
545
- .map((provider) => createProviderBackendResolver(provider, workspace))
546
- .filter((resolver) => Boolean(resolver));
552
+ const remoteResolvers = createWorkspaceProviderResolvers(workspace, (provider) => createProviderBackendResolver(provider, workspace));
547
553
  const inlineResolver = createInlineBackendResolver(workspace);
548
554
  return (binding) => {
549
555
  const providerResolved = localResolver?.(binding) ??
@@ -555,11 +561,7 @@ export function createResourceToolResolver(workspace, options = {}) {
555
561
  const functionResolver = createFunctionToolResolver(workspace);
556
562
  const mcpResolver = createMcpToolResolver(workspace);
557
563
  const localResolver = createProviderToolResolver(localResource, workspace, options);
558
- const remoteResolvers = (workspace.resourceSources ?? [])
559
- .map((source) => remoteResourceCache.get(source))
560
- .filter((provider) => Boolean(provider))
561
- .map((provider) => createProviderToolResolver(provider, workspace, options))
562
- .filter((resolver) => Boolean(resolver));
564
+ const remoteResolvers = createWorkspaceProviderResolvers(workspace, (provider) => createProviderToolResolver(provider, workspace, options));
563
565
  return (toolIds, binding) => {
564
566
  const resolved = [
565
567
  ...functionResolver(toolIds, binding),
@@ -29,28 +29,17 @@ export declare class AgentRuntimeAdapter {
29
29
  private createModelFallbackRunnable;
30
30
  private applyStrictToolJsonInstruction;
31
31
  private resolveModel;
32
- private buildToolNameMapping;
33
- private buildSlashCommandSkillInstruction;
34
- private buildInvocationRequest;
35
- private buildRawModelMessages;
36
32
  private resolveTools;
37
- private compileInterruptOn;
38
- private resolveInterruptOn;
39
33
  private resolveFilesystemBackend;
40
34
  private resolveBuiltinMiddlewareBackend;
35
+ private createDeclaredMiddlewareResolverOptions;
41
36
  private invokeBuiltinTaskTool;
42
37
  private resolveBuiltinMiddlewareTools;
43
38
  private resolveAutomaticSummarizationMiddleware;
44
39
  private resolveLangChainAutomaticMiddleware;
45
- private resolveDeepAgentAutomaticMiddleware;
46
40
  private resolveMiddleware;
47
- private resolveCheckpointer;
48
41
  private resolveSubagents;
49
42
  private createLangChainRunnable;
50
- private extractInvocationRequestText;
51
- private prependSystemMessage;
52
- private replaceLastUserMessage;
53
- private extractExecutedToolResults;
54
43
  private createRunnable;
55
44
  private createDeepAgentRunnable;
56
45
  create(binding: CompiledAgentBinding): Promise<RunnableLike>;
@@ -7,7 +7,6 @@ import { extractToolFallbackContext, extractVisibleOutput, isToolCallParseFailur
7
7
  import { readStreamDelta, } from "./parsing/stream-event-parsing.js";
8
8
  import { wrapToolForExecution } from "./adapter/tool/tool-hitl.js";
9
9
  import { resolveDeclaredMiddleware } from "./adapter/tool/declared-middleware.js";
10
- import { extractMessageText } from "../utils/message-content.js";
11
10
  import { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths, } from "./adapter/compat/deepagent-compat.js";
12
11
  import { buildToolNameMapping, } from "./adapter/tool/tool-name-mapping.js";
13
12
  import { createBuiltinMiddlewareTools } from "./adapter/tool/builtin-middleware-tools.js";
@@ -19,12 +18,12 @@ import { buildDeepAgentRunnableConfig } from "./adapter/deepagent-runnable-confi
19
18
  import { buildLangChainRunnableConfig } from "./adapter/langchain-runnable-config.js";
20
19
  import { computeRemainingTimeoutMs, isRetryableProviderError, resolveBindingTimeout, resolveProviderRetryPolicy, resolveStreamIdleTimeout, } from "./adapter/resilience.js";
21
20
  import { createResolvedModel } from "./adapter/model/model-providers.js";
22
- import { buildInvocationRequest, buildSlashCommandSkillInstruction, } from "./adapter/model/invocation-request.js";
21
+ import { buildInvocationRequest, } from "./adapter/model/invocation-request.js";
23
22
  import { compileInterruptOn } from "./adapter/tool/interrupt-policy.js";
24
23
  import { buildRawModelMessages } from "./adapter/model/message-assembly.js";
25
24
  import { asStructuredExecutableTool, hasCallableToolHandler, normalizeResolvedToolSchema, wrapResolvedToolWithModelFacingName, } from "./adapter/tool/resolved-tool.js";
26
25
  import { instantiateProviderTool } from "./adapter/tool/provider-tool.js";
27
- import { asObject, countConfiguredTools, hasConfiguredMiddlewareKind, hasConfiguredSubagentSupport, isObject, isRecord, sleep, } from "./adapter/runtime-adapter-support.js";
26
+ import { countConfiguredTools, hasConfiguredMiddlewareKind, hasConfiguredSubagentSupport, isObject, isRecord, sleep, } from "./adapter/runtime-adapter-support.js";
28
27
  export { applyDeepAgentDelegationPromptCompatibility, materializeDeepAgentSkillSourcePaths, relativizeDeepAgentSkillSourcePaths, shouldRelaxDeepAgentDelegationPrompt, } from "./adapter/compat/deepagent-compat.js";
29
28
  export { buildAuthOmittingFetch, normalizeOpenAICompatibleInit } from "./adapter/compat/openai-compatible.js";
30
29
  export { buildToolNameMapping, createModelFacingToolNameCandidates, createModelFacingToolNameLookupCandidates, resolveModelFacingToolName, sanitizeToolNameForModel, } from "./adapter/tool/tool-name-mapping.js";
@@ -227,21 +226,9 @@ export class AgentRuntimeAdapter {
227
226
  throw error;
228
227
  }
229
228
  }
230
- buildToolNameMapping(tools) {
231
- return buildToolNameMapping(tools);
232
- }
233
- buildSlashCommandSkillInstruction(binding, input) {
234
- return buildSlashCommandSkillInstruction(binding, input);
235
- }
236
- buildInvocationRequest(binding, history, input, options = {}) {
237
- return buildInvocationRequest(binding, history, input, options);
238
- }
239
- buildRawModelMessages(binding, systemPrompt, history, input) {
240
- return buildRawModelMessages(binding, systemPrompt, history, input);
241
- }
242
229
  resolveTools(tools, binding) {
243
230
  const resolved = this.options.toolResolver ? this.options.toolResolver(tools.map((tool) => tool.id), binding) : [];
244
- const toolNameMapping = this.buildToolNameMapping(tools);
231
+ const toolNameMapping = buildToolNameMapping(tools);
245
232
  return tools.flatMap((compiledTool, index) => {
246
233
  const resolvedTool = resolved[index] ?? (compiledTool.type === "provider" ? instantiateProviderTool(compiledTool) : undefined);
247
234
  if (resolvedTool === undefined) {
@@ -256,12 +243,6 @@ export class AgentRuntimeAdapter {
256
243
  return modelFacingName === compiledTool.name ? wrappedTool : wrapResolvedToolWithModelFacingName(wrappedTool, modelFacingName);
257
244
  });
258
245
  }
259
- compileInterruptOn(tools, compatibilityRules) {
260
- return compileInterruptOn(tools, compatibilityRules);
261
- }
262
- resolveInterruptOn(binding) {
263
- return this.compileInterruptOn(getBindingPrimaryTools(binding), getBindingInterruptCompatibilityRules(binding));
264
- }
265
246
  resolveFilesystemBackend(binding) {
266
247
  const filesystemConfig = getBindingLangChainParams(binding)?.filesystem;
267
248
  const configuredRootDir = typeof filesystemConfig?.rootDir === "string" && filesystemConfig.rootDir.trim().length > 0
@@ -299,6 +280,21 @@ export class AgentRuntimeAdapter {
299
280
  }
300
281
  return new StateBackend(runtimeLike);
301
282
  }
283
+ createDeclaredMiddlewareResolverOptions(binding) {
284
+ return {
285
+ resolveModel: (model) => this.resolveModel(model),
286
+ resolveBackend: (resolvedBinding) => {
287
+ const targetBinding = resolvedBinding ?? binding;
288
+ return targetBinding ? this.options.backendResolver?.(targetBinding) : undefined;
289
+ },
290
+ resolveFilesystemBackend: (resolvedBinding) => {
291
+ const targetBinding = resolvedBinding ?? binding;
292
+ return targetBinding ? this.resolveFilesystemBackend(targetBinding) : undefined;
293
+ },
294
+ resolveCustom: this.options.declaredMiddlewareResolver,
295
+ binding,
296
+ };
297
+ }
302
298
  async invokeBuiltinTaskTool(binding, input, options = {}) {
303
299
  if (!isDeepAgentBinding(binding)) {
304
300
  throw new Error("The built-in task tool is only available for deepagent bindings.");
@@ -340,7 +336,7 @@ export class AgentRuntimeAdapter {
340
336
  ]),
341
337
  ...(selectedSubagent.interruptOn
342
338
  ? [humanInTheLoopMiddleware({
343
- interruptOn: this.compileInterruptOn(selectedSubagent.tools ?? [], selectedSubagent.interruptOn),
339
+ interruptOn: compileInterruptOn(selectedSubagent.tools ?? [], selectedSubagent.interruptOn),
344
340
  })]
345
341
  : []),
346
342
  ];
@@ -376,13 +372,7 @@ export class AgentRuntimeAdapter {
376
372
  if (!primaryModel) {
377
373
  return [];
378
374
  }
379
- return resolveDeclaredMiddleware([{ kind: "summarization", model: primaryModel }], {
380
- resolveModel: (model) => this.resolveModel(model),
381
- resolveBackend: (resolvedBinding) => this.options.backendResolver?.(resolvedBinding ?? binding),
382
- resolveFilesystemBackend: (resolvedBinding) => this.resolveFilesystemBackend(resolvedBinding ?? binding),
383
- resolveCustom: this.options.declaredMiddlewareResolver,
384
- binding,
385
- });
375
+ return resolveDeclaredMiddleware([{ kind: "summarization", model: primaryModel }], this.createDeclaredMiddlewareResolverOptions(binding));
386
376
  }
387
377
  async resolveLangChainAutomaticMiddleware(binding) {
388
378
  const params = getBindingLangChainParams(binding);
@@ -417,23 +407,11 @@ export class AgentRuntimeAdapter {
417
407
  }
418
408
  return automaticMiddleware;
419
409
  }
420
- async resolveDeepAgentAutomaticMiddleware(binding) {
421
- if (!isDeepAgentBinding(binding)) {
422
- return [];
423
- }
424
- return [];
425
- }
426
410
  async resolveMiddleware(binding, interruptOn) {
427
- const declarativeMiddleware = await resolveDeclaredMiddleware(getBindingMiddlewareConfigs(binding), {
428
- resolveModel: (model) => this.resolveModel(model),
429
- resolveBackend: (resolvedBinding) => this.options.backendResolver?.(resolvedBinding ?? binding),
430
- resolveFilesystemBackend: (resolvedBinding) => this.resolveFilesystemBackend(resolvedBinding ?? binding),
431
- resolveCustom: this.options.declaredMiddlewareResolver,
432
- binding,
433
- });
411
+ const declarativeMiddleware = await resolveDeclaredMiddleware(getBindingMiddlewareConfigs(binding), this.createDeclaredMiddlewareResolverOptions(binding));
434
412
  const automaticMiddleware = isLangChainBinding(binding)
435
413
  ? await this.resolveLangChainAutomaticMiddleware(binding)
436
- : await this.resolveDeepAgentAutomaticMiddleware(binding);
414
+ : [];
437
415
  const middleware = [
438
416
  ...declarativeMiddleware,
439
417
  ...automaticMiddleware,
@@ -444,9 +422,6 @@ export class AgentRuntimeAdapter {
444
422
  }
445
423
  return middleware;
446
424
  }
447
- resolveCheckpointer(binding) {
448
- return this.options.checkpointerResolver ? this.options.checkpointerResolver(binding) : new MemorySaver();
449
- }
450
425
  async resolveSubagents(subagents, binding) {
451
426
  return Promise.all(subagents.map(async (subagent) => ({
452
427
  ...subagent,
@@ -459,27 +434,15 @@ export class AgentRuntimeAdapter {
459
434
  ownerId: `${binding?.agent.id ?? "agent"}-${subagent.name}`,
460
435
  skillPaths: subagent.skills,
461
436
  }),
462
- interruptOn: this.compileInterruptOn(subagent.tools ?? [], subagent.interruptOn),
437
+ interruptOn: compileInterruptOn(subagent.tools ?? [], subagent.interruptOn),
463
438
  responseFormat: subagent.responseFormat,
464
439
  contextSchema: subagent.contextSchema,
465
- middleware: (await resolveDeclaredMiddleware(subagent.middleware, {
466
- resolveModel: (model) => this.resolveModel(model),
467
- resolveBackend: (resolvedBinding) => {
468
- const targetBinding = resolvedBinding ?? binding;
469
- return targetBinding ? this.options.backendResolver?.(targetBinding) : undefined;
470
- },
471
- resolveFilesystemBackend: (resolvedBinding) => {
472
- const targetBinding = resolvedBinding ?? binding;
473
- return targetBinding ? this.resolveFilesystemBackend(targetBinding) : undefined;
474
- },
475
- resolveCustom: this.options.declaredMiddlewareResolver,
476
- binding,
477
- })),
440
+ middleware: (await resolveDeclaredMiddleware(subagent.middleware, this.createDeclaredMiddlewareResolverOptions(binding))),
478
441
  })));
479
442
  }
480
443
  async createLangChainRunnable(binding, options = {}) {
481
444
  const params = getBindingLangChainParams(binding);
482
- const interruptOn = this.resolveInterruptOn(binding);
445
+ const interruptOn = compileInterruptOn(getBindingPrimaryTools(binding), getBindingInterruptCompatibilityRules(binding));
483
446
  const model = (await this.resolveModel(params.model));
484
447
  const tools = this.resolveTools(params.tools, binding);
485
448
  if (tools.length > 0 && typeof model.bindTools !== "function") {
@@ -490,90 +453,12 @@ export class AgentRuntimeAdapter {
490
453
  resolvedModel: model,
491
454
  resolvedTools: tools,
492
455
  resolvedMiddleware: await this.resolveMiddleware(binding, interruptOn),
493
- resolvedCheckpointer: this.resolveCheckpointer(binding),
456
+ resolvedCheckpointer: this.options.checkpointerResolver ? this.options.checkpointerResolver(binding) : new MemorySaver(),
494
457
  resolvedStore: this.options.storeResolver?.(binding),
495
458
  passthroughOverride: options.passthroughOverride,
496
459
  systemPromptOverride: options.systemPromptOverride,
497
460
  }));
498
461
  }
499
- extractInvocationRequestText(request) {
500
- if (!isRecord(request) || !Array.isArray(request.messages)) {
501
- return "";
502
- }
503
- for (let index = request.messages.length - 1; index >= 0; index -= 1) {
504
- const message = request.messages[index];
505
- if (!isRecord(message)) {
506
- continue;
507
- }
508
- const role = typeof message.role === "string" ? message.role : undefined;
509
- if (role !== "user") {
510
- continue;
511
- }
512
- return extractMessageText(message.content);
513
- }
514
- return "";
515
- }
516
- prependSystemMessage(request, content) {
517
- if (!content.trim() || !isRecord(request) || !Array.isArray(request.messages)) {
518
- return request;
519
- }
520
- return {
521
- ...request,
522
- messages: [{ role: "system", content }, ...request.messages],
523
- };
524
- }
525
- replaceLastUserMessage(request, content) {
526
- if (!content.trim() || !isRecord(request) || !Array.isArray(request.messages)) {
527
- return request;
528
- }
529
- const messages = [...request.messages];
530
- for (let index = messages.length - 1; index >= 0; index -= 1) {
531
- const message = messages[index];
532
- if (!isRecord(message) || message.role !== "user") {
533
- continue;
534
- }
535
- messages[index] = {
536
- ...message,
537
- content,
538
- };
539
- return {
540
- ...request,
541
- messages,
542
- };
543
- }
544
- return {
545
- ...request,
546
- messages: [...messages, { role: "user", content }],
547
- };
548
- }
549
- extractExecutedToolResults(result) {
550
- const metadata = asObject(result?.metadata);
551
- if (Array.isArray(metadata?.executedToolResults)) {
552
- return metadata.executedToolResults;
553
- }
554
- const messages = Array.isArray(result?.messages) ? result.messages : [];
555
- return messages.flatMap((message) => {
556
- const typed = asObject(message);
557
- const kwargs = asObject(typed?.kwargs);
558
- const typeId = Array.isArray(typed?.id) ? typed.id.at(-1) : undefined;
559
- const runtimeType = typeof typed?.type === "string" ? typed.type : undefined;
560
- if (typeId !== "ToolMessage" && runtimeType !== "tool") {
561
- return [];
562
- }
563
- const toolName = typeof typed?.name === "string"
564
- ? typed.name
565
- : typeof kwargs?.name === "string"
566
- ? kwargs.name
567
- : "tool";
568
- const output = typed?.content ??
569
- kwargs?.content ??
570
- "";
571
- return [{
572
- toolName,
573
- output,
574
- }];
575
- });
576
- }
577
462
  async createRunnable(binding) {
578
463
  if (getBindingAdapterKind(binding) === "langgraph") {
579
464
  throw new Error(`Agent ${binding.agent.id} uses removed backend langgraph; use langchain-v1 or deepagent`);
@@ -595,10 +480,10 @@ export class AgentRuntimeAdapter {
595
480
  resolvedTools: this.resolveTools(compatibleParams.tools, binding),
596
481
  resolvedMiddleware: await this.resolveMiddleware(binding),
597
482
  resolvedSubagents: await this.resolveSubagents(compatibleParams.subagents, binding),
598
- resolvedCheckpointer: this.resolveCheckpointer(binding),
483
+ resolvedCheckpointer: this.options.checkpointerResolver ? this.options.checkpointerResolver(binding) : new MemorySaver(),
599
484
  resolvedStore: this.options.storeResolver?.(binding),
600
485
  resolvedBackend: this.options.backendResolver?.(binding),
601
- resolvedInterruptOn: this.resolveInterruptOn(binding),
486
+ resolvedInterruptOn: compileInterruptOn(getBindingPrimaryTools(binding), getBindingInterruptCompatibilityRules(binding)),
602
487
  resolvedSkills: (await materializeDeepAgentSkillSourcePaths({
603
488
  workspaceRoot: binding.harnessRuntime.workspaceRoot,
604
489
  runRoot: binding.harnessRuntime.runRoot,
@@ -625,7 +510,7 @@ export class AgentRuntimeAdapter {
625
510
  }
626
511
  async invoke(binding, input, threadId, runId, resumePayload, history = [], options = {}) {
627
512
  const request = resumePayload === undefined
628
- ? this.buildInvocationRequest(binding, history, input, options)
513
+ ? buildInvocationRequest(binding, history, input, options)
629
514
  : new Command({ resume: resumePayload });
630
515
  let result;
631
516
  const callRuntime = async (activeBinding, activeRequest) => {
@@ -657,7 +542,7 @@ export class AgentRuntimeAdapter {
657
542
  }
658
543
  else {
659
544
  const resolvedTools = this.resolveTools(primaryTools, binding);
660
- const toolNameMapping = this.buildToolNameMapping(primaryTools);
545
+ const toolNameMapping = buildToolNameMapping(primaryTools);
661
546
  const executableTools = new Map();
662
547
  const builtinExecutableTools = await this.resolveBuiltinMiddlewareTools(binding, options);
663
548
  for (let index = 0; index < primaryTools.length; index += 1) {
@@ -720,7 +605,7 @@ export class AgentRuntimeAdapter {
720
605
  const streamIdleTimeoutMs = resolveStreamIdleTimeout(binding);
721
606
  const streamDeadlineAt = invokeTimeoutMs ? Date.now() + invokeTimeoutMs : undefined;
722
607
  const primaryTools = getBindingPrimaryTools(binding);
723
- const toolNameMapping = this.buildToolNameMapping(primaryTools);
608
+ const toolNameMapping = buildToolNameMapping(primaryTools);
724
609
  const primaryModel = getBindingPrimaryModel(binding);
725
610
  const forceInvokeFallback = isLangChainBinding(binding) &&
726
611
  primaryTools.length > 0 &&
@@ -738,7 +623,7 @@ export class AgentRuntimeAdapter {
738
623
  // For tool-using langchain agents, a raw model.stream pass cannot execute the
739
624
  // agent loop and only adds an extra model round-trip before the runnable path.
740
625
  if (canUseDirectModelStream && typeof model.stream === "function") {
741
- const stream = await this.withTimeout(() => model.stream(this.buildRawModelMessages(binding, getBindingSystemPrompt(binding), history, input)), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "model stream start", "stream");
626
+ const stream = await this.withTimeout(() => model.stream(buildRawModelMessages(binding, getBindingSystemPrompt(binding), history, input)), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "model stream start", "stream");
742
627
  let emitted = false;
743
628
  const projected = projectTextStreamChunks(this.iterateWithTimeout(stream, streamIdleTimeoutMs, "model stream", streamDeadlineAt, invokeTimeoutMs));
744
629
  let nextChunk = await projected.next();
@@ -755,7 +640,7 @@ export class AgentRuntimeAdapter {
755
640
  }
756
641
  }
757
642
  const runnable = await this.create(binding);
758
- const request = this.buildInvocationRequest(binding, history, input, options);
643
+ const request = buildInvocationRequest(binding, history, input, options);
759
644
  if (!forceInvokeFallback && typeof runnable.streamEvents === "function") {
760
645
  const events = await this.withTimeout(() => runnable.streamEvents(request, { configurable: { thread_id: threadId, run_id: options.runId }, version: "v2", ...(options.context ? { context: options.context } : {}) }), computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs), "agent streamEvents start", "stream");
761
646
  const projectionState = createStreamEventProjectionState();
@@ -0,0 +1,42 @@
1
+ import type { MessageContent, RunResult, ThreadSummary, WorkspaceBundle } from "../../../contracts/types.js";
2
+ import type { RuntimePersistence } from "../../../persistence/types.js";
3
+ import type { AgentRuntimeAdapter } from "../../agent-runtime-adapter.js";
4
+ import type { ConcurrencyConfig, RecoveryConfig } from "../../../workspace/support/workspace-ref-utils.js";
5
+ type RecoveryBinding = WorkspaceBundle["bindings"] extends Map<any, infer T> ? T : never;
6
+ type StartupRecoveryContext = {
7
+ persistence: RuntimePersistence;
8
+ workspace: WorkspaceBundle;
9
+ runtimeAdapter: AgentRuntimeAdapter;
10
+ recoveryConfig: RecoveryConfig;
11
+ concurrencyConfig: ConcurrencyConfig;
12
+ getBinding: (agentId: string) => RecoveryBinding | undefined;
13
+ acquireRunSlot: (threadId?: string, runId?: string, activeState?: RunResult["state"], priority?: number) => Promise<() => Promise<void>>;
14
+ executeQueuedRun: (binding: RecoveryBinding, input: MessageContent, threadId: string, runId: string, agentId: string, options?: {
15
+ context?: Record<string, unknown>;
16
+ state?: Record<string, unknown>;
17
+ files?: Record<string, unknown>;
18
+ previousState?: RunResult["state"];
19
+ stateSequence?: number;
20
+ approvalSequence?: number;
21
+ }) => Promise<RunResult>;
22
+ setRunStateAndEmit: (threadId: string, runId: string, sequence: number, state: RunResult["state"], options: {
23
+ previousState: string | null;
24
+ checkpointRef?: string | null;
25
+ error?: string;
26
+ }) => Promise<unknown>;
27
+ emit: (threadId: string, runId: string, sequence: number, eventType: string, payload: Record<string, unknown>) => Promise<unknown>;
28
+ loadRunInput: (threadId: string, runId: string) => Promise<MessageContent>;
29
+ finalizeContinuedRun: (binding: RecoveryBinding, threadId: string, runId: string, input: MessageContent, actual: RunResult, options: {
30
+ previousState: RunResult["state"] | null;
31
+ stateSequence: number;
32
+ approvalSequence?: number;
33
+ }) => Promise<RunResult>;
34
+ supportsRunningReplay: (binding: RecoveryBinding) => boolean;
35
+ isStaleRunningRun: (thread: ThreadSummary, nowMs?: number) => Promise<boolean>;
36
+ recordLlmSuccess: (startedAt: number) => void;
37
+ recordLlmFailure: (startedAt: number) => void;
38
+ };
39
+ export declare function recoverQueuedStartupRun(context: StartupRecoveryContext, thread: ThreadSummary): Promise<boolean>;
40
+ export declare function recoverRunningStartupRun(context: StartupRecoveryContext, thread: ThreadSummary): Promise<boolean>;
41
+ export declare function recoverResumingStartupRun(context: StartupRecoveryContext, thread: ThreadSummary): Promise<boolean>;
42
+ export {};