@botbotgo/agent-harness 0.0.99 → 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.
Files changed (74) hide show
  1. package/README.md +3 -6
  2. package/README.zh.md +2 -2
  3. package/dist/benchmark/upstream-runtime-ab-benchmark.d.ts +1 -1
  4. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -2
  5. package/dist/contracts/core.d.ts +2 -2
  6. package/dist/contracts/runtime.d.ts +1 -5
  7. package/dist/package-version.d.ts +1 -1
  8. package/dist/package-version.js +1 -1
  9. package/dist/resource/resource-impl.js +78 -76
  10. package/dist/runtime/adapter/deepagent-runnable-config.d.ts +30 -0
  11. package/dist/runtime/adapter/deepagent-runnable-config.js +22 -0
  12. package/dist/runtime/adapter/index.d.ts +0 -2
  13. package/dist/runtime/adapter/index.js +0 -2
  14. package/dist/runtime/adapter/invocation-result.d.ts +13 -0
  15. package/dist/runtime/adapter/invocation-result.js +40 -0
  16. package/dist/runtime/adapter/langchain-runnable-config.d.ts +25 -0
  17. package/dist/runtime/adapter/langchain-runnable-config.js +19 -0
  18. package/dist/runtime/adapter/local-tool-invocation.d.ts +23 -0
  19. package/dist/runtime/adapter/local-tool-invocation.js +64 -0
  20. package/dist/runtime/adapter/runtime-adapter-support.d.ts +18 -0
  21. package/dist/runtime/adapter/runtime-adapter-support.js +54 -0
  22. package/dist/runtime/adapter/stream-event-projection.d.ts +19 -0
  23. package/dist/runtime/adapter/stream-event-projection.js +79 -0
  24. package/dist/runtime/adapter/stream-text-consumption.d.ts +4 -0
  25. package/dist/runtime/adapter/stream-text-consumption.js +18 -0
  26. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +64 -0
  27. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +144 -0
  28. package/dist/runtime/adapter/tool/tool-replay.d.ts +18 -0
  29. package/dist/runtime/adapter/tool/tool-replay.js +26 -0
  30. package/dist/runtime/agent-runtime-adapter.d.ts +2 -54
  31. package/dist/runtime/agent-runtime-adapter.js +122 -1568
  32. package/dist/runtime/harness/run/helpers.js +2 -8
  33. package/dist/runtime/harness/run/recovery.d.ts +42 -0
  34. package/dist/runtime/harness/run/recovery.js +139 -0
  35. package/dist/runtime/harness/run/routing.d.ts +1 -3
  36. package/dist/runtime/harness/run/routing.js +2 -25
  37. package/dist/runtime/harness/run/run-lifecycle.d.ts +0 -11
  38. package/dist/runtime/harness/run/run-lifecycle.js +7 -50
  39. package/dist/runtime/harness/runtime-defaults.d.ts +4 -0
  40. package/dist/runtime/harness/runtime-defaults.js +39 -0
  41. package/dist/runtime/harness/system/inventory.js +2 -1
  42. package/dist/runtime/harness/system/skill-requirements.d.ts +1 -0
  43. package/dist/runtime/harness.d.ts +5 -24
  44. package/dist/runtime/harness.js +356 -536
  45. package/dist/runtime/index.d.ts +1 -12
  46. package/dist/runtime/index.js +1 -12
  47. package/dist/runtime/support/compiled-binding.d.ts +0 -2
  48. package/dist/runtime/support/compiled-binding.js +3 -22
  49. package/dist/runtime/support/harness-support.d.ts +0 -11
  50. package/dist/runtime/support/harness-support.js +1 -44
  51. package/dist/runtime/support/index.d.ts +1 -1
  52. package/dist/runtime/support/index.js +1 -1
  53. package/dist/runtime/support/runtime-factories.js +2 -2
  54. package/dist/workspace/agent-binding-compiler.js +9 -93
  55. package/dist/workspace/index.d.ts +0 -5
  56. package/dist/workspace/index.js +0 -5
  57. package/dist/workspace/object-loader.js +44 -99
  58. package/dist/workspace/support/agent-capabilities.js +2 -2
  59. package/dist/workspace/support/workspace-ref-utils.d.ts +0 -2
  60. package/dist/workspace/support/workspace-ref-utils.js +0 -17
  61. package/dist/workspace/validate.js +1 -1
  62. package/package.json +1 -1
  63. package/dist/config/workflows/langgraph-workflows.yaml +0 -570
  64. package/dist/config/workflows/runtime-profiles.yaml +0 -94
  65. package/dist/runtime/adapter/langgraph/presets.d.ts +0 -25
  66. package/dist/runtime/adapter/langgraph/presets.js +0 -165
  67. package/dist/runtime/adapter/langgraph/profiles.d.ts +0 -6
  68. package/dist/runtime/adapter/langgraph/profiles.js +0 -206
  69. package/dist/runtime/checkpoint-maintenance.d.ts +0 -1
  70. package/dist/runtime/checkpoint-maintenance.js +0 -1
  71. package/dist/runtime/file-checkpoint-saver.d.ts +0 -1
  72. package/dist/runtime/file-checkpoint-saver.js +0 -1
  73. package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +0 -1
  74. package/dist/runtime/sqlite-maintained-checkpoint-saver.js +0 -1
package/README.md CHANGED
@@ -79,7 +79,7 @@ Boundary documents live in:
79
79
  - `docs/model-layering.md`
80
80
  - `docs/coding-agent-guide.md`
81
81
 
82
- ACP is the intended future client protocol direction when external tools need a standard runtime boundary. The harness should become ACP-capable while keeping runtime lifecycle, persistence, recovery, and governance harness-owned.
82
+ `deepagents-acp` is the required external protocol direction when external tools need a standard runtime boundary. The harness should conform to `deepagents-acp` semantics at that boundary while keeping runtime lifecycle, persistence, recovery, and governance harness-owned.
83
83
 
84
84
  Recommended orchestration shape for long-running flows:
85
85
 
@@ -262,7 +262,7 @@ const result = await run(runtime, {
262
262
  });
263
263
  ```
264
264
 
265
- `agentId: "auto"` evaluates ordered routing rules in `config/runtime/workspace.yaml`, then `routing.defaultAgentId`, and only falls back to model routing when `routing.modelRouting: true`.
265
+ `agentId: "auto"` evaluates ordered routing rules in `config/runtime/workspace.yaml`, then `routing.defaultAgentId`, and otherwise falls back to the default runtime entry host.
266
266
 
267
267
  ### Stream Output And Events
268
268
 
@@ -416,8 +416,6 @@ Important fields:
416
416
  - `concurrency.maxConcurrentRuns`
417
417
  - `routing.defaultAgentId`
418
418
  - `routing.rules`
419
- - `routing.systemPrompt`
420
- - `routing.modelRouting`
421
419
  - `maintenance.checkpoints`
422
420
  - `maintenance.records`
423
421
  - `recovery.enabled`
@@ -444,7 +442,6 @@ spec:
444
442
  maxConcurrentRuns: 3
445
443
  routing:
446
444
  defaultAgentId: orchestra
447
- modelRouting: false
448
445
  maintenance:
449
446
  checkpoints:
450
447
  enabled: true
@@ -639,7 +636,7 @@ For backend-specific options, prefer the upstream concept directly inside `spec.
639
636
  - `agent-harness` is not a third agent framework
640
637
  - public runtime contract stays generic and small
641
638
  - application-level orchestration and lifecycle management stays in the harness
642
- - ACP should be the preferred future external client protocol instead of a parallel harness-only protocol
639
+ - the external protocol boundary should strictly conform to `deepagents-acp` instead of a parallel harness-only protocol
643
640
  - upstream LangChain v1 and DeepAgents concepts should be expressed as directly as possible in YAML
644
641
  - when a feature can be expressed in YAML, prefer YAML over expanding the public API
645
642
  - recovery, approvals, threads, runs, and events are runtime concepts, not backend escape hatches
package/README.zh.md CHANGED
@@ -79,7 +79,7 @@
79
79
  - `docs/model-layering.md`
80
80
  - `docs/coding-agent-guide.md`
81
81
 
82
- 当外部工具需要标准运行时边界时,ACP 是预期的未来客户端协议方向。`agent-harness` 应该具备 ACP 能力,同时继续把运行时生命周期、持久化、恢复与治理保留在 harness 内部。
82
+ 当外部工具需要标准运行时边界时,`deepagents-acp` 是必须遵循的外部协议方向。`agent-harness` 应在该边界上严格契合 `deepagents-acp` 语义,同时继续把运行时生命周期、持久化、恢复与治理保留在 harness 内部。
83
83
 
84
84
  长链路编排的推荐形态:
85
85
 
@@ -633,7 +633,7 @@ spec:
633
633
  - `agent-harness` 不是第三个 agent 框架
634
634
  - 公共运行时契约保持通用且精简
635
635
  - 应用级编排与生命周期管理留在 harness 中
636
- - ACP 应作为优先对齐的未来外部客户端协议,而不是再做一套并行的 harness 私有协议
636
+ - 外部协议边界应严格契合 `deepagents-acp`,而不是再做一套并行的 harness 私有协议
637
637
  - 应尽量在 YAML 中直接表达 LangChain v1 与 DeepAgents 的概念
638
638
  - 能用 YAML 表达的能力,优先 YAML 而非扩张公共 API
639
639
  - 恢复、审批、线程、运行与事件是运行时概念,不是后端逃生舱
@@ -1,4 +1,4 @@
1
- export declare const DEFAULT_UPSTREAM_BENCHMARK_PATHS: readonly ["harness", "raw-langchain-v1", "raw-langgraph", "raw-deepagent"];
1
+ export declare const DEFAULT_UPSTREAM_BENCHMARK_PATHS: readonly ["harness", "raw-langchain-v1", "raw-deepagent"];
2
2
  export declare const DEFAULT_UPSTREAM_BENCHMARK_WORKLOAD: "tool";
3
3
  export type UpstreamBenchmarkPath = (typeof DEFAULT_UPSTREAM_BENCHMARK_PATHS)[number];
4
4
  export type UpstreamBenchmarkWorkload = "tool" | "no-tool";
@@ -1,7 +1,6 @@
1
1
  export const DEFAULT_UPSTREAM_BENCHMARK_PATHS = Object.freeze([
2
2
  "harness",
3
3
  "raw-langchain-v1",
4
- "raw-langgraph",
5
4
  "raw-deepagent",
6
5
  ]);
7
6
  export const DEFAULT_UPSTREAM_BENCHMARK_WORKLOAD = "tool";
@@ -48,7 +47,7 @@ export function resolveUpstreamBenchmarkPaths(rawValue) {
48
47
  const parsed = rawValue
49
48
  .split(",")
50
49
  .map((value) => value.trim().toLowerCase())
51
- .filter((value) => value === "harness" || value === "raw-langchain-v1" || value === "raw-langgraph" || value === "raw-deepagent");
50
+ .filter((value) => value === "harness" || value === "raw-langchain-v1" || value === "raw-deepagent");
52
51
  return parsed.length > 0 ? parsed : [...DEFAULT_UPSTREAM_BENCHMARK_PATHS];
53
52
  }
54
53
  export function resolveUpstreamBenchmarkWorkload(rawValue) {
@@ -1,6 +1,6 @@
1
- export type ExecutionMode = "deepagent" | "langchain-v1" | "langgraph";
1
+ export type ExecutionMode = "deepagent" | "langchain-v1";
2
2
  export declare const AUTO_AGENT_ID = "auto";
3
- export type RuntimeModelSlot = "routing" | "planning" | "execution" | "review" | "final";
3
+ export type RuntimeModelSlot = "planning" | "execution" | "review" | "final";
4
4
  export type RuntimeModelRefMap = Partial<Record<RuntimeModelSlot, string>>;
5
5
  export type RuntimeCapabilities = {
6
6
  delegation?: boolean;
@@ -9,7 +9,7 @@ export type ThreadSummary = {
9
9
  status: RunState;
10
10
  };
11
11
  export type SessionRecord = ThreadSummary;
12
- export type KnownHarnessEventType = "run.created" | "run.queued" | "run.dequeued" | "run.state.changed" | "run.reviewed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "reasoning.delta" | "runtime.health.changed" | "runtime.synthetic_fallback";
12
+ export type KnownHarnessEventType = "run.created" | "run.queued" | "run.dequeued" | "run.state.changed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "reasoning.delta" | "runtime.health.changed" | "runtime.synthetic_fallback";
13
13
  export type HarnessEventType = KnownHarnessEventType | (string & {});
14
14
  export type HarnessEvent = {
15
15
  eventId: string;
@@ -190,8 +190,6 @@ export type RunStartOptions = {
190
190
  priority?: number;
191
191
  invocation?: InvocationEnvelope;
192
192
  listeners?: RunListeners;
193
- runtimeListeners?: RuntimeListeners;
194
- frontendListeners?: FrontendStreamListeners;
195
193
  };
196
194
  export type RunDecisionOptions = {
197
195
  threadId: string;
@@ -200,8 +198,6 @@ export type RunDecisionOptions = {
200
198
  decision: "approve" | "edit" | "reject";
201
199
  editedInput?: Record<string, unknown>;
202
200
  listeners?: RunListeners;
203
- runtimeListeners?: RuntimeListeners;
204
- frontendListeners?: FrontendStreamListeners;
205
201
  };
206
202
  export type RunOptions = RunStartOptions | RunDecisionOptions;
207
203
  export type HarnessStreamItem = {
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.98";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.100";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.98";
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),
@@ -0,0 +1,30 @@
1
+ import type { DeepAgentParams } from "../../contracts/types.js";
2
+ export declare function buildDeepAgentRunnableConfig(params: {
3
+ compatibleParams: DeepAgentParams;
4
+ resolvedModel: unknown;
5
+ resolvedTools: unknown[];
6
+ resolvedMiddleware: unknown[];
7
+ resolvedSubagents: unknown[];
8
+ resolvedCheckpointer: unknown;
9
+ resolvedStore: unknown;
10
+ resolvedBackend: unknown;
11
+ resolvedInterruptOn: unknown;
12
+ resolvedSkills: string[];
13
+ }): {
14
+ model: never;
15
+ tools: never;
16
+ systemPrompt: string | undefined;
17
+ responseFormat: never;
18
+ contextSchema: never;
19
+ middleware: never;
20
+ subagents: never;
21
+ checkpointer: never;
22
+ store: never;
23
+ backend: never;
24
+ interruptOn: never;
25
+ name: string;
26
+ memory: string[];
27
+ skills: string[];
28
+ generalPurposeAgent: boolean | undefined;
29
+ taskDescription: string | undefined;
30
+ };
@@ -0,0 +1,22 @@
1
+ export function buildDeepAgentRunnableConfig(params) {
2
+ const { compatibleParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedSubagents, resolvedCheckpointer, resolvedStore, resolvedBackend, resolvedInterruptOn, resolvedSkills, } = params;
3
+ return {
4
+ ...(compatibleParams.passthrough ?? {}),
5
+ model: resolvedModel,
6
+ tools: resolvedTools,
7
+ systemPrompt: compatibleParams.systemPrompt,
8
+ responseFormat: compatibleParams.responseFormat,
9
+ contextSchema: compatibleParams.contextSchema,
10
+ middleware: resolvedMiddleware,
11
+ subagents: resolvedSubagents,
12
+ checkpointer: resolvedCheckpointer,
13
+ store: resolvedStore,
14
+ backend: resolvedBackend,
15
+ interruptOn: resolvedInterruptOn,
16
+ name: compatibleParams.name,
17
+ memory: compatibleParams.memory,
18
+ skills: resolvedSkills,
19
+ generalPurposeAgent: compatibleParams.generalPurposeAgent,
20
+ taskDescription: compatibleParams.taskDescription,
21
+ };
22
+ }
@@ -2,8 +2,6 @@ export * from "./tool/declared-middleware.js";
2
2
  export * from "./compat/deepagent-compat.js";
3
3
  export * from "./tool/interrupt-policy.js";
4
4
  export * from "./model/invocation-request.js";
5
- export * from "./langgraph/presets.js";
6
- export * from "./langgraph/profiles.js";
7
5
  export * from "./model/message-assembly.js";
8
6
  export * from "./model/model-providers.js";
9
7
  export * from "./compat/openai-compatible.js";
@@ -2,8 +2,6 @@ export * from "./tool/declared-middleware.js";
2
2
  export * from "./compat/deepagent-compat.js";
3
3
  export * from "./tool/interrupt-policy.js";
4
4
  export * from "./model/invocation-request.js";
5
- export * from "./langgraph/presets.js";
6
- export * from "./langgraph/profiles.js";
7
5
  export * from "./model/message-assembly.js";
8
6
  export * from "./model/model-providers.js";
9
7
  export * from "./compat/openai-compatible.js";
@@ -0,0 +1,13 @@
1
+ import type { RunResult } from "../../contracts/types.js";
2
+ export type ExecutedToolResult = {
3
+ toolName: string;
4
+ output: unknown;
5
+ isError?: boolean;
6
+ };
7
+ export declare function finalizeInvocationResult(params: {
8
+ bindingAgentId: string;
9
+ threadId: string;
10
+ runId: string;
11
+ result: Record<string, unknown>;
12
+ executedToolResults: ExecutedToolResult[];
13
+ }): RunResult;
@@ -0,0 +1,40 @@
1
+ import { extractContentBlocks, extractEmptyAssistantMessageFailure, extractOutputContent, extractToolFallbackContext, extractVisibleOutput, isLikelyToolArgsObject, sanitizeVisibleText, tryParseJson, } from "../parsing/output-parsing.js";
2
+ import { buildStateSnapshot } from "./model/message-assembly.js";
3
+ import { asRecord } from "./tool/resolved-tool.js";
4
+ export function finalizeInvocationResult(params) {
5
+ const { bindingAgentId, threadId, runId, result, executedToolResults } = params;
6
+ const interruptContent = Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? JSON.stringify(result.__interrupt__) : undefined;
7
+ const extractedOutput = extractVisibleOutput(result);
8
+ const visibleOutput = extractedOutput && !isLikelyToolArgsObject(tryParseJson(extractedOutput)) ? extractedOutput : "";
9
+ const emptyAssistantMessageFailure = extractEmptyAssistantMessageFailure(result);
10
+ const toolFallback = extractToolFallbackContext(result);
11
+ if (!visibleOutput && !toolFallback && emptyAssistantMessageFailure) {
12
+ throw new Error(emptyAssistantMessageFailure);
13
+ }
14
+ const output = visibleOutput || toolFallback || JSON.stringify(result, null, 2);
15
+ const finalMessageText = sanitizeVisibleText(output);
16
+ const outputContent = extractOutputContent(result);
17
+ const contentBlocks = extractContentBlocks(result);
18
+ const structuredResponse = result.structuredResponse;
19
+ return {
20
+ threadId,
21
+ runId,
22
+ agentId: bindingAgentId,
23
+ state: Array.isArray(result.__interrupt__) && result.__interrupt__.length > 0 ? "waiting_for_approval" : "completed",
24
+ interruptContent,
25
+ output: finalMessageText,
26
+ finalMessageText,
27
+ ...(outputContent !== undefined ? { outputContent } : {}),
28
+ ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
29
+ ...(structuredResponse !== undefined ? { structuredResponse } : {}),
30
+ metadata: {
31
+ ...(executedToolResults.length > 0 ? { executedToolResults } : {}),
32
+ ...(structuredResponse !== undefined ? { structuredResponse } : {}),
33
+ ...(outputContent !== undefined ? { outputContent } : {}),
34
+ ...(contentBlocks.length > 0 ? { contentBlocks } : {}),
35
+ ...(asRecord(result.files) ? { files: asRecord(result.files) } : {}),
36
+ ...(buildStateSnapshot(result) ? { stateSnapshot: buildStateSnapshot(result) } : {}),
37
+ upstreamResult: result,
38
+ },
39
+ };
40
+ }
@@ -0,0 +1,25 @@
1
+ import type { LangChainAgentParams } from "../../contracts/types.js";
2
+ export declare function buildLangChainRunnableConfig(params: {
3
+ langchainParams: LangChainAgentParams;
4
+ resolvedModel: unknown;
5
+ resolvedTools: unknown[];
6
+ resolvedMiddleware: unknown[];
7
+ resolvedCheckpointer: unknown;
8
+ resolvedStore: unknown;
9
+ passthroughOverride?: Record<string, unknown>;
10
+ systemPromptOverride?: string;
11
+ }): {
12
+ model: never;
13
+ tools: never;
14
+ systemPrompt: string | undefined;
15
+ stateSchema: never;
16
+ responseFormat: never;
17
+ contextSchema: never;
18
+ middleware: never;
19
+ checkpointer: never;
20
+ store: never;
21
+ includeAgentName: "inline" | undefined;
22
+ version: "v1" | "v2" | undefined;
23
+ name: string | undefined;
24
+ description: string;
25
+ };
@@ -0,0 +1,19 @@
1
+ export function buildLangChainRunnableConfig(params) {
2
+ const { langchainParams, resolvedModel, resolvedTools, resolvedMiddleware, resolvedCheckpointer, resolvedStore, passthroughOverride, systemPromptOverride, } = params;
3
+ return {
4
+ ...(passthroughOverride ?? langchainParams.passthrough ?? {}),
5
+ model: resolvedModel,
6
+ tools: resolvedTools,
7
+ systemPrompt: systemPromptOverride ?? langchainParams.systemPrompt,
8
+ stateSchema: langchainParams.stateSchema,
9
+ responseFormat: langchainParams.responseFormat,
10
+ contextSchema: langchainParams.contextSchema,
11
+ middleware: resolvedMiddleware,
12
+ checkpointer: resolvedCheckpointer,
13
+ store: resolvedStore,
14
+ includeAgentName: langchainParams.includeAgentName,
15
+ version: langchainParams.version,
16
+ name: langchainParams.name,
17
+ description: langchainParams.description,
18
+ };
19
+ }
@@ -0,0 +1,23 @@
1
+ import type { CompiledAgentBinding, CompiledTool } from "../../contracts/types.js";
2
+ import { type ToolNameMapping } from "./tool/tool-name-mapping.js";
3
+ import type { ExecutedToolResult } from "./invocation-result.js";
4
+ type ExecutableTool = {
5
+ name: string;
6
+ schema: unknown;
7
+ invoke: (input: unknown) => Promise<unknown>;
8
+ };
9
+ type LocalToolInvocationParams = {
10
+ binding: CompiledAgentBinding;
11
+ request: unknown;
12
+ primaryTools: CompiledTool[];
13
+ toolNameMapping: ToolNameMapping;
14
+ executableTools: Map<string, ExecutableTool>;
15
+ builtinExecutableTools: Map<string, ExecutableTool>;
16
+ callRuntimeWithToolParseRecovery: (request: unknown) => Promise<Record<string, unknown>>;
17
+ };
18
+ type LocalToolInvocationResult = {
19
+ result: Record<string, unknown>;
20
+ executedToolResults: ExecutedToolResult[];
21
+ };
22
+ export declare function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, }: LocalToolInvocationParams): Promise<LocalToolInvocationResult>;
23
+ export {};
@@ -0,0 +1,64 @@
1
+ import { ToolMessage } from "@langchain/core/messages";
2
+ import { createModelFacingToolNameLookupCandidates, resolveModelFacingToolName } from "./tool/tool-name-mapping.js";
3
+ import { canReplayToolCallsLocally } from "./tool/tool-replay.js";
4
+ import { extractToolCallsFromResult, normalizeToolArgsForSchema, stringifyToolOutput } from "./tool/tool-arguments.js";
5
+ export async function runLocalToolInvocationLoop({ binding, request, primaryTools, toolNameMapping, executableTools, builtinExecutableTools, callRuntimeWithToolParseRecovery, }) {
6
+ const executedToolResults = [];
7
+ let activeRequest = request;
8
+ let currentMessages = Array.isArray(activeRequest.messages) ? [...activeRequest.messages] : [];
9
+ const maxToolIterations = 8;
10
+ let pendingResult;
11
+ let result;
12
+ for (let iteration = 0; iteration < maxToolIterations; iteration += 1) {
13
+ result = pendingResult ?? await callRuntimeWithToolParseRecovery(activeRequest);
14
+ pendingResult = undefined;
15
+ const toolCalls = extractToolCallsFromResult(result);
16
+ if (toolCalls.length === 0) {
17
+ break;
18
+ }
19
+ if (!canReplayToolCallsLocally(binding, toolCalls, primaryTools, toolNameMapping, executableTools, builtinExecutableTools)) {
20
+ break;
21
+ }
22
+ if (iteration + 1 === maxToolIterations) {
23
+ throw new Error(`Tool-calling loop exceeded the maximum of ${maxToolIterations} iterations`);
24
+ }
25
+ const resultMessages = result.messages;
26
+ const nextMessages = Array.isArray(resultMessages)
27
+ ? [...resultMessages]
28
+ : [...currentMessages];
29
+ for (let toolIndex = 0; toolIndex < toolCalls.length; toolIndex += 1) {
30
+ const toolCall = toolCalls[toolIndex];
31
+ const resolvedToolName = resolveModelFacingToolName(toolCall.name, toolNameMapping, primaryTools);
32
+ const executable = executableTools.get(toolCall.name) ?? executableTools.get(resolvedToolName);
33
+ const builtinExecutable = builtinExecutableTools.get(toolCall.name) ??
34
+ builtinExecutableTools.get(resolvedToolName) ??
35
+ createModelFacingToolNameLookupCandidates(toolCall.name)
36
+ .map((candidate) => builtinExecutableTools.get(candidate))
37
+ .find((candidate) => candidate !== undefined);
38
+ const activeExecutable = executable ?? builtinExecutable;
39
+ if (!activeExecutable) {
40
+ throw new Error(`Tool ${toolCall.name} is not configured for this agent.`);
41
+ }
42
+ const normalizedArgs = normalizeToolArgsForSchema(toolCall.args, activeExecutable.schema);
43
+ const toolResult = await activeExecutable.invoke(normalizedArgs);
44
+ executedToolResults.push({
45
+ toolName: activeExecutable.name,
46
+ output: toolResult,
47
+ });
48
+ nextMessages.push(new ToolMessage({
49
+ name: activeExecutable.name,
50
+ tool_call_id: toolCall.id ?? `tool-${iteration + 1}-${toolIndex + 1}`,
51
+ content: stringifyToolOutput(toolResult),
52
+ }));
53
+ }
54
+ currentMessages = nextMessages;
55
+ activeRequest = {
56
+ ...activeRequest,
57
+ messages: currentMessages,
58
+ };
59
+ }
60
+ if (!result) {
61
+ throw new Error("Agent invocation returned no result");
62
+ }
63
+ return { result, executedToolResults };
64
+ }