@botbotgo/agent-harness 0.0.23 → 0.0.25

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/README.md CHANGED
@@ -195,6 +195,8 @@ const server = await createToolMcpServer(harness, { agentId: "orchestra" });
195
195
  await serveToolsOverStdio(harness, { agentId: "orchestra" });
196
196
  ```
197
197
 
198
+ If you omit `serverInfo`, the harness uses `agent-harness-<agentId>` as the MCP server name and the current package version as the server version.
199
+
198
200
  ### Read Back Thread State
199
201
 
200
202
  ```ts
package/dist/mcp.js CHANGED
@@ -2,6 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import { z } from "zod";
5
+ import { AGENT_HARNESS_VERSION } from "./package-version.js";
5
6
  import { loadToolModuleDefinition } from "./tool-modules.js";
6
7
  function asResolvedTool(value) {
7
8
  return typeof value === "object" && value !== null ? value : null;
@@ -86,7 +87,7 @@ function jsonSchemaToZod(schema) {
86
87
  export async function createToolMcpServerFromHarness(harness, options) {
87
88
  const server = new McpServer({
88
89
  name: options.serverInfo?.name ?? `agent-harness-${options.agentId}`,
89
- version: options.serverInfo?.version ?? "0.0.16",
90
+ version: options.serverInfo?.version ?? AGENT_HARNESS_VERSION,
90
91
  });
91
92
  const allowedNames = options.includeToolNames ? new Set(options.includeToolNames) : null;
92
93
  for (const { compiledTool, resolvedTool } of harness.resolveAgentTools(options.agentId)) {
@@ -0,0 +1 @@
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.24";
@@ -0,0 +1 @@
1
+ export const AGENT_HARNESS_VERSION = "0.0.24";
@@ -1,14 +1,16 @@
1
- import { existsSync } from "node:fs";
1
+ import { existsSync, mkdirSync } from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import path from "node:path";
4
4
  import { stat } from "node:fs/promises";
5
5
  import { readFile } from "node:fs/promises";
6
6
  import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import { CompositeBackend, LocalShellBackend, StateBackend, StoreBackend } from "deepagents";
7
8
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
8
9
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
9
10
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
10
11
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
11
12
  import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
13
+ import { AGENT_HARNESS_VERSION } from "../package-version.js";
12
14
  import { isSupportedToolModulePath, loadToolModuleDefinition } from "../tool-modules.js";
13
15
  import { resolveIsolatedResourceModulePath } from "./isolation.js";
14
16
  import { ensureExternalResourceSource, ensureExternalSource, isExternalSourceLocator, parseExternalSourceLocator } from "./sources.js";
@@ -61,6 +63,113 @@ function createProviderBackendResolver(provider, workspace) {
61
63
  return (provider?.createResourceBackendResolver?.(workspace) ??
62
64
  provider?.createBuiltinBackendResolver?.(workspace));
63
65
  }
66
+ class CompatibleCompositeBackend {
67
+ id;
68
+ execute;
69
+ composite;
70
+ constructor(defaultBackend, routes) {
71
+ this.composite = new CompositeBackend(defaultBackend, routes);
72
+ const sandboxLike = defaultBackend;
73
+ if (typeof sandboxLike.id === "string" && typeof sandboxLike.execute === "function") {
74
+ this.id = sandboxLike.id;
75
+ this.execute = (command) => this.composite.execute(command);
76
+ }
77
+ }
78
+ lsInfo(filePath) {
79
+ return this.composite.lsInfo(filePath);
80
+ }
81
+ read(filePath, offset, limit) {
82
+ return this.composite.read(filePath, offset, limit);
83
+ }
84
+ readRaw(filePath) {
85
+ return this.composite.readRaw(filePath);
86
+ }
87
+ grepRaw(pattern, filePath, glob) {
88
+ return this.composite.grepRaw(pattern, filePath ?? undefined, glob ?? undefined);
89
+ }
90
+ globInfo(pattern, filePath) {
91
+ return this.composite.globInfo(pattern, filePath);
92
+ }
93
+ write(filePath, content) {
94
+ return this.composite.write(filePath, content);
95
+ }
96
+ edit(filePath, oldString, newString, replaceAll) {
97
+ return this.composite.edit(filePath, oldString, newString, replaceAll);
98
+ }
99
+ uploadFiles(files) {
100
+ return this.composite.uploadFiles(files);
101
+ }
102
+ downloadFiles(paths) {
103
+ return this.composite.downloadFiles(paths);
104
+ }
105
+ }
106
+ function createInlineBackendResolver(workspace) {
107
+ return (binding) => {
108
+ const backendConfig = binding.deepAgentParams?.backend;
109
+ if (!backendConfig || typeof backendConfig !== "object") {
110
+ return undefined;
111
+ }
112
+ const resolveBackendRootDir = (configuredRootDir) => {
113
+ if (typeof configuredRootDir === "string" && configuredRootDir.trim().length > 0) {
114
+ return path.isAbsolute(configuredRootDir)
115
+ ? configuredRootDir
116
+ : path.resolve(workspace.workspaceRoot, configuredRootDir);
117
+ }
118
+ return workspace.workspaceRoot;
119
+ };
120
+ const createBackend = (kind, config, runtimeLike) => {
121
+ switch (kind) {
122
+ case "LocalShellBackend": {
123
+ const rootDir = resolveBackendRootDir(config?.rootDir);
124
+ mkdirSync(rootDir, { recursive: true });
125
+ return new LocalShellBackend({
126
+ rootDir,
127
+ virtualMode: config?.virtualMode === true,
128
+ timeout: typeof config?.timeout === "number" ? config.timeout : undefined,
129
+ maxOutputBytes: typeof config?.maxOutputBytes === "number" ? config.maxOutputBytes : undefined,
130
+ env: typeof config?.env === "object" && config.env
131
+ ? Object.fromEntries(Object.entries(config.env).filter((entry) => typeof entry[1] === "string"))
132
+ : undefined,
133
+ inheritEnv: config?.inheritEnv !== false,
134
+ });
135
+ }
136
+ case "StateBackend":
137
+ return new StateBackend(runtimeLike);
138
+ case "StoreBackend":
139
+ return new StoreBackend(runtimeLike);
140
+ default:
141
+ throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, StateBackend, StoreBackend, CompositeBackend.`);
142
+ }
143
+ };
144
+ return (runtimeLike) => {
145
+ const kind = typeof backendConfig.kind === "string" ? backendConfig.kind : "CompositeBackend";
146
+ switch (kind) {
147
+ case "LocalShellBackend":
148
+ return createBackend("LocalShellBackend", backendConfig, runtimeLike);
149
+ case "StateBackend":
150
+ return new StateBackend(runtimeLike);
151
+ case "StoreBackend":
152
+ return new StoreBackend(runtimeLike);
153
+ case "CompositeBackend": {
154
+ const stateConfig = typeof backendConfig.state === "object" && backendConfig.state
155
+ ? backendConfig.state
156
+ : { kind: "StateBackend" };
157
+ const defaultBackendKind = typeof stateConfig.kind === "string" ? stateConfig.kind : "StateBackend";
158
+ const routes = typeof backendConfig.routes === "object" && backendConfig.routes
159
+ ? backendConfig.routes
160
+ : { "/memories/": { kind: "StoreBackend" } };
161
+ const mappedRoutes = Object.fromEntries(Object.entries(routes).map(([route, routeConfig]) => {
162
+ const routeKind = typeof routeConfig?.kind === "string" ? routeConfig.kind : "StoreBackend";
163
+ return [route, createBackend(routeKind, routeConfig, runtimeLike)];
164
+ }));
165
+ return new CompatibleCompositeBackend(createBackend(defaultBackendKind, stateConfig, runtimeLike), mappedRoutes);
166
+ }
167
+ default:
168
+ throw new Error(`Unsupported DeepAgent backend kind "${kind}". Supported inline kinds: LocalShellBackend, StateBackend, StoreBackend, CompositeBackend.`);
169
+ }
170
+ };
171
+ };
172
+ }
64
173
  function requireLocalResource(feature) {
65
174
  if (localResource) {
66
175
  return localResource;
@@ -176,7 +285,7 @@ export async function getOrCreateMcpClient(config) {
176
285
  const loading = (async () => {
177
286
  const client = new Client({
178
287
  name: "agent-harness",
179
- version: "0.0.16",
288
+ version: AGENT_HARNESS_VERSION,
180
289
  });
181
290
  const headers = {
182
291
  ...(config.headers ?? {}),
@@ -384,7 +493,17 @@ export async function listResourceToolsForSource(source, workspaceRoot = process
384
493
  }
385
494
  export function createResourceBackendResolver(workspace) {
386
495
  const localResolver = createProviderBackendResolver(localResource, workspace);
387
- return (binding) => localResolver?.(binding);
496
+ const remoteResolvers = (workspace.resourceSources ?? workspace.builtinSources ?? [])
497
+ .map((source) => remoteResourceCache.get(source))
498
+ .filter((provider) => Boolean(provider))
499
+ .map((provider) => createProviderBackendResolver(provider, workspace))
500
+ .filter((resolver) => Boolean(resolver));
501
+ const inlineResolver = createInlineBackendResolver(workspace);
502
+ return (binding) => {
503
+ const providerResolved = localResolver?.(binding) ??
504
+ remoteResolvers.map((resolver) => resolver(binding)).find((resolved) => resolved !== undefined);
505
+ return providerResolved ?? inlineResolver(binding);
506
+ };
388
507
  }
389
508
  export function createResourceToolResolver(workspace, options = {}) {
390
509
  const functionResolver = createFunctionToolResolver(workspace);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "description": "Agent Harness framework package",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",