@botbotgo/agent-harness 0.0.156 → 0.0.158

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 (38) hide show
  1. package/README.md +36 -0
  2. package/README.zh.md +28 -0
  3. package/dist/acp.d.ts +86 -0
  4. package/dist/acp.js +208 -0
  5. package/dist/api.d.ts +15 -2
  6. package/dist/api.js +11 -0
  7. package/dist/contracts/runtime.d.ts +55 -0
  8. package/dist/flow/build-flow-graph.d.ts +2 -0
  9. package/dist/flow/build-flow-graph.js +737 -0
  10. package/dist/flow/export-mermaid.d.ts +2 -0
  11. package/dist/flow/export-mermaid.js +96 -0
  12. package/dist/flow/export-sequence-mermaid.d.ts +3 -0
  13. package/dist/flow/export-sequence-mermaid.js +169 -0
  14. package/dist/flow/index.d.ts +4 -0
  15. package/dist/flow/index.js +3 -0
  16. package/dist/flow/types.d.ts +75 -0
  17. package/dist/flow/types.js +1 -0
  18. package/dist/index.d.ts +4 -2
  19. package/dist/index.js +1 -1
  20. package/dist/package-version.d.ts +1 -1
  21. package/dist/package-version.js +1 -1
  22. package/dist/persistence/file-store.d.ts +1 -0
  23. package/dist/persistence/file-store.js +10 -1
  24. package/dist/persistence/types.d.ts +2 -0
  25. package/dist/runtime/adapter/tool/resolved-tool.d.ts +1 -1
  26. package/dist/runtime/agent-runtime-adapter.d.ts +5 -1
  27. package/dist/runtime/agent-runtime-adapter.js +61 -24
  28. package/dist/runtime/harness/events/streaming.js +6 -0
  29. package/dist/runtime/harness/run/governance.d.ts +2 -0
  30. package/dist/runtime/harness/run/governance.js +76 -0
  31. package/dist/runtime/harness/run/inspection.js +4 -0
  32. package/dist/runtime/harness/run/stream-run.js +1 -1
  33. package/dist/runtime/harness/system/policy-engine.d.ts +2 -1
  34. package/dist/runtime/harness/system/policy-engine.js +5 -1
  35. package/dist/runtime/harness.d.ts +5 -1
  36. package/dist/runtime/harness.js +82 -0
  37. package/dist/workspace/agent-binding-compiler.js +7 -1
  38. package/package.json +11 -2
@@ -159,7 +159,7 @@ function shouldAttachMinimalDeepAgentBackend(binding) {
159
159
  export class AgentRuntimeAdapter {
160
160
  options;
161
161
  modelCache = new Map();
162
- runnableCache = new WeakMap();
162
+ runnableCache = new Map();
163
163
  toolNameMappingCache = new WeakMap();
164
164
  constructor(options = {}) {
165
165
  this.options = options;
@@ -213,7 +213,12 @@ export class AgentRuntimeAdapter {
213
213
  }
214
214
  }
215
215
  invalidateBindingRuntimeCaches(binding) {
216
- this.runnableCache.delete(binding);
216
+ const prefix = `${binding.agent.sourcePath}::`;
217
+ for (const key of Array.from(this.runnableCache.keys())) {
218
+ if (key.startsWith(prefix)) {
219
+ this.runnableCache.delete(key);
220
+ }
221
+ }
217
222
  this.modelCache.clear();
218
223
  }
219
224
  resolveTools(tools, binding) {
@@ -232,15 +237,19 @@ export class AgentRuntimeAdapter {
232
237
  this.toolNameMappingCache.set(binding, resolved);
233
238
  return resolved;
234
239
  }
235
- resolveFilesystemBackend(binding) {
240
+ resolveFilesystemBackend(binding, options = {}) {
236
241
  const filesystemConfig = getBindingFilesystemConfig(binding);
242
+ const sessionStorage = typeof filesystemConfig?.sessionStorage === "object" && filesystemConfig.sessionStorage
243
+ ? filesystemConfig.sessionStorage
244
+ : undefined;
237
245
  const configuredRootDir = typeof filesystemConfig?.rootDir === "string" && filesystemConfig.rootDir.trim().length > 0
238
246
  ? filesystemConfig.rootDir
239
247
  : undefined;
240
248
  const workspaceRoot = binding.harnessRuntime.workspaceRoot;
241
- const rootDir = configuredRootDir
249
+ const baseRootDir = configuredRootDir
242
250
  ? (path.isAbsolute(configuredRootDir) ? configuredRootDir : path.resolve(workspaceRoot ?? process.cwd(), configuredRootDir))
243
251
  : workspaceRoot ?? process.cwd();
252
+ const rootDir = this.resolveFilesystemRootDir(baseRootDir, binding, sessionStorage, options.threadId);
244
253
  return new FilesystemBackend({
245
254
  rootDir,
246
255
  virtualMode: filesystemConfig?.virtualMode === true,
@@ -249,6 +258,25 @@ export class AgentRuntimeAdapter {
249
258
  : 10,
250
259
  });
251
260
  }
261
+ resolveFilesystemRootDir(baseRootDir, binding, sessionStorage, threadId) {
262
+ const enabled = sessionStorage?.enabled === true;
263
+ if (!enabled || !threadId) {
264
+ return baseRootDir;
265
+ }
266
+ const workspaceRoot = binding.harnessRuntime.workspaceRoot ?? process.cwd();
267
+ const runRoot = binding.harnessRuntime.runRoot;
268
+ const configuredRootDir = typeof sessionStorage.rootDir === "string" && sessionStorage.rootDir.trim().length > 0
269
+ ? sessionStorage.rootDir.trim()
270
+ : "{runRoot}/threads/{threadId}/filesystem";
271
+ const rendered = configuredRootDir
272
+ .replaceAll("{threadId}", threadId)
273
+ .replaceAll("{sessionId}", threadId)
274
+ .replaceAll("{agentId}", binding.agent.id)
275
+ .replaceAll("{runRoot}", runRoot)
276
+ .replaceAll("{workspaceRoot}", workspaceRoot)
277
+ .replaceAll("{baseRootDir}", baseRootDir);
278
+ return path.isAbsolute(rendered) ? rendered : path.resolve(workspaceRoot, rendered);
279
+ }
252
280
  resolveBuiltinMiddlewareBackend(binding, options = {}) {
253
281
  return resolveBuiltinMiddlewareBackendHelper({
254
282
  binding,
@@ -257,7 +285,7 @@ export class AgentRuntimeAdapter {
257
285
  options,
258
286
  });
259
287
  }
260
- createDeclaredMiddlewareResolverOptions(binding) {
288
+ createDeclaredMiddlewareResolverOptions(binding, options = {}) {
261
289
  return {
262
290
  resolveModel: (model) => this.resolveModel(model),
263
291
  resolveBackend: (resolvedBinding) => {
@@ -266,7 +294,7 @@ export class AgentRuntimeAdapter {
266
294
  },
267
295
  resolveFilesystemBackend: (resolvedBinding) => {
268
296
  const targetBinding = resolvedBinding ?? binding;
269
- return targetBinding ? this.resolveFilesystemBackend(targetBinding) : undefined;
297
+ return targetBinding ? this.resolveFilesystemBackend(targetBinding, { threadId: options.threadId }) : undefined;
270
298
  },
271
299
  resolveCustom: this.options.declaredMiddlewareResolver,
272
300
  binding,
@@ -276,8 +304,8 @@ export class AgentRuntimeAdapter {
276
304
  return {
277
305
  resolveModel: (model) => this.resolveModel(model),
278
306
  resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
279
- resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding),
280
- createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding),
307
+ resolveFilesystemBackend: (currentBinding) => this.resolveFilesystemBackend(currentBinding, { threadId: options.threadId }),
308
+ createDeclaredMiddlewareResolverOptions: (currentBinding) => this.createDeclaredMiddlewareResolverOptions(currentBinding, options),
281
309
  resolveBuiltinMiddlewareBackend: (currentBinding, currentOptions = {}) => this.resolveBuiltinMiddlewareBackend(currentBinding, currentOptions),
282
310
  resolveSubagents: (subagents, currentBinding) => this.resolveSubagents(subagents, currentBinding),
283
311
  invokeBuiltinTaskTool: (currentBinding, toolInput, currentOptions = {}) => this.invokeBuiltinTaskTool(currentBinding, toolInput, currentOptions),
@@ -313,8 +341,8 @@ export class AgentRuntimeAdapter {
313
341
  createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
314
342
  });
315
343
  }
316
- async resolveLangChainRuntimeExtensionMiddleware(binding) {
317
- const assembly = this.createAssemblyResolvers(binding);
344
+ async resolveLangChainRuntimeExtensionMiddleware(binding, options = {}) {
345
+ const assembly = this.createAssemblyResolvers(binding, options);
318
346
  return resolveLangChainRuntimeExtensionMiddlewareHelper({
319
347
  binding,
320
348
  materializeAutomaticSummarizationMiddleware: (currentBinding) => this.materializeAutomaticSummarizationMiddleware(currentBinding),
@@ -324,14 +352,14 @@ export class AgentRuntimeAdapter {
324
352
  resolveSubagents: assembly.resolveSubagents,
325
353
  });
326
354
  }
327
- async resolveMiddleware(binding, interruptOn) {
328
- const assembly = this.createAssemblyResolvers(binding);
355
+ async resolveMiddleware(binding, interruptOn, options = {}) {
356
+ const assembly = this.createAssemblyResolvers(binding, options);
329
357
  return resolveMiddlewareHelper({
330
358
  binding,
331
359
  interruptOn,
332
360
  runtimeAdapterOptions: this.options,
333
361
  createDeclaredMiddlewareResolverOptions: assembly.createDeclaredMiddlewareResolverOptions,
334
- resolveLangChainRuntimeExtensionMiddleware: (currentBinding) => this.resolveLangChainRuntimeExtensionMiddleware(currentBinding),
362
+ resolveLangChainRuntimeExtensionMiddleware: (currentBinding) => this.resolveLangChainRuntimeExtensionMiddleware(currentBinding, options),
335
363
  });
336
364
  }
337
365
  async resolveSubagents(subagents, binding) {
@@ -354,7 +382,7 @@ export class AgentRuntimeAdapter {
354
382
  const interruptOn = resolveRunnableInterruptOn(binding);
355
383
  const resolvedModel = await this.resolveModel(primaryModel);
356
384
  const resolvedTools = this.resolveTools(primaryTools, binding);
357
- const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn);
385
+ const resolvedMiddleware = await this.resolveMiddleware(binding, interruptOn, { threadId: options.threadId });
358
386
  const resolvedCheckpointer = resolveRunnableCheckpointer(this.options, binding);
359
387
  const resolvedStore = this.options.storeResolver?.(binding);
360
388
  const model = resolvedModel;
@@ -372,12 +400,12 @@ export class AgentRuntimeAdapter {
372
400
  systemPromptOverride: options.systemPromptOverride,
373
401
  }));
374
402
  }
375
- async createRunnable(binding) {
403
+ async createRunnable(binding, options = {}) {
376
404
  if (getBindingAdapterKind(binding) === "langgraph") {
377
405
  throw new Error(`Agent ${binding.agent.id} uses removed backend langgraph; use langchain-v1 or deepagent`);
378
406
  }
379
407
  if (isLangChainBinding(binding)) {
380
- return this.createLangChainRunnable(binding);
408
+ return this.createLangChainRunnable(binding, { threadId: options.threadId });
381
409
  }
382
410
  return this.createDeepAgentRunnable(binding);
383
411
  }
@@ -425,25 +453,34 @@ export class AgentRuntimeAdapter {
425
453
  });
426
454
  return createDeepAgent(deepAgentConfig);
427
455
  }
428
- async create(binding) {
429
- const cached = this.runnableCache.get(binding);
456
+ buildRunnableCacheKey(binding, threadId) {
457
+ const filesystemConfig = getBindingFilesystemConfig(binding);
458
+ const sessionStorage = typeof filesystemConfig?.sessionStorage === "object" && filesystemConfig.sessionStorage
459
+ ? filesystemConfig.sessionStorage
460
+ : undefined;
461
+ const sessionScoped = sessionStorage?.enabled === true;
462
+ return `${binding.agent.sourcePath}::${sessionScoped ? (threadId ?? "__default__") : "__binding__"}`;
463
+ }
464
+ async create(binding, options = {}) {
465
+ const cacheKey = this.buildRunnableCacheKey(binding, options.threadId);
466
+ const cached = this.runnableCache.get(cacheKey);
430
467
  if (cached) {
431
468
  return cached;
432
469
  }
433
- const pending = this.createRunnable(binding);
434
- this.runnableCache.set(binding, pending);
470
+ const pending = this.createRunnable(binding, options);
471
+ this.runnableCache.set(cacheKey, pending);
435
472
  try {
436
473
  return await pending;
437
474
  }
438
475
  catch (error) {
439
- this.runnableCache.delete(binding);
476
+ this.runnableCache.delete(cacheKey);
440
477
  throw error;
441
478
  }
442
479
  }
443
480
  async invoke(binding, input, threadId, runId, resumePayload, history = [], options = {}) {
444
481
  const callRuntime = async (activeBinding, activeRequest) => {
445
482
  return this.invokeWithProviderRetry(activeBinding, async () => {
446
- const runnable = await this.create(activeBinding);
483
+ const runnable = await this.create(activeBinding, { threadId });
447
484
  return (await this.withTimeout(() => runnable.invoke(activeRequest, resolveLangChainInvocationConfig(activeBinding, {
448
485
  threadId,
449
486
  runId,
@@ -469,7 +506,7 @@ export class AgentRuntimeAdapter {
469
506
  invokeOptions: options,
470
507
  resolveTools: (tools, currentBinding) => this.resolveTools(tools, currentBinding),
471
508
  getToolNameMapping: (currentBinding) => this.getToolNameMapping(currentBinding),
472
- resolveBuiltinMiddlewareTools: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareTools(currentBinding, currentOptions),
509
+ resolveBuiltinMiddlewareTools: (currentBinding, currentOptions) => this.resolveBuiltinMiddlewareTools(currentBinding, { ...currentOptions, threadId }),
473
510
  callRuntimeWithToolParseRecovery,
474
511
  });
475
512
  }
@@ -494,7 +531,7 @@ export class AgentRuntimeAdapter {
494
531
  forceInvokeFallback,
495
532
  canUseDirectModelStream,
496
533
  langChainStreamModel,
497
- createRunnable: () => this.create(binding),
534
+ createRunnable: () => this.create(binding, { threadId }),
498
535
  withTimeout: (producer, timeoutMs, operation, stage) => this.withTimeout(producer, timeoutMs, operation, stage),
499
536
  iterateWithTimeout: (iterable, timeoutMs, operation, deadlineAt, deadlineTimeoutMs) => this.iterateWithTimeout(iterable, timeoutMs, operation, deadlineAt, deadlineTimeoutMs),
500
537
  invokeTimeoutMs: computeRemainingTimeoutMs(streamDeadlineAt, invokeTimeoutMs),
@@ -42,6 +42,12 @@ export async function dispatchRunListeners(stream, listeners, options) {
42
42
  }
43
43
  if (item.type === "upstream-event") {
44
44
  await options.notifyListener(listeners.onUpstreamEvent, item.event);
45
+ await options.notifyListener(listeners.onUpstreamItem, {
46
+ threadId: item.threadId,
47
+ runId: item.runId,
48
+ agentId: item.agentId,
49
+ event: item.event,
50
+ });
45
51
  continue;
46
52
  }
47
53
  if (item.type === "result") {
@@ -0,0 +1,2 @@
1
+ import type { CompiledAgentBinding, RuntimeGovernanceBundle } from "../../../contracts/types.js";
2
+ export declare function buildRuntimeGovernanceBundles(binding: CompiledAgentBinding): RuntimeGovernanceBundle[];
@@ -0,0 +1,76 @@
1
+ import { getBindingPrimaryTools } from "../../support/compiled-binding.js";
2
+ import { toolRequiresRuntimeApproval } from "../../adapter/tool/tool-hitl.js";
3
+ const WRITE_LIKE_PATTERN = /\b(write|edit|delete|create|update|append|insert|push|commit|publish|send|post|apply|merge|sync|upload|save)\b/i;
4
+ function inputHints(binding, tool) {
5
+ const hints = new Set();
6
+ const target = `${tool.name} ${tool.description}`.toLowerCase();
7
+ if (/(path|file|dir|directory|folder|workspace|repo|repository)/.test(target)) {
8
+ hints.add("filesystem-scope");
9
+ }
10
+ if (/(memory|knowledge|store|recall)/.test(target)) {
11
+ hints.add("memory-scope");
12
+ }
13
+ if (tool.config?.mcp) {
14
+ hints.add("remote-mcp");
15
+ }
16
+ if (binding.agent.executionMode === "deepagent") {
17
+ hints.add("delegated-runtime");
18
+ }
19
+ return Array.from(hints);
20
+ }
21
+ function classifyRisk(policy) {
22
+ if (policy.requiresApproval) {
23
+ return "high";
24
+ }
25
+ const target = `${policy.toolName} ${policy.description}`;
26
+ if (policy.toolType === "mcp" && WRITE_LIKE_PATTERN.test(target)) {
27
+ return "high";
28
+ }
29
+ if (policy.toolType === "backend" || policy.toolType === "mcp") {
30
+ return "medium";
31
+ }
32
+ return "low";
33
+ }
34
+ function toCategory(toolType) {
35
+ if (toolType === "mcp") {
36
+ return "mcp";
37
+ }
38
+ if (toolType === "backend") {
39
+ return "backend";
40
+ }
41
+ if (toolType === "provider") {
42
+ return "provider-native";
43
+ }
44
+ return "local";
45
+ }
46
+ export function buildRuntimeGovernanceBundles(binding) {
47
+ const toolPolicies = getBindingPrimaryTools(binding).map((tool) => {
48
+ const requiresApproval = toolRequiresRuntimeApproval(tool);
49
+ return {
50
+ toolName: tool.name,
51
+ toolId: tool.id,
52
+ toolType: tool.type,
53
+ category: toCategory(tool.type),
54
+ risk: classifyRisk({
55
+ toolType: tool.type,
56
+ requiresApproval,
57
+ toolName: tool.name,
58
+ description: tool.description,
59
+ config: tool.config,
60
+ }),
61
+ requiresApproval,
62
+ approvalPolicy: tool.hitl?.enabled === true ? "explicit-hitl" : requiresApproval ? "runtime-default" : "none",
63
+ hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
64
+ inputRiskHints: inputHints(binding, tool),
65
+ };
66
+ });
67
+ if (toolPolicies.length === 0) {
68
+ return [];
69
+ }
70
+ return [{
71
+ bundleId: `governance/${binding.agent.id}`,
72
+ title: "Runtime tool governance",
73
+ summary: `${toolPolicies.filter((tool) => tool.requiresApproval).length} of ${toolPolicies.length} tool(s) require approval`,
74
+ toolPolicies,
75
+ }];
76
+ }
@@ -1,5 +1,6 @@
1
1
  import { readSkillMetadata } from "../../support/skill-metadata.js";
2
2
  import { getBindingMemorySources, getBindingPrimaryModel, getBindingPrimaryTools, getBindingSkills, getBindingSubagents, } from "../../support/compiled-binding.js";
3
+ import { buildRuntimeGovernanceBundles } from "./governance.js";
3
4
  function asObject(value) {
4
5
  return typeof value === "object" && value !== null ? value : null;
5
6
  }
@@ -67,6 +68,9 @@ export function buildRunRuntimeSnapshot(binding, options) {
67
68
  };
68
69
  }),
69
70
  memory: getBindingMemorySources(binding),
71
+ governance: {
72
+ bundles: buildRuntimeGovernanceBundles(binding),
73
+ },
70
74
  ...(tracing ? { tracing } : {}),
71
75
  };
72
76
  }
@@ -85,7 +85,7 @@ export async function* streamHarnessRun(options) {
85
85
  type: "upstream-event",
86
86
  threadId: options.threadId,
87
87
  runId: options.runId,
88
- agentId: options.selectedAgentId,
88
+ agentId: currentAgentId,
89
89
  event: normalizedChunk.event,
90
90
  };
91
91
  continue;
@@ -1,7 +1,8 @@
1
- import type { CompiledAgentBinding } from "../../../contracts/types.js";
1
+ import type { CompiledAgentBinding, RuntimeGovernanceBundle } from "../../../contracts/types.js";
2
2
  export type PolicyEngineDecision = {
3
3
  allowed: boolean;
4
4
  reasons: string[];
5
+ bundles?: RuntimeGovernanceBundle[];
5
6
  };
6
7
  export declare class PolicyEngine {
7
8
  /**
@@ -7,6 +7,7 @@ export class PolicyEngine {
7
7
  */
8
8
  evaluate(binding) {
9
9
  const reasons = [];
10
+ const bundles = [];
10
11
  let allowed = true;
11
12
  for (const evaluator of getPolicyEvaluators()) {
12
13
  const decision = evaluator.evaluate(binding);
@@ -17,8 +18,11 @@ export class PolicyEngine {
17
18
  allowed = false;
18
19
  }
19
20
  reasons.push(...decision.reasons);
21
+ if (Array.isArray(decision.bundles)) {
22
+ bundles.push(...decision.bundles);
23
+ }
20
24
  }
21
- return { allowed, reasons };
25
+ return bundles.length > 0 ? { allowed, reasons, bundles } : { allowed, reasons };
22
26
  }
23
27
  }
24
28
  export { PolicyEngine as GovernanceEngine, };
@@ -1,4 +1,4 @@
1
- import type { ApprovalRecord, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
1
+ import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
2
2
  import { type ToolMcpServerOptions } from "../mcp.js";
3
3
  import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
@@ -82,6 +82,10 @@ export declare class AgentHarnessRuntime {
82
82
  runId?: string;
83
83
  }): Promise<ApprovalRecord[]>;
84
84
  getApproval(approvalId: string): Promise<ApprovalRecord | null>;
85
+ listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
86
+ readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
87
+ listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
88
+ exportEvaluationBundle(input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
85
89
  listAgentSkills(agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
86
90
  getAgent(agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
87
91
  describeWorkspaceInventory(options?: RequirementAssessmentOptions): {
@@ -475,6 +475,51 @@ export class AgentHarnessRuntime {
475
475
  persistence: this.persistence,
476
476
  }, approvalId);
477
477
  }
478
+ async listArtifacts(threadId, runId) {
479
+ return this.persistence.listArtifacts(threadId, runId);
480
+ }
481
+ async readArtifact(threadId, runId, artifactPath) {
482
+ return this.persistence.readArtifact(threadId, runId, artifactPath);
483
+ }
484
+ async listRunEvents(threadId, runId) {
485
+ return this.persistence.listRunEvents(threadId, runId);
486
+ }
487
+ async exportEvaluationBundle(input) {
488
+ const thread = await this.getThread(input.sessionId);
489
+ const run = await this.getRun(input.requestId);
490
+ const approvals = await this.listApprovals({ threadId: input.sessionId, runId: input.requestId });
491
+ const transcript = await this.persistence.listThreadMessages(input.sessionId, 500);
492
+ const events = await this.persistence.listRunEvents(input.sessionId, input.requestId);
493
+ const runtimeHealth = await this.getHealth();
494
+ const artifactsListing = input.includeArtifacts === false
495
+ ? { items: [] }
496
+ : await this.persistence.listArtifacts(input.sessionId, input.requestId);
497
+ const artifacts = await Promise.all(artifactsListing.items.map(async (artifact) => ({
498
+ ...artifact,
499
+ ...(input.includeArtifactContents === true
500
+ ? { content: await this.persistence.readArtifact(input.sessionId, input.requestId, artifact.path) }
501
+ : {}),
502
+ })));
503
+ return {
504
+ session: thread ? toSessionRecord(thread) : null,
505
+ request: run ? toRequestRecord(run) : null,
506
+ approvals,
507
+ transcript,
508
+ events,
509
+ artifacts,
510
+ runtimeHealth,
511
+ ...(typeof input.expectedOutput === "string" && input.expectedOutput.trim().length > 0
512
+ ? { expectedOutput: input.expectedOutput.trim() }
513
+ : {}),
514
+ rubric: Array.isArray(input.rubric)
515
+ ? input.rubric.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
516
+ : [],
517
+ tags: Array.isArray(input.tags)
518
+ ? input.tags.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
519
+ : [],
520
+ ...(input.metadata ? { metadata: { ...input.metadata } } : {}),
521
+ };
522
+ }
478
523
  listAgentSkills(agentId, options = {}) {
479
524
  return listWorkspaceAgentSkills(this.workspace, agentId, {
480
525
  assessRequirements: isInventoryEnabled(this.workspace),
@@ -1393,3 +1438,40 @@ export class AgentHarnessRuntime {
1393
1438
  }, thread, nowMs);
1394
1439
  }
1395
1440
  }
1441
+ function toRequestSummary(summary) {
1442
+ return {
1443
+ requestId: summary.runId,
1444
+ sessionId: summary.threadId,
1445
+ agentId: summary.agentId,
1446
+ executionMode: summary.executionMode,
1447
+ adapterKind: summary.adapterKind,
1448
+ createdAt: summary.createdAt,
1449
+ updatedAt: summary.updatedAt,
1450
+ state: summary.state,
1451
+ checkpointRef: summary.checkpointRef,
1452
+ resumable: summary.resumable,
1453
+ startedAt: summary.startedAt,
1454
+ endedAt: summary.endedAt,
1455
+ lastActivityAt: summary.lastActivityAt,
1456
+ currentAgentId: summary.currentAgentId,
1457
+ delegationChain: summary.delegationChain,
1458
+ runtimeSnapshot: summary.runtimeSnapshot,
1459
+ };
1460
+ }
1461
+ function toSessionRecord(record) {
1462
+ return {
1463
+ sessionId: record.threadId,
1464
+ entryAgentId: record.entryAgentId,
1465
+ currentAgentId: record.currentAgentId,
1466
+ currentState: record.currentState,
1467
+ latestRequestId: record.latestRunId,
1468
+ createdAt: record.createdAt,
1469
+ updatedAt: record.updatedAt,
1470
+ messages: record.messages,
1471
+ requests: record.runs.map(toRequestSummary),
1472
+ pendingDecision: record.pendingDecision,
1473
+ };
1474
+ }
1475
+ function toRequestRecord(record) {
1476
+ return toRequestSummary(record);
1477
+ }
@@ -337,6 +337,12 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
337
337
  const store = resolveStoreConfig(agent, refs);
338
338
  const checkpointer = resolveCheckpointerConfig(agent, refs);
339
339
  const runtimeMemory = resolveRuntimeMemoryConfig(agent, refs);
340
+ const runtimeFilesystemDefaults = agent.executionMode === "langchain-v1"
341
+ ? asObject(runtimeDefaults?.filesystem)
342
+ : undefined;
343
+ const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
344
+ ? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
345
+ : undefined;
340
346
  const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
341
347
  ? path.resolve(workspaceRoot, agent.runRoot)
342
348
  : typeof runtimeDefaults?.runRoot === "string" && runtimeDefaults.runRoot.trim().length > 0
@@ -362,7 +368,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
362
368
  langchain: {
363
369
  passthrough,
364
370
  interruptOn: resolveInterruptOn(agent),
365
- filesystem: getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }),
371
+ filesystem: compiledFilesystemConfig,
366
372
  subagents: compileSubagents(agent, agents, workspaceRoot, models, tools, compiledAgentSkills, compiledAgentModel),
367
373
  memory: compiledAgentMemory,
368
374
  skills: compiledAgentSkills,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.156",
3
+ "version": "0.0.158",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",
@@ -28,6 +28,11 @@
28
28
  "import": "./dist/index.js",
29
29
  "default": "./dist/index.js"
30
30
  },
31
+ "./acp": {
32
+ "types": "./dist/acp.d.ts",
33
+ "import": "./dist/acp.js",
34
+ "default": "./dist/acp.js"
35
+ },
31
36
  "./tools": {
32
37
  "types": "./dist/tools.d.ts",
33
38
  "import": "./dist/tools.js",
@@ -54,7 +59,7 @@
54
59
  "mem0ai": "^2.4.4",
55
60
  "mustache": "^4.2.0",
56
61
  "yaml": "^2.8.1",
57
- "zod": "^3.25.67"
62
+ "zod": "^4.3.6"
58
63
  },
59
64
  "scripts": {
60
65
  "build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
@@ -70,5 +75,9 @@
70
75
  "@types/node": "^24.6.0",
71
76
  "typescript": "^5.9.3",
72
77
  "vitest": "^3.2.4"
78
+ },
79
+ "overrides": {
80
+ "@browserbasehq/stagehand": "3.2.0",
81
+ "openai": "6.33.0"
73
82
  }
74
83
  }