@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.
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/resource/resource-impl.js +78 -76
- package/dist/runtime/agent-runtime-adapter.d.ts +1 -12
- package/dist/runtime/agent-runtime-adapter.js +33 -148
- package/dist/runtime/harness/run/recovery.d.ts +42 -0
- package/dist/runtime/harness/run/recovery.js +139 -0
- package/dist/runtime/harness.d.ts +2 -17
- package/dist/runtime/harness.js +306 -473
- package/dist/runtime/support/runtime-factories.js +2 -2
- package/dist/workspace/object-loader.js +40 -78
- package/package.json +1 -1
- package/dist/runtime/checkpoint-maintenance.d.ts +0 -1
- package/dist/runtime/checkpoint-maintenance.js +0 -1
- package/dist/runtime/file-checkpoint-saver.d.ts +0 -1
- package/dist/runtime/file-checkpoint-saver.js +0 -1
- package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +0 -1
- package/dist/runtime/sqlite-maintained-checkpoint-saver.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.100";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
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
|
|
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
|
|
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
|
|
190
|
+
return createInlineBackendInstance(workspace.workspaceRoot, "LocalShellBackend", backendConfig, runtimeLike);
|
|
193
191
|
case "VfsSandbox":
|
|
194
|
-
return
|
|
192
|
+
return createInlineBackendInstance(workspace.workspaceRoot, "VfsSandbox", backendConfig, runtimeLike);
|
|
195
193
|
case "StateBackend":
|
|
196
|
-
return
|
|
194
|
+
return createInlineBackendInstance(workspace.workspaceRoot, "StateBackend", backendConfig, runtimeLike);
|
|
197
195
|
case "StoreBackend":
|
|
198
|
-
return
|
|
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,
|
|
207
|
+
return [route, createInlineBackendInstance(workspace.workspaceRoot, routeKind, routeConfig, runtimeLike)];
|
|
210
208
|
}));
|
|
211
|
-
return new CompatibleCompositeBackend(
|
|
209
|
+
return new CompatibleCompositeBackend(createInlineBackendInstance(workspace.workspaceRoot, defaultBackendKind, stateConfig, runtimeLike), mappedRoutes);
|
|
212
210
|
}
|
|
213
211
|
default:
|
|
214
|
-
|
|
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:
|
|
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:
|
|
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?.()
|
|
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?.()
|
|
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
|
|
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
|
|
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,
|
|
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 {
|
|
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 =
|
|
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:
|
|
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
|
-
:
|
|
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:
|
|
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 =
|
|
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.
|
|
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.
|
|
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:
|
|
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
|
-
?
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 {};
|