@botbotgo/agent-harness 0.0.159 → 0.0.161

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
@@ -881,8 +881,14 @@ Primary exports:
881
881
  - `getApproval`
882
882
  - `listArtifacts`
883
883
  - `getArtifact`
884
+ - `listRunEvents`
885
+ - `exportRunPackage`
886
+ - `exportSessionPackage`
884
887
  - `exportEvaluationBundle`
888
+ - `replayEvaluationBundle`
885
889
  - `createAcpServer`
890
+ - `serveAcpHttp`
891
+ - `serveAcpStdio`
886
892
  - `createToolMcpServer`
887
893
  - `serveToolsOverStdio`
888
894
  - `stop`
@@ -899,3 +905,9 @@ Inspection helpers:
899
905
  - `exportFlowGraphToSequenceMermaid(...)` renders the same inspection graph as a Mermaid sequence diagram. By default it emits only user-defined participants and calls, while `view: "debug"` includes runtime participants and lifecycle messages.
900
906
 
901
907
  These helpers are visualization and inspection utilities. They do not introduce a canonical harness-owned execution protocol.
908
+
909
+ ACP transport notes:
910
+
911
+ - `serveAcpStdio(runtime)` exposes newline-delimited JSON-RPC over stdio for local IDE, CLI, or subprocess clients.
912
+ - `serveAcpHttp(runtime)` exposes JSON-RPC over HTTP plus SSE runtime events so remote operator surfaces can connect without importing the runtime in-process.
913
+ - `exportRunPackage(...)` and `exportSessionPackage(...)` package stable runtime records, transcript, approvals, events, and artifacts for operator tooling without reaching into persistence internals.
package/README.zh.md CHANGED
@@ -840,8 +840,14 @@ spec:
840
840
  - `getApproval`
841
841
  - `listArtifacts`
842
842
  - `getArtifact`
843
+ - `listRunEvents`
844
+ - `exportRunPackage`
845
+ - `exportSessionPackage`
843
846
  - `exportEvaluationBundle`
847
+ - `replayEvaluationBundle`
844
848
  - `createAcpServer`
849
+ - `serveAcpHttp`
850
+ - `serveAcpStdio`
845
851
  - `createToolMcpServer`
846
852
  - `serveToolsOverStdio`
847
853
  - `stop`
@@ -858,3 +864,9 @@ Inspection 辅助工具:
858
864
  - `exportFlowGraphToSequenceMermaid(...)` 可把同一份 inspection graph 导出为 Mermaid sequence diagram。默认只输出用户定义的参与者与调用;传 `view: "debug"` 才会包含 runtime participant 与生命周期消息。
859
865
 
860
866
  这些 helper 只用于可视化与检查,不代表新的 harness 官方执行协议。
867
+
868
+ ACP transport 说明:
869
+
870
+ - `serveAcpStdio(runtime)` 提供基于 stdio 的 newline-delimited JSON-RPC,适合本地 IDE、CLI 或子进程客户端。
871
+ - `serveAcpHttp(runtime)` 提供基于 HTTP 的 JSON-RPC 与 SSE runtime events,适合远程 operator surface 或独立控制面接入。
872
+ - `exportRunPackage(...)` 与 `exportSessionPackage(...)` 可把稳定 runtime 记录、transcript、approvals、events 和 artifacts 打包给 operator tooling,而不必直接访问 persistence 内部实现。
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ArtifactListing, CancelOptions, InvocationEnvelope, ListMemoriesInput, ListMemoriesResult, MemoryRecord, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RemoveMemoryInput, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, SessionRecord, SessionSummary, UpdateMemoryInput, WorkspaceLoadOptions } from "./contracts/types.js";
1
+ import type { ArtifactListing, CancelOptions, InvocationEnvelope, ListMemoriesInput, ListMemoriesResult, MemoryRecord, MemorizeInput, MemorizeResult, MessageContent, RecallInput, RecallResult, RemoveMemoryInput, RequestRecord, RequestSummary, ResumeOptions, RunDecisionOptions, RunResult, RunStartOptions, RuntimeHealthSnapshot, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, SessionRecord, SessionSummary, UpdateMemoryInput, WorkspaceLoadOptions } from "./contracts/types.js";
2
2
  import { AgentHarnessRuntime } from "./runtime/harness.js";
3
3
  import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/harness/system/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./runtime/harness/system/skill-requirements.js";
@@ -8,7 +8,9 @@ export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, A
8
8
  export { AgentHarnessRuntime } from "./runtime/harness.js";
9
9
  export { buildFlowGraph, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid } from "./flow/index.js";
10
10
  export { createUpstreamTimelineReducer } from "./upstream-events.js";
11
- export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, UpdateMemoryInput, } from "./contracts/types.js";
11
+ export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, UpdateMemoryInput, } from "./contracts/types.js";
12
+ export type { AcpHttpServer, AcpHttpServerOptions } from "./protocol/acp/http.js";
13
+ export type { AcpStdioServer, AcpStdioServerOptions } from "./protocol/acp/stdio.js";
12
14
  type PublicApprovalRecord = {
13
15
  approvalId: string;
14
16
  pendingActionId: string;
@@ -84,8 +86,17 @@ export declare function getArtifact(runtime: AgentHarnessRuntime, input: {
84
86
  requestId: string;
85
87
  artifactPath: string;
86
88
  }): Promise<unknown>;
89
+ export declare function listRunEvents(runtime: AgentHarnessRuntime, input: {
90
+ sessionId: string;
91
+ requestId: string;
92
+ }): Promise<import("./contracts/runtime.js").HarnessEvent[]>;
87
93
  export declare function getHealth(runtime: AgentHarnessRuntime): Promise<RuntimeHealthSnapshot>;
94
+ export declare function exportRunPackage(runtime: AgentHarnessRuntime, input: RuntimeRunPackageInput): Promise<RuntimeRunPackage>;
95
+ export declare function exportSessionPackage(runtime: AgentHarnessRuntime, input: RuntimeSessionPackageInput): Promise<RuntimeSessionPackage>;
88
96
  export declare function exportEvaluationBundle(runtime: AgentHarnessRuntime, input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
97
+ export declare function replayEvaluationBundle(runtime: AgentHarnessRuntime, input: RuntimeEvaluationReplayInput): Promise<RuntimeEvaluationReplayResult>;
98
+ export declare function serveAcpStdio(runtime: AgentHarnessRuntime, options?: import("./protocol/acp/stdio.js").AcpStdioServerOptions): import("./protocol/acp/stdio.js").AcpStdioServer;
99
+ export declare function serveAcpHttp(runtime: AgentHarnessRuntime, options?: import("./protocol/acp/http.js").AcpHttpServerOptions): Promise<import("./protocol/acp/http.js").AcpHttpServer>;
89
100
  export declare function listAgentSkills(runtime: AgentHarnessRuntime, agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
90
101
  export declare function getAgent(runtime: AgentHarnessRuntime, agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
91
102
  export declare function describeInventory(runtime: AgentHarnessRuntime, options?: RequirementAssessmentOptions): {
package/dist/api.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { AgentHarnessRuntime } from "./runtime/harness.js";
2
+ import { serveAcpOverHttp } from "./protocol/acp/http.js";
3
+ import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
2
4
  import { normalizeMessageContent } from "./utils/message-content.js";
3
5
  import { loadWorkspace } from "./workspace/compile.js";
4
6
  export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
@@ -186,12 +188,30 @@ export async function listArtifacts(runtime, input) {
186
188
  export async function getArtifact(runtime, input) {
187
189
  return runtime.readArtifact(input.sessionId, input.requestId, input.artifactPath);
188
190
  }
191
+ export async function listRunEvents(runtime, input) {
192
+ return runtime.listRunEvents(input.sessionId, input.requestId);
193
+ }
189
194
  export async function getHealth(runtime) {
190
195
  return runtime.getHealth();
191
196
  }
197
+ export async function exportRunPackage(runtime, input) {
198
+ return runtime.exportRunPackage(input);
199
+ }
200
+ export async function exportSessionPackage(runtime, input) {
201
+ return runtime.exportSessionPackage(input);
202
+ }
192
203
  export async function exportEvaluationBundle(runtime, input) {
193
204
  return runtime.exportEvaluationBundle(input);
194
205
  }
206
+ export async function replayEvaluationBundle(runtime, input) {
207
+ return runtime.replayEvaluationBundle(input);
208
+ }
209
+ export function serveAcpStdio(runtime, options) {
210
+ return serveAcpOverStdio(runtime, options);
211
+ }
212
+ export async function serveAcpHttp(runtime, options) {
213
+ return serveAcpOverHttp(runtime, options);
214
+ }
195
215
  export function listAgentSkills(runtime, agentId, options) {
196
216
  return runtime.listAgentSkills(agentId, options);
197
217
  }
package/dist/cli.d.ts CHANGED
@@ -1,8 +1,16 @@
1
1
  #!/usr/bin/env node
2
+ import { createAgentHarness } from "./api.js";
3
+ import { serveAcpOverHttp } from "./protocol/acp/http.js";
4
+ import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
2
5
  type CliIo = {
3
6
  cwd?: string;
4
7
  stdout?: (message: string) => void;
5
8
  stderr?: (message: string) => void;
6
9
  };
7
- export declare function runCli(argv: string[], io?: CliIo): Promise<number>;
10
+ type CliDeps = {
11
+ createAgentHarness?: typeof createAgentHarness;
12
+ serveAcpOverHttp?: typeof serveAcpOverHttp;
13
+ serveAcpOverStdio?: typeof serveAcpOverStdio;
14
+ };
15
+ export declare function runCli(argv: string[], io?: CliIo, deps?: CliDeps): Promise<number>;
8
16
  export {};
package/dist/cli.js CHANGED
@@ -1,10 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import path from "node:path";
3
3
  import { pathToFileURL } from "node:url";
4
+ import { createAgentHarness } from "./api.js";
4
5
  import { initProject } from "./init-project.js";
6
+ import { serveAcpOverHttp } from "./protocol/acp/http.js";
7
+ import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
5
8
  function renderUsage() {
6
9
  return `Usage:
7
10
  agent-harness init <project-name> [--template deep-research|single-agent] [--provider <provider>] [--model <model>] [--with-web-search|--no-web-search]
11
+ agent-harness acp serve [--workspace <path>] [--transport stdio|http] [--host <hostname>] [--port <port>]
8
12
  `;
9
13
  }
10
14
  function isTemplate(value) {
@@ -46,11 +50,68 @@ function parseInitOptions(args) {
46
50
  }
47
51
  return { options };
48
52
  }
49
- export async function runCli(argv, io = {}) {
53
+ function parseAcpServeOptions(args) {
54
+ let workspaceRoot;
55
+ let transport = "stdio";
56
+ let hostname;
57
+ let port;
58
+ for (let index = 0; index < args.length; index += 1) {
59
+ const arg = args[index];
60
+ if (arg === "--workspace") {
61
+ const value = args[index + 1];
62
+ if (!value) {
63
+ return { transport, error: "Missing value for --workspace" };
64
+ }
65
+ workspaceRoot = value;
66
+ index += 1;
67
+ continue;
68
+ }
69
+ if (arg === "--transport") {
70
+ const value = args[index + 1];
71
+ if (!value) {
72
+ return { transport, hostname, port, error: "Missing value for --transport" };
73
+ }
74
+ if (value !== "stdio" && value !== "http") {
75
+ return { transport, hostname, port, error: `Unsupported ACP transport: ${value}` };
76
+ }
77
+ transport = value;
78
+ index += 1;
79
+ continue;
80
+ }
81
+ if (arg === "--host") {
82
+ const value = args[index + 1];
83
+ if (!value) {
84
+ return { transport, hostname, port, error: "Missing value for --host" };
85
+ }
86
+ hostname = value;
87
+ index += 1;
88
+ continue;
89
+ }
90
+ if (arg === "--port") {
91
+ const value = args[index + 1];
92
+ if (!value) {
93
+ return { transport, hostname, port, error: "Missing value for --port" };
94
+ }
95
+ const parsedPort = Number.parseInt(value, 10);
96
+ if (!Number.isFinite(parsedPort) || parsedPort < 0) {
97
+ return { transport, hostname, port, error: `Invalid ACP port: ${value}` };
98
+ }
99
+ port = parsedPort;
100
+ index += 1;
101
+ continue;
102
+ }
103
+ return { transport, hostname, port, error: `Unknown option: ${arg}` };
104
+ }
105
+ return { workspaceRoot, transport, hostname, port };
106
+ }
107
+ export async function runCli(argv, io = {}, deps = {}) {
50
108
  const cwd = io.cwd ?? process.cwd();
51
109
  const stdout = io.stdout ?? ((message) => process.stdout.write(message));
52
110
  const stderr = io.stderr ?? ((message) => process.stderr.write(message));
53
111
  const [command, projectName, ...rest] = argv;
112
+ const createHarness = deps.createAgentHarness ?? createAgentHarness;
113
+ const serveAcpHttp = deps.serveAcpOverHttp ?? serveAcpOverHttp;
114
+ const serveAcp = deps.serveAcpOverStdio ?? serveAcpOverStdio;
54
115
  if (command === "init") {
55
116
  if (!projectName?.trim()) {
56
117
  stderr(renderUsage());
@@ -81,6 +142,43 @@ export async function runCli(argv, io = {}) {
81
142
  return 1;
82
143
  }
83
144
  }
145
+ if (command === "acp") {
146
+ const [subcommand, ...subcommandArgs] = [projectName, ...rest];
147
+ if (subcommand !== "serve") {
148
+ stderr(renderUsage());
149
+ return 1;
150
+ }
151
+ const parsed = parseAcpServeOptions(subcommandArgs);
152
+ if (parsed.error) {
153
+ stderr(`${parsed.error}\n`);
154
+ stderr(renderUsage());
155
+ return 1;
156
+ }
157
+ try {
158
+ const runtime = await createHarness(path.resolve(cwd, parsed.workspaceRoot ?? "."));
159
+ const workspacePath = path.resolve(cwd, parsed.workspaceRoot ?? ".");
160
+ if (parsed.transport === "http") {
161
+ const server = await serveAcpHttp(runtime, {
162
+ hostname: parsed.hostname,
163
+ port: parsed.port,
164
+ });
165
+ stderr(`Serving ACP over http from ${workspacePath} at ${server.rpcUrl} (events ${server.eventsUrl})\n`);
166
+ await server.completed;
167
+ }
168
+ else {
169
+ stderr(`Serving ACP over stdio from ${workspacePath}\n`);
170
+ const server = serveAcp(runtime);
171
+ await server.completed;
172
+ }
173
+ await runtime.stop();
174
+ return 0;
175
+ }
176
+ catch (error) {
177
+ const message = error instanceof Error ? error.message : String(error);
178
+ stderr(`${message}\n`);
179
+ return 1;
180
+ }
181
+ }
84
182
  stderr(renderUsage());
85
183
  return 1;
86
184
  }
@@ -593,6 +593,11 @@ export type RuntimeEvaluationArtifact = ArtifactRecord & {
593
593
  export type RuntimeEvaluationExport = {
594
594
  session: SessionRecord | null;
595
595
  request: RequestRecord | null;
596
+ runRequest: {
597
+ input: MessageContent;
598
+ invocation?: InvocationEnvelope;
599
+ priority?: number;
600
+ } | null;
596
601
  approvals: ApprovalRecord[];
597
602
  transcript: TranscriptMessage[];
598
603
  events: HarnessEvent[];
@@ -603,6 +608,54 @@ export type RuntimeEvaluationExport = {
603
608
  tags: string[];
604
609
  metadata?: Record<string, unknown>;
605
610
  };
611
+ export type RuntimeEvaluationReplayInput = {
612
+ bundle: RuntimeEvaluationExport;
613
+ agentId?: string;
614
+ sessionId?: string;
615
+ invocation?: InvocationEnvelope;
616
+ };
617
+ export type RuntimeEvaluationReplayResult = {
618
+ request: {
619
+ agentId: string;
620
+ input: MessageContent;
621
+ invocation?: InvocationEnvelope;
622
+ sessionId?: string;
623
+ };
624
+ result: RunResult;
625
+ assertions: {
626
+ expectedOutputMatched?: boolean;
627
+ };
628
+ };
629
+ export type RuntimeRunPackageInput = {
630
+ sessionId: string;
631
+ requestId: string;
632
+ includeArtifacts?: boolean;
633
+ includeArtifactContents?: boolean;
634
+ includeRuntimeHealth?: boolean;
635
+ };
636
+ export type RuntimeRunPackage = {
637
+ session: SessionRecord | null;
638
+ request: RequestRecord | null;
639
+ approvals: ApprovalRecord[];
640
+ transcript: TranscriptMessage[];
641
+ events: HarnessEvent[];
642
+ artifacts: RuntimeEvaluationArtifact[];
643
+ runtimeHealth?: RuntimeHealthSnapshot;
644
+ };
645
+ export type RuntimeSessionPackageInput = {
646
+ sessionId: string;
647
+ includeArtifacts?: boolean;
648
+ includeArtifactContents?: boolean;
649
+ includeRuntimeHealth?: boolean;
650
+ };
651
+ export type RuntimeSessionPackage = {
652
+ session: SessionRecord | null;
653
+ requests: RequestRecord[];
654
+ approvals: ApprovalRecord[];
655
+ transcript: TranscriptMessage[];
656
+ runs: RuntimeRunPackage[];
657
+ runtimeHealth?: RuntimeHealthSnapshot;
658
+ };
606
659
  export type RuntimeInventoryContext = {
607
660
  workspace: WorkspaceBundle;
608
661
  };
@@ -234,6 +234,7 @@ export type CompiledAgentBinding = {
234
234
  workspaceRoot?: string;
235
235
  capabilities?: RuntimeCapabilities;
236
236
  resilience?: Record<string, unknown>;
237
+ governance?: Record<string, unknown>;
237
238
  deepagent?: {
238
239
  description?: string;
239
240
  passthrough?: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
1
+ export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
2
2
  export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRunRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
3
- export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, UpdateMemoryInput, UserChatInput, UserChatMessage, } from "./api.js";
3
+ export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, UpdateMemoryInput, UserChatInput, UserChatMessage, } from "./api.js";
4
4
  export type { BuildFlowGraphInput, FlowEdge, FlowEdgeKind, FlowGraph, FlowGraphMermaidOptions, FlowGraphSequenceMermaidOptions, FlowGroup, FlowGroupKind, FlowNode, FlowNodeKind, FlowNodeLayer, FlowNodeStatus, } from "./flow/index.js";
5
+ export type { AcpHttpServer, AcpHttpServerOptions, AcpStdioServer, AcpStdioServerOptions } from "./api.js";
5
6
  export type { ToolMcpServerOptions } from "./mcp.js";
6
7
  export { tool } from "./tools.js";
7
8
  export type { UpstreamTimelineProjection, UpstreamTimelineReducer } from "./upstream-events.js";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
1
+ export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
2
2
  export { tool } from "./tools.js";
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.158";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.160";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.158";
1
+ export const AGENT_HARNESS_VERSION = "0.0.160";
@@ -0,0 +1,20 @@
1
+ import { type Server } from "node:http";
2
+ import type { AgentHarnessRuntime } from "../../runtime/harness.js";
3
+ export type AcpHttpServerOptions = {
4
+ hostname?: string;
5
+ port?: number;
6
+ rpcPath?: string;
7
+ eventsPath?: string;
8
+ };
9
+ export type AcpHttpServer = {
10
+ hostname: string;
11
+ port: number;
12
+ rpcPath: string;
13
+ eventsPath: string;
14
+ rpcUrl: string;
15
+ eventsUrl: string;
16
+ completed: Promise<void>;
17
+ close: () => Promise<void>;
18
+ };
19
+ export declare function serveAcpOverHttp(runtime: AgentHarnessRuntime, options?: AcpHttpServerOptions): Promise<AcpHttpServer>;
20
+ export type { Server as AcpHttpNodeServer };
@@ -0,0 +1,130 @@
1
+ import { createServer } from "node:http";
2
+ import { createAcpServer } from "../../acp.js";
3
+ function normalizePath(value, fallback) {
4
+ const source = typeof value === "string" && value.trim().length > 0 ? value.trim() : fallback;
5
+ return source.startsWith("/") ? source : `/${source}`;
6
+ }
7
+ function writeJson(response, statusCode, payload) {
8
+ response.statusCode = statusCode;
9
+ response.setHeader("content-type", "application/json; charset=utf-8");
10
+ response.end(JSON.stringify(payload));
11
+ }
12
+ function readRequestBody(request) {
13
+ return new Promise((resolve, reject) => {
14
+ const chunks = [];
15
+ request.on("data", (chunk) => {
16
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
17
+ });
18
+ request.on("end", () => {
19
+ resolve(Buffer.concat(chunks).toString("utf8"));
20
+ });
21
+ request.on("error", reject);
22
+ });
23
+ }
24
+ export async function serveAcpOverHttp(runtime, options = {}) {
25
+ const hostname = options.hostname?.trim() || "127.0.0.1";
26
+ const port = typeof options.port === "number" && Number.isFinite(options.port) ? options.port : 0;
27
+ const rpcPath = normalizePath(options.rpcPath, "/rpc");
28
+ const eventsPath = normalizePath(options.eventsPath, "/events");
29
+ const server = createAcpServer(runtime);
30
+ const eventSubscribers = new Set();
31
+ const unsubscribe = server.subscribe((notification) => {
32
+ const payload = `data: ${JSON.stringify(notification)}\n\n`;
33
+ for (const response of Array.from(eventSubscribers)) {
34
+ if (response.writableEnded || response.destroyed) {
35
+ eventSubscribers.delete(response);
36
+ continue;
37
+ }
38
+ response.write(payload);
39
+ }
40
+ });
41
+ const httpServer = createServer(async (request, response) => {
42
+ try {
43
+ const requestUrl = new URL(request.url ?? "/", `http://${hostname}`);
44
+ if (request.method === "GET" && requestUrl.pathname === eventsPath) {
45
+ response.statusCode = 200;
46
+ response.setHeader("content-type", "text/event-stream; charset=utf-8");
47
+ response.setHeader("cache-control", "no-cache, no-transform");
48
+ response.setHeader("connection", "keep-alive");
49
+ response.write(": connected\n\n");
50
+ eventSubscribers.add(response);
51
+ request.on("close", () => {
52
+ eventSubscribers.delete(response);
53
+ response.end();
54
+ });
55
+ return;
56
+ }
57
+ if (request.method === "POST" && requestUrl.pathname === rpcPath) {
58
+ const body = await readRequestBody(request);
59
+ let payload;
60
+ try {
61
+ payload = JSON.parse(body);
62
+ }
63
+ catch {
64
+ writeJson(response, 400, {
65
+ jsonrpc: "2.0",
66
+ id: null,
67
+ error: {
68
+ code: -32700,
69
+ message: "Invalid JSON payload.",
70
+ },
71
+ });
72
+ return;
73
+ }
74
+ const rpcResponse = await server.handle(payload);
75
+ if (!rpcResponse) {
76
+ response.statusCode = 204;
77
+ response.end();
78
+ return;
79
+ }
80
+ writeJson(response, 200, rpcResponse);
81
+ return;
82
+ }
83
+ writeJson(response, 404, {
84
+ error: "Not Found",
85
+ rpcPath,
86
+ eventsPath,
87
+ });
88
+ }
89
+ catch (error) {
90
+ writeJson(response, 500, {
91
+ error: error instanceof Error ? error.message : "ACP HTTP transport failed.",
92
+ });
93
+ }
94
+ });
95
+ const completed = new Promise((resolve, reject) => {
96
+ httpServer.once("close", resolve);
97
+ httpServer.once("error", reject);
98
+ });
99
+ await new Promise((resolve, reject) => {
100
+ httpServer.listen(port, hostname, () => resolve());
101
+ httpServer.once("error", reject);
102
+ });
103
+ const address = httpServer.address();
104
+ const resolvedPort = typeof address === "object" && address ? address.port : port;
105
+ return {
106
+ hostname,
107
+ port: resolvedPort,
108
+ rpcPath,
109
+ eventsPath,
110
+ rpcUrl: `http://${hostname}:${resolvedPort}${rpcPath}`,
111
+ eventsUrl: `http://${hostname}:${resolvedPort}${eventsPath}`,
112
+ completed,
113
+ close: async () => {
114
+ unsubscribe();
115
+ for (const response of Array.from(eventSubscribers)) {
116
+ response.end();
117
+ }
118
+ eventSubscribers.clear();
119
+ await new Promise((resolve, reject) => {
120
+ httpServer.close((error) => {
121
+ if (error) {
122
+ reject(error);
123
+ return;
124
+ }
125
+ resolve();
126
+ });
127
+ });
128
+ },
129
+ };
130
+ }
@@ -0,0 +1,11 @@
1
+ import type { Readable, Writable } from "node:stream";
2
+ import type { AgentHarnessRuntime } from "../../runtime/harness.js";
3
+ export type AcpStdioServerOptions = {
4
+ input?: Readable;
5
+ output?: Writable;
6
+ };
7
+ export type AcpStdioServer = {
8
+ completed: Promise<void>;
9
+ close: () => Promise<void>;
10
+ };
11
+ export declare function serveAcpOverStdio(runtime: AgentHarnessRuntime, options?: AcpStdioServerOptions): AcpStdioServer;
@@ -0,0 +1,69 @@
1
+ import { createInterface } from "node:readline";
2
+ import { createAcpServer } from "../../acp.js";
3
+ function writeJsonLine(output, payload) {
4
+ return new Promise((resolve, reject) => {
5
+ output.write(`${JSON.stringify(payload)}\n`, (error) => {
6
+ if (error) {
7
+ reject(error);
8
+ return;
9
+ }
10
+ resolve();
11
+ });
12
+ });
13
+ }
14
+ export function serveAcpOverStdio(runtime, options = {}) {
15
+ const input = options.input ?? process.stdin;
16
+ const output = options.output ?? process.stdout;
17
+ const server = createAcpServer(runtime);
18
+ const unsubscribe = server.subscribe((notification) => {
19
+ void writeJsonLine(output, notification);
20
+ });
21
+ const lineReader = createInterface({
22
+ input,
23
+ crlfDelay: Infinity,
24
+ });
25
+ const completed = (async () => {
26
+ try {
27
+ for await (const line of lineReader) {
28
+ const trimmed = line.trim();
29
+ if (trimmed.length === 0) {
30
+ continue;
31
+ }
32
+ let request;
33
+ try {
34
+ request = JSON.parse(trimmed);
35
+ }
36
+ catch {
37
+ await writeJsonLine(output, {
38
+ jsonrpc: "2.0",
39
+ id: null,
40
+ error: {
41
+ code: -32700,
42
+ message: "Invalid JSON payload.",
43
+ },
44
+ });
45
+ continue;
46
+ }
47
+ const response = await server.handle(request);
48
+ if (response) {
49
+ await writeJsonLine(output, response);
50
+ }
51
+ }
52
+ }
53
+ finally {
54
+ unsubscribe();
55
+ lineReader.close();
56
+ }
57
+ })();
58
+ return {
59
+ completed,
60
+ close: async () => {
61
+ unsubscribe();
62
+ lineReader.close();
63
+ if (typeof input.destroy === "function") {
64
+ input.destroy();
65
+ }
66
+ await completed.catch(() => undefined);
67
+ },
68
+ };
69
+ }
@@ -43,8 +43,67 @@ function toCategory(toolType) {
43
43
  }
44
44
  return "local";
45
45
  }
46
+ function asObject(value) {
47
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
48
+ }
49
+ function readStringArray(value) {
50
+ return Array.isArray(value)
51
+ ? value.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
52
+ : [];
53
+ }
54
+ function readRisk(value) {
55
+ return value === "low" || value === "medium" || value === "high" ? value : undefined;
56
+ }
57
+ function readApprovalPolicy(value) {
58
+ return value === "explicit-hitl" || value === "runtime-default" || value === "none" ? value : undefined;
59
+ }
60
+ function matchesToolPolicy(rule, policy) {
61
+ const match = asObject(rule.match) ?? rule;
62
+ const toolName = typeof match.toolName === "string" ? match.toolName.trim() : undefined;
63
+ const category = typeof match.category === "string" ? match.category.trim() : undefined;
64
+ const toolType = typeof match.toolType === "string" ? match.toolType.trim() : undefined;
65
+ return (!toolName || toolName === policy.toolName)
66
+ && (!category || category === policy.category)
67
+ && (!toolType || toolType === policy.toolType);
68
+ }
69
+ function applyGovernanceOverrides(binding, policies) {
70
+ const governance = asObject(binding.harnessRuntime.governance);
71
+ const overrides = Array.isArray(governance?.toolPolicies) ? governance.toolPolicies : [];
72
+ if (overrides.length === 0) {
73
+ return policies;
74
+ }
75
+ return policies.map((policy) => {
76
+ const merged = { ...policy };
77
+ for (const rule of overrides) {
78
+ const typedRule = asObject(rule);
79
+ if (!typedRule || !matchesToolPolicy(typedRule, merged)) {
80
+ continue;
81
+ }
82
+ const overrideRisk = readRisk(typedRule.risk);
83
+ const overrideApprovalPolicy = readApprovalPolicy(typedRule.approvalPolicy);
84
+ const overrideRequiresApproval = typeof typedRule.requiresApproval === "boolean" ? typedRule.requiresApproval : undefined;
85
+ if (overrideRisk) {
86
+ merged.risk = overrideRisk;
87
+ }
88
+ if (overrideRequiresApproval !== undefined) {
89
+ merged.requiresApproval = overrideRequiresApproval;
90
+ }
91
+ if (overrideApprovalPolicy) {
92
+ merged.approvalPolicy = overrideApprovalPolicy;
93
+ }
94
+ else if (overrideRequiresApproval === true && merged.approvalPolicy === "none") {
95
+ merged.approvalPolicy = "runtime-default";
96
+ }
97
+ const extraHints = readStringArray(typedRule.inputRiskHints);
98
+ if (extraHints.length > 0) {
99
+ merged.inputRiskHints = Array.from(new Set([...merged.inputRiskHints, ...extraHints]));
100
+ }
101
+ }
102
+ return merged;
103
+ });
104
+ }
46
105
  export function buildRuntimeGovernanceBundles(binding) {
47
- const toolPolicies = getBindingPrimaryTools(binding).map((tool) => {
106
+ const toolPolicies = applyGovernanceOverrides(binding, getBindingPrimaryTools(binding).map((tool) => {
48
107
  const requiresApproval = toolRequiresRuntimeApproval(tool);
49
108
  return {
50
109
  toolName: tool.name,
@@ -63,7 +122,7 @@ export function buildRuntimeGovernanceBundles(binding) {
63
122
  hasInputSchema: typeof tool.inputSchemaRef === "string" && tool.inputSchemaRef.trim().length > 0,
64
123
  inputRiskHints: inputHints(binding, tool),
65
124
  };
66
- });
125
+ }));
67
126
  if (toolPolicies.length === 0) {
68
127
  return [];
69
128
  }
@@ -9,6 +9,35 @@ export class PolicyEngine {
9
9
  const reasons = [];
10
10
  const bundles = [];
11
11
  let allowed = true;
12
+ const governance = typeof binding.harnessRuntime.governance === "object" && binding.harnessRuntime.governance
13
+ ? binding.harnessRuntime.governance
14
+ : undefined;
15
+ const denyConfig = typeof governance?.deny === "object" && governance.deny
16
+ ? governance.deny
17
+ : undefined;
18
+ if (denyConfig) {
19
+ const deniedNames = new Set(Array.isArray(denyConfig.toolNames)
20
+ ? denyConfig.toolNames.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
21
+ : []);
22
+ const deniedCategories = new Set(Array.isArray(denyConfig.categories)
23
+ ? denyConfig.categories.filter((item) => typeof item === "string" && item.trim().length > 0).map((item) => item.trim())
24
+ : []);
25
+ const tools = binding.execution?.params?.tools ?? binding.langchainAgentParams?.tools ?? binding.deepAgentParams?.tools ?? [];
26
+ const blocked = tools.filter((tool) => {
27
+ const category = tool.type === "mcp"
28
+ ? "mcp"
29
+ : tool.type === "backend"
30
+ ? "backend"
31
+ : tool.type === "provider"
32
+ ? "provider-native"
33
+ : "local";
34
+ return deniedNames.has(tool.name) || deniedCategories.has(category);
35
+ });
36
+ if (blocked.length > 0) {
37
+ allowed = false;
38
+ reasons.push(`runtime governance denied tool access: ${blocked.map((tool) => tool.name).join(", ")}`);
39
+ }
40
+ }
12
41
  for (const evaluator of getPolicyEvaluators()) {
13
42
  const decision = evaluator.evaluate(binding);
14
43
  if (!decision) {
@@ -1,4 +1,4 @@
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";
1
+ import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, 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";
@@ -85,7 +85,10 @@ export declare class AgentHarnessRuntime {
85
85
  listArtifacts(threadId: string, runId: string): Promise<ArtifactListing>;
86
86
  readArtifact(threadId: string, runId: string, artifactPath: string): Promise<unknown>;
87
87
  listRunEvents(threadId: string, runId: string): Promise<HarnessEvent[]>;
88
+ exportRunPackage(input: RuntimeRunPackageInput): Promise<RuntimeRunPackage>;
89
+ exportSessionPackage(input: RuntimeSessionPackageInput): Promise<RuntimeSessionPackage>;
88
90
  exportEvaluationBundle(input: RuntimeEvaluationExportInput): Promise<RuntimeEvaluationExport>;
91
+ replayEvaluationBundle(input: RuntimeEvaluationReplayInput): Promise<RuntimeEvaluationReplayResult>;
89
92
  listAgentSkills(agentId: string, options?: RequirementAssessmentOptions): InventorySkillRecord[];
90
93
  getAgent(agentId: string, options?: RequirementAssessmentOptions): InventoryAgentRecord | null;
91
94
  describeWorkspaceInventory(options?: RequirementAssessmentOptions): {
@@ -484,9 +484,54 @@ export class AgentHarnessRuntime {
484
484
  async listRunEvents(threadId, runId) {
485
485
  return this.persistence.listRunEvents(threadId, runId);
486
486
  }
487
+ async exportRunPackage(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 artifactsListing = input.includeArtifacts === false
494
+ ? { items: [] }
495
+ : await this.persistence.listArtifacts(input.sessionId, input.requestId);
496
+ const artifacts = await Promise.all(artifactsListing.items.map(async (artifact) => ({
497
+ ...artifact,
498
+ ...(input.includeArtifactContents === true
499
+ ? { content: await this.persistence.readArtifact(input.sessionId, input.requestId, artifact.path) }
500
+ : {}),
501
+ })));
502
+ return {
503
+ session: thread ? toSessionRecord(thread) : null,
504
+ request: run ? toRequestRecord(run) : null,
505
+ approvals,
506
+ transcript,
507
+ events,
508
+ artifacts,
509
+ ...(input.includeRuntimeHealth === false ? {} : { runtimeHealth: await this.getHealth() }),
510
+ };
511
+ }
512
+ async exportSessionPackage(input) {
513
+ const thread = await this.getThread(input.sessionId);
514
+ const runIds = Array.from(new Set((thread?.runs ?? []).map((item) => item.runId)));
515
+ const runs = await Promise.all(runIds.map((requestId) => this.exportRunPackage({
516
+ sessionId: input.sessionId,
517
+ requestId,
518
+ includeArtifacts: input.includeArtifacts,
519
+ includeArtifactContents: input.includeArtifactContents,
520
+ includeRuntimeHealth: false,
521
+ })));
522
+ return {
523
+ session: thread ? toSessionRecord(thread) : null,
524
+ requests: runs.map((item) => item.request).filter((item) => Boolean(item)),
525
+ approvals: await this.listApprovals({ threadId: input.sessionId }),
526
+ transcript: await this.persistence.listThreadMessages(input.sessionId, 500),
527
+ runs,
528
+ ...(input.includeRuntimeHealth === false ? {} : { runtimeHealth: await this.getHealth() }),
529
+ };
530
+ }
487
531
  async exportEvaluationBundle(input) {
488
532
  const thread = await this.getThread(input.sessionId);
489
533
  const run = await this.getRun(input.requestId);
534
+ const runRequest = await this.persistence.getRunRequest(input.sessionId, input.requestId);
490
535
  const approvals = await this.listApprovals({ threadId: input.sessionId, runId: input.requestId });
491
536
  const transcript = await this.persistence.listThreadMessages(input.sessionId, 500);
492
537
  const events = await this.persistence.listRunEvents(input.sessionId, input.requestId);
@@ -503,6 +548,13 @@ export class AgentHarnessRuntime {
503
548
  return {
504
549
  session: thread ? toSessionRecord(thread) : null,
505
550
  request: run ? toRequestRecord(run) : null,
551
+ runRequest: runRequest
552
+ ? {
553
+ input: runRequest.input,
554
+ ...(runRequest.invocation ? { invocation: runRequest.invocation } : {}),
555
+ ...(typeof runRequest.priority === "number" ? { priority: runRequest.priority } : {}),
556
+ }
557
+ : (deriveRunRequestFromTranscript(transcript, input.requestId) ?? null),
506
558
  approvals,
507
559
  transcript,
508
560
  events,
@@ -520,6 +572,36 @@ export class AgentHarnessRuntime {
520
572
  ...(input.metadata ? { metadata: { ...input.metadata } } : {}),
521
573
  };
522
574
  }
575
+ async replayEvaluationBundle(input) {
576
+ const replayAgentId = input.agentId ?? input.bundle.request?.agentId ?? input.bundle.session?.entryAgentId;
577
+ if (!replayAgentId) {
578
+ throw new Error("Evaluation replay requires an agentId on the replay input or exported bundle.");
579
+ }
580
+ const replayRequest = input.bundle.runRequest ?? deriveRunRequestFromTranscript(input.bundle.transcript, input.bundle.request?.requestId);
581
+ if (!replayRequest) {
582
+ throw new Error("Evaluation replay requires bundle.runRequest from exportEvaluationBundle.");
583
+ }
584
+ const invocation = input.invocation ?? replayRequest.invocation;
585
+ const result = await this.run({
586
+ agentId: replayAgentId,
587
+ input: replayRequest.input,
588
+ ...(input.sessionId ? { threadId: input.sessionId } : {}),
589
+ ...(invocation ? { invocation } : {}),
590
+ });
591
+ const expected = typeof input.bundle.expectedOutput === "string" ? input.bundle.expectedOutput.trim() : "";
592
+ return {
593
+ request: {
594
+ agentId: replayAgentId,
595
+ input: replayRequest.input,
596
+ ...(invocation ? { invocation } : {}),
597
+ ...(input.sessionId ? { sessionId: input.sessionId } : {}),
598
+ },
599
+ result,
600
+ assertions: {
601
+ ...(expected.length > 0 ? { expectedOutputMatched: result.output.includes(expected) } : {}),
602
+ },
603
+ };
604
+ }
523
605
  listAgentSkills(agentId, options = {}) {
524
606
  return listWorkspaceAgentSkills(this.workspace, agentId, {
525
607
  assessRequirements: isInventoryEnabled(this.workspace),
@@ -1475,3 +1557,9 @@ function toSessionRecord(record) {
1475
1557
  function toRequestRecord(record) {
1476
1558
  return toRequestSummary(record);
1477
1559
  }
1560
+ function deriveRunRequestFromTranscript(transcript, runId) {
1561
+ const candidate = [...transcript]
1562
+ .reverse()
1563
+ .find((message) => message.role === "user" && (!runId || message.runId === runId));
1564
+ return candidate ? { input: candidate.content } : null;
1565
+ }
@@ -340,6 +340,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
340
340
  const runtimeFilesystemDefaults = agent.executionMode === "langchain-v1"
341
341
  ? asObject(runtimeDefaults?.filesystem)
342
342
  : undefined;
343
+ const runtimeGovernanceDefaults = asObject(runtimeDefaults?.governance);
343
344
  const compiledFilesystemConfig = agent.executionMode === "langchain-v1"
344
345
  ? mergeConfigObjects(runtimeFilesystemDefaults, getAgentExecutionObject(agent, "filesystem", { executionMode: "langchain-v1" }))
345
346
  : undefined;
@@ -355,6 +356,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
355
356
  workspaceRoot,
356
357
  capabilities: inferAgentCapabilities(agent),
357
358
  resilience,
359
+ ...(runtimeGovernanceDefaults ? { governance: runtimeGovernanceDefaults } : {}),
358
360
  ...(agent.executionMode === "deepagent"
359
361
  ? {
360
362
  deepagent: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.159",
3
+ "version": "0.0.161",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",