@botbotgo/agent-harness 0.0.37 → 0.0.39
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 +79 -137
- package/dist/api.d.ts +15 -12
- package/dist/api.js +25 -41
- package/dist/config/embedding-model.yaml +2 -2
- package/dist/config/workspace.yaml +37 -3
- package/dist/contracts/types.d.ts +17 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp.d.ts +8 -3
- package/dist/mcp.js +10 -11
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/resource/resource-impl.d.ts +2 -1
- package/dist/resource/resource-impl.js +16 -11
- package/dist/resource/resource.d.ts +1 -1
- package/dist/resource/resource.js +1 -1
- package/dist/runtime/agent-runtime-adapter.js +4 -2
- package/dist/runtime/event-bus.d.ts +5 -4
- package/dist/runtime/event-bus.js +7 -9
- package/dist/runtime/event-sink.d.ts +9 -0
- package/dist/runtime/event-sink.js +35 -0
- package/dist/runtime/harness.d.ts +21 -12
- package/dist/runtime/harness.js +81 -31
- package/dist/runtime/index.d.ts +3 -1
- package/dist/runtime/index.js +2 -1
- package/dist/runtime/parsing/stream-event-parsing.d.ts +2 -0
- package/dist/runtime/parsing/stream-event-parsing.js +35 -3
- package/dist/runtime/support/harness-support.d.ts +1 -0
- package/dist/runtime/support/harness-support.js +38 -4
- package/dist/runtime/thread-memory-sync.d.ts +4 -2
- package/dist/runtime/thread-memory-sync.js +10 -1
- package/dist/workspace/agent-binding-compiler.js +0 -3
- package/dist/workspace/compile.js +0 -1
- package/dist/workspace/support/discovery.js +11 -8
- package/dist/workspace/support/source-collectors.js +1 -1
- package/dist/workspace/support/workspace-ref-utils.d.ts +19 -0
- package/dist/workspace/support/workspace-ref-utils.js +112 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,33 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
## Product Overview
|
|
4
4
|
|
|
5
|
-
`@botbotgo/agent-harness`
|
|
5
|
+
`@botbotgo/agent-harness` solves the gap between an agent execution engine and a real multi-agent application runtime.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The problem:
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
- discover tools and SKILL packages from `resources/`
|
|
13
|
-
- bridge remote MCP servers into agent toolsets
|
|
14
|
-
- expose harness-managed tools as an MCP server
|
|
15
|
-
- run through either LangChain v1 or DeepAgents with one app-facing API
|
|
9
|
+
- agent logic, tools, MCP, routing, memory, and approvals usually end up scattered across code and scripts
|
|
10
|
+
- execution frameworks can run agents, but they do not give you a workspace-shaped product runtime by themselves
|
|
11
|
+
- applications need persisted threads, resumability, approvals, and operational control, not just model calls
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
What this package provides:
|
|
18
14
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- thread state, approvals, resumability, and maintenance are built in
|
|
15
|
+
- a workspace runtime for multi-agent applications
|
|
16
|
+
- YAML-defined agents, models, routing, and maintenance policy
|
|
17
|
+
- local tools and SKILL packages loaded from `resources/`
|
|
18
|
+
- DeepAgents-first execution with LangChain v1 compatibility
|
|
19
|
+
- feature-level runtime APIs for runs, threads, approvals, and events
|
|
25
20
|
|
|
26
21
|
Core API:
|
|
27
22
|
|
|
28
23
|
- `createAgentHarness(...)`
|
|
29
24
|
- `run(...)`
|
|
30
25
|
- `subscribe(...)`
|
|
26
|
+
- `listThreads(...)`
|
|
31
27
|
- `getThread(...)`
|
|
28
|
+
- `listApprovals(...)`
|
|
29
|
+
- `getApproval(...)`
|
|
32
30
|
- `stop(...)`
|
|
33
31
|
|
|
34
32
|
## Quick Start
|
|
@@ -39,7 +37,7 @@ Install the package:
|
|
|
39
37
|
npm install @botbotgo/agent-harness
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
Workspace layout:
|
|
43
41
|
|
|
44
42
|
```text
|
|
45
43
|
your-workspace/
|
|
@@ -56,109 +54,83 @@ your-workspace/
|
|
|
56
54
|
skills/
|
|
57
55
|
```
|
|
58
56
|
|
|
59
|
-
Use the standard layout only. Agent entry files must live under `config/agents
|
|
57
|
+
Use the standard layout only. Agent entry files must live under `config/agents/`.
|
|
60
58
|
|
|
61
59
|
Minimal usage:
|
|
62
60
|
|
|
63
61
|
```ts
|
|
64
62
|
import { createAgentHarness, run, stop } from "@botbotgo/agent-harness";
|
|
65
63
|
|
|
66
|
-
const
|
|
64
|
+
const runtime = await createAgentHarness("/absolute/path/to/your-workspace");
|
|
67
65
|
|
|
68
66
|
try {
|
|
69
|
-
const result = await run(
|
|
70
|
-
agentId: "
|
|
67
|
+
const result = await run(runtime, {
|
|
68
|
+
agentId: "auto",
|
|
71
69
|
input: "Summarize what this workspace is for.",
|
|
72
70
|
});
|
|
73
71
|
|
|
74
72
|
console.log(result.output);
|
|
75
73
|
} finally {
|
|
76
|
-
await stop(
|
|
74
|
+
await stop(runtime);
|
|
77
75
|
}
|
|
78
76
|
```
|
|
79
77
|
|
|
80
78
|
## Feature List
|
|
81
79
|
|
|
82
|
-
-
|
|
83
|
-
-
|
|
84
|
-
- Built-in routing for direct and orchestration flows
|
|
80
|
+
- Workspace runtime with DeepAgents-first execution and LangChain v1 compatibility
|
|
81
|
+
- YAML-defined host routing through `config/workspace.yaml`
|
|
85
82
|
- Auto-discovered local tools and SKILL packages from `resources/tools/` and `resources/skills/`
|
|
86
|
-
- MCP bridge support
|
|
87
|
-
- MCP server support
|
|
88
|
-
-
|
|
89
|
-
-
|
|
83
|
+
- MCP bridge support for agent-declared servers
|
|
84
|
+
- MCP server support for exposing an agent toolset to other clients
|
|
85
|
+
- Persisted threads, approvals, run lifecycle, and resumable checkpoints
|
|
86
|
+
- Background checkpoint maintenance
|
|
90
87
|
|
|
91
88
|
## How To Use
|
|
92
89
|
|
|
93
|
-
### Create A
|
|
94
|
-
|
|
95
|
-
Pass a workspace root:
|
|
90
|
+
### Create A Runtime
|
|
96
91
|
|
|
97
92
|
```ts
|
|
98
|
-
import { createAgentHarness } from "@botbotgo/agent-harness";
|
|
93
|
+
import { AgentHarnessRuntime, createAgentHarness } from "@botbotgo/agent-harness";
|
|
99
94
|
|
|
100
|
-
const
|
|
95
|
+
const runtime: AgentHarnessRuntime = await createAgentHarness("/absolute/path/to/workspace");
|
|
101
96
|
```
|
|
102
97
|
|
|
103
|
-
Or
|
|
98
|
+
Or:
|
|
104
99
|
|
|
105
100
|
```ts
|
|
106
|
-
const
|
|
101
|
+
const runtime = await createAgentHarness(workspaceBundle);
|
|
107
102
|
```
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
- `createAgentHarness(workspaceRoot)` loads and compiles one `WorkspaceBundle` before the runtime starts
|
|
112
|
-
- the loader reads `config/workspace.yaml`, `config/models.yaml`, `config/agent-context.md`, and every `config/agents/*.yaml` entry file, then validates the final topology
|
|
113
|
-
- local resource refs are hydrated after config load, so `resources/tools/`, `resources/skills/`, and agent-declared MCP servers are resolved before the harness accepts runs
|
|
114
|
-
- after compilation, the harness initializes persistence under the resolved `runRoot`, wires the runtime adapter, starts thread-memory syncing, and starts checkpoint maintenance when configured
|
|
104
|
+
`createAgentHarness(workspaceRoot)` loads one `WorkspaceBundle`, resolves `resources/`, initializes persistence under `runRoot`, and starts runtime maintenance.
|
|
115
105
|
|
|
116
106
|
### Run A Request
|
|
117
107
|
|
|
118
108
|
```ts
|
|
119
109
|
import { run } from "@botbotgo/agent-harness";
|
|
120
110
|
|
|
121
|
-
const result = await run(
|
|
122
|
-
agentId: "
|
|
111
|
+
const result = await run(runtime, {
|
|
112
|
+
agentId: "orchestra",
|
|
123
113
|
input: "Explain the available agents in this workspace.",
|
|
124
114
|
});
|
|
125
115
|
```
|
|
126
116
|
|
|
127
|
-
The result includes
|
|
128
|
-
|
|
129
|
-
- `threadId`
|
|
130
|
-
- `runId`
|
|
131
|
-
- `state`
|
|
132
|
-
- `output`
|
|
133
|
-
|
|
134
|
-
Runtime behavior:
|
|
117
|
+
Each run creates or continues a persisted thread. The result includes `threadId`, `runId`, `state`, and `output`.
|
|
135
118
|
|
|
136
|
-
|
|
137
|
-
- the harness stores thread metadata, run lifecycle, streamed events, approvals, delegations, and artifacts on disk so `getThread(...)` can reconstruct the session later
|
|
138
|
-
- when a store is configured, the harness also mirrors thread status and open approvals into `/memories/threads/<threadId>/`
|
|
139
|
-
- `stop(...)` should always be called so background persistence and maintenance loops shut down cleanly
|
|
140
|
-
|
|
141
|
-
### Let The Harness Choose The Host Agent
|
|
142
|
-
|
|
143
|
-
Use `agentId: "auto"` when your workspace defines routing:
|
|
119
|
+
### Let The Runtime Route
|
|
144
120
|
|
|
145
121
|
```ts
|
|
146
|
-
const result = await run(
|
|
122
|
+
const result = await run(runtime, {
|
|
147
123
|
agentId: "auto",
|
|
148
124
|
input: "Inspect this repository and explain the release flow.",
|
|
149
125
|
});
|
|
150
126
|
```
|
|
151
127
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
- `agentId: "auto"` asks the runtime adapter to classify between the primary and secondary host bindings discovered from the workspace
|
|
155
|
-
- when the run belongs to an existing thread, the router includes recent conversation turns so follow-up requests can stay on the correct lane
|
|
156
|
-
- if no model-driven routing prompt is configured, the harness falls back to heuristic routing for obvious research or implementation-style requests
|
|
128
|
+
`agentId: "auto"` evaluates ordered `routing.rules` first, then falls back to `routing.defaultAgentId`, and only uses model routing when `routing.modelRouting: true`.
|
|
157
129
|
|
|
158
130
|
### Stream Output And Events
|
|
159
131
|
|
|
160
132
|
```ts
|
|
161
|
-
const result = await run(
|
|
133
|
+
const result = await run(runtime, {
|
|
162
134
|
agentId: "orchestra",
|
|
163
135
|
input: "Inspect the workspace and explain the available tools.",
|
|
164
136
|
listeners: {
|
|
@@ -172,12 +144,30 @@ const result = await run(harness, {
|
|
|
172
144
|
});
|
|
173
145
|
```
|
|
174
146
|
|
|
147
|
+
The runtime emits typed lifecycle events for output, state changes, approvals, and delegations. `subscribe(...)` is a read-only observer surface.
|
|
148
|
+
|
|
149
|
+
### Query Threads And Approvals
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import {
|
|
153
|
+
getApproval,
|
|
154
|
+
getThread,
|
|
155
|
+
listApprovals,
|
|
156
|
+
listThreads,
|
|
157
|
+
} from "@botbotgo/agent-harness";
|
|
158
|
+
|
|
159
|
+
const threads = await listThreads(runtime);
|
|
160
|
+
const thread = await getThread(runtime, threads[0]!.threadId);
|
|
161
|
+
const approvals = await listApprovals(runtime, { status: "pending" });
|
|
162
|
+
const approval = approvals[0] ? await getApproval(runtime, approvals[0].approvalId) : null;
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
These methods return stored runtime data, not raw persistence, workspace, or backend instances.
|
|
166
|
+
|
|
175
167
|
### Use Skills And Local Tools
|
|
176
168
|
|
|
177
169
|
`agent-harness` treats `resources/skills/` as SKILL packages and `resources/tools/` as executable local tools.
|
|
178
170
|
|
|
179
|
-
Point agent YAML at both:
|
|
180
|
-
|
|
181
171
|
```yaml
|
|
182
172
|
spec:
|
|
183
173
|
skills:
|
|
@@ -186,17 +176,10 @@ spec:
|
|
|
186
176
|
- ref: tool/local-toolset
|
|
187
177
|
```
|
|
188
178
|
|
|
189
|
-
Tool
|
|
190
|
-
|
|
191
|
-
- tool modules are discovered from `resources/tools/*.js`, `resources/tools/*.mjs`, and `resources/tools/*.cjs`
|
|
192
|
-
- the preferred format is exporting `tool({...})`; the harness also accepts exported functions plus `nameSchema`, `nameSchemaShape`, or generic `schema` metadata
|
|
193
|
-
- when a module exports exactly one tool function, generic `schema` or `schemaShape` metadata can describe that function
|
|
194
|
-
- keep runtime dependencies for local tools in `resources/package.json`, because the resource package is the execution boundary for those modules
|
|
179
|
+
Tool modules are discovered from `resources/tools/*.js`, `resources/tools/*.mjs`, and `resources/tools/*.cjs`. The preferred format is exporting `tool({...})`.
|
|
195
180
|
|
|
196
181
|
### Bridge MCP Servers Into Agents
|
|
197
182
|
|
|
198
|
-
Use `mcpServers:` inside agent YAML to bridge MCP servers into the agent's tool list:
|
|
199
|
-
|
|
200
183
|
```yaml
|
|
201
184
|
spec:
|
|
202
185
|
mcpServers:
|
|
@@ -209,82 +192,52 @@ spec:
|
|
|
209
192
|
token: ${DOCS_MCP_TOKEN}
|
|
210
193
|
```
|
|
211
194
|
|
|
212
|
-
The
|
|
195
|
+
The runtime discovers MCP tools, filters them through agent config, and exposes them like any other tool.
|
|
213
196
|
|
|
214
|
-
### Expose
|
|
215
|
-
|
|
216
|
-
Use the MCP server helpers when another client should connect to the harness as an MCP server:
|
|
197
|
+
### Expose Runtime Tools As An MCP Server
|
|
217
198
|
|
|
218
199
|
```ts
|
|
219
200
|
import { createToolMcpServer, serveToolsOverStdio } from "@botbotgo/agent-harness";
|
|
220
201
|
|
|
221
|
-
const server = await createToolMcpServer(
|
|
222
|
-
await serveToolsOverStdio(
|
|
202
|
+
const server = await createToolMcpServer(runtime, { agentId: "orchestra" });
|
|
203
|
+
await serveToolsOverStdio(runtime, { agentId: "orchestra" });
|
|
223
204
|
```
|
|
224
205
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
### Read Back Thread State
|
|
228
|
-
|
|
229
|
-
```ts
|
|
230
|
-
import { getThread } from "@botbotgo/agent-harness";
|
|
231
|
-
|
|
232
|
-
const thread = await getThread(harness, result.threadId);
|
|
233
|
-
console.log(thread?.messages.at(-1)?.content);
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Subscribe To Global Events
|
|
237
|
-
|
|
238
|
-
```ts
|
|
239
|
-
import { subscribe } from "@botbotgo/agent-harness";
|
|
240
|
-
|
|
241
|
-
const unsubscribe = subscribe(harness, (event) => {
|
|
242
|
-
console.log(event.threadId, event.runId, event.eventType);
|
|
243
|
-
});
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Stop The Harness
|
|
206
|
+
### Stop The Runtime
|
|
247
207
|
|
|
248
208
|
```ts
|
|
249
209
|
import { stop } from "@botbotgo/agent-harness";
|
|
250
210
|
|
|
251
|
-
await stop(
|
|
211
|
+
await stop(runtime);
|
|
252
212
|
```
|
|
253
213
|
|
|
254
214
|
## How To Configure
|
|
255
215
|
|
|
256
216
|
Core workspace files:
|
|
257
217
|
|
|
258
|
-
- `config/workspace.yaml`:
|
|
218
|
+
- `config/workspace.yaml`: runtime defaults such as `runRoot`, routing, and maintenance
|
|
259
219
|
- `config/agent-context.md`: shared bootstrap context for agents
|
|
260
220
|
- `config/models.yaml`: named model presets
|
|
261
|
-
- `config/agents/direct.yaml`: lightweight host
|
|
262
|
-
- `config/agents/orchestra.yaml`: default
|
|
221
|
+
- `config/agents/direct.yaml`: optional lightweight side-path host
|
|
222
|
+
- `config/agents/orchestra.yaml`: default DeepAgent execution host
|
|
263
223
|
- `resources/package.json`: resource package boundary
|
|
264
224
|
- `resources/tools/`: local tool modules
|
|
265
225
|
- `resources/skills/`: local skills
|
|
266
226
|
|
|
267
227
|
### `config/workspace.yaml`
|
|
268
228
|
|
|
269
|
-
Use this file for
|
|
229
|
+
Use this file for:
|
|
270
230
|
|
|
271
231
|
- `runRoot`
|
|
272
|
-
-
|
|
273
|
-
-
|
|
274
|
-
|
|
275
|
-
Implementation details:
|
|
232
|
+
- ordered `routing.rules`
|
|
233
|
+
- `routing.systemPrompt`
|
|
234
|
+
- `maintenance.checkpoints.*`
|
|
276
235
|
|
|
277
|
-
|
|
278
|
-
- the resolved `runRoot` stores thread indexes, per-thread transcripts, per-run events, approvals, delegations, artifacts, and checkpoint references
|
|
279
|
-
- checkpoint maintenance only starts when `maintenance.checkpoints.enabled: true`; for SQLite checkpoints, cleanup policies can sweep old rows and optionally `VACUUM` the database
|
|
236
|
+
If `runRoot` is omitted, the runtime defaults to `<workspace-root>/run-data`.
|
|
280
237
|
|
|
281
238
|
### `config/agent-context.md`
|
|
282
239
|
|
|
283
|
-
Use this file for shared bootstrap context that agents read at construction time.
|
|
284
|
-
|
|
285
|
-
Put stable project context here, not long-term mutable memory.
|
|
286
|
-
|
|
287
|
-
If a runnable app workspace also includes `AGENTS.md`, treat that file as workspace-level operating guidance. It complements `config/agents/*.yaml`: `AGENTS.md` carries durable behavioral rules, while `config/agents/` defines agent topology and runtime configuration.
|
|
240
|
+
Use this file for shared bootstrap context that agents read at construction time. Put stable project context here, not long-term mutable memory.
|
|
288
241
|
|
|
289
242
|
### Agent YAML
|
|
290
243
|
|
|
@@ -307,21 +260,10 @@ Use `resources/` for executable extensions:
|
|
|
307
260
|
- `resources/tools/` for local tool modules
|
|
308
261
|
- `resources/skills/` for SKILL packages
|
|
309
262
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
Implementation details:
|
|
313
|
-
|
|
314
|
-
- keep runtime extension source under `resources/`; keep tests outside the published source tree, for example under the repository `test/` folder
|
|
315
|
-
- `resources/package.json` is the module resolution boundary used when local tools import third-party packages or skill-local scripts
|
|
316
|
-
- SKILL packages stay file-based, so prompts, templates, helper scripts, and metadata can ship together without extra registration steps
|
|
263
|
+
Keep runtime extension source under `resources/`. Keep tests outside the published source tree, for example under the repository `test/` folder.
|
|
317
264
|
|
|
318
265
|
### Skills And MCP
|
|
319
266
|
|
|
320
|
-
- Use `resources/skills/` for
|
|
321
|
-
- Use `mcpServers:` in `config/agents/*.yaml`
|
|
322
|
-
- Use `createToolMcpServer(...)` or `serveToolsOverStdio(...)` when you want the
|
|
323
|
-
|
|
324
|
-
Implementation details:
|
|
325
|
-
|
|
326
|
-
- agent-declared `mcpServers:` entries are hydrated into concrete MCP tool refs during workspace compilation, then validated against the collected MCP server definitions
|
|
327
|
-
- `createToolMcpServer(...)` exposes the selected agent toolset through one MCP server surface; `serveToolsOverStdio(...)` is the stdio transport wrapper around that same server construction
|
|
267
|
+
- Use `resources/skills/` for reusable skill packages
|
|
268
|
+
- Use `mcpServers:` in `config/agents/*.yaml` to bridge external MCP tools into an agent
|
|
269
|
+
- Use `createToolMcpServer(...)` or `serveToolsOverStdio(...)` when you want the runtime to act as an MCP server for another client
|
package/dist/api.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { ApprovalRecord, RunOptions, RuntimeAdapterOptions, ThreadSummary, ThreadRecord, WorkspaceLoadOptions, WorkspaceBundle } from "./contracts/types.js";
|
|
2
|
+
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
3
|
import type { ToolMcpServerOptions } from "./mcp.js";
|
|
4
|
+
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
4
5
|
type CreateAgentHarnessOptions = {
|
|
5
6
|
load?: WorkspaceLoadOptions;
|
|
6
7
|
adapter?: RuntimeAdapterOptions;
|
|
7
8
|
};
|
|
8
|
-
export declare function createAgentHarness(): Promise<
|
|
9
|
-
export declare function createAgentHarness(workspaceRoot: string, options?: CreateAgentHarnessOptions): Promise<
|
|
10
|
-
export declare function createAgentHarness(workspace: WorkspaceBundle, options?: CreateAgentHarnessOptions): Promise<
|
|
11
|
-
export declare function run(
|
|
12
|
-
export declare function subscribe(
|
|
13
|
-
export declare function
|
|
14
|
-
export declare function
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function
|
|
17
|
-
export
|
|
9
|
+
export declare function createAgentHarness(): Promise<AgentHarnessRuntime>;
|
|
10
|
+
export declare function createAgentHarness(workspaceRoot: string, options?: CreateAgentHarnessOptions): Promise<AgentHarnessRuntime>;
|
|
11
|
+
export declare function createAgentHarness(workspace: WorkspaceBundle, options?: CreateAgentHarnessOptions): Promise<AgentHarnessRuntime>;
|
|
12
|
+
export declare function run(runtime: AgentHarnessRuntime, options: RunOptions): Promise<import("./contracts/types.js").RunResult>;
|
|
13
|
+
export declare function subscribe(runtime: AgentHarnessRuntime, listener: Parameters<AgentHarnessRuntime["subscribe"]>[0]): () => void;
|
|
14
|
+
export declare function listThreads(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listThreads"]>[0]): Promise<ThreadSummary[]>;
|
|
15
|
+
export declare function getThread(runtime: AgentHarnessRuntime, threadId: string): Promise<ThreadRecord | null>;
|
|
16
|
+
export declare function listApprovals(runtime: AgentHarnessRuntime, filter?: Parameters<AgentHarnessRuntime["listApprovals"]>[0]): Promise<ApprovalRecord[]>;
|
|
17
|
+
export declare function getApproval(runtime: AgentHarnessRuntime, approvalId: string): Promise<ApprovalRecord | null>;
|
|
18
|
+
export declare function stop(runtime: AgentHarnessRuntime): Promise<void>;
|
|
19
|
+
export declare function createToolMcpServer(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
|
20
|
+
export declare function serveToolsOverStdio(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
package/dist/api.js
CHANGED
|
@@ -1,54 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createToolMcpServerFromHarness, serveToolsOverStdioFromHarness } from "./mcp.js";
|
|
1
|
+
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
3
2
|
import { loadWorkspace } from "./workspace/compile.js";
|
|
4
|
-
|
|
5
|
-
function registerHarness(harness) {
|
|
6
|
-
const handle = { kind: "AgentHarnessHandle" };
|
|
7
|
-
Object.defineProperty(handle, HARNESS_INSTANCE, {
|
|
8
|
-
value: harness,
|
|
9
|
-
enumerable: false,
|
|
10
|
-
configurable: false,
|
|
11
|
-
writable: false,
|
|
12
|
-
});
|
|
13
|
-
return Object.freeze(handle);
|
|
14
|
-
}
|
|
15
|
-
function requireHarness(handle) {
|
|
16
|
-
if (handle instanceof AgentHarness) {
|
|
17
|
-
return handle;
|
|
18
|
-
}
|
|
19
|
-
if (typeof handle === "object" && handle !== null && "run" in handle && "subscribe" in handle && "close" in handle) {
|
|
20
|
-
return handle;
|
|
21
|
-
}
|
|
22
|
-
const harness = handle[HARNESS_INSTANCE];
|
|
23
|
-
if (!harness) {
|
|
24
|
-
throw new Error("Unknown or stopped AgentHarnessHandle");
|
|
25
|
-
}
|
|
26
|
-
return harness;
|
|
27
|
-
}
|
|
3
|
+
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
28
4
|
export async function createAgentHarness(input = process.cwd(), options = {}) {
|
|
29
5
|
const workspace = typeof input === "string"
|
|
30
6
|
? await loadWorkspace(input, options.load ?? {})
|
|
31
7
|
: input;
|
|
32
|
-
const harness = new
|
|
8
|
+
const harness = new AgentHarnessRuntime(workspace, options.adapter ?? {});
|
|
33
9
|
await harness.initialize();
|
|
34
|
-
return
|
|
10
|
+
return harness;
|
|
11
|
+
}
|
|
12
|
+
export async function run(runtime, options) {
|
|
13
|
+
return runtime.run(options);
|
|
14
|
+
}
|
|
15
|
+
export function subscribe(runtime, listener) {
|
|
16
|
+
return runtime.subscribe(listener);
|
|
17
|
+
}
|
|
18
|
+
export async function listThreads(runtime, filter) {
|
|
19
|
+
return runtime.listThreads(filter);
|
|
35
20
|
}
|
|
36
|
-
export async function
|
|
37
|
-
return
|
|
21
|
+
export async function getThread(runtime, threadId) {
|
|
22
|
+
return runtime.getThread(threadId);
|
|
38
23
|
}
|
|
39
|
-
export function
|
|
40
|
-
return
|
|
24
|
+
export async function listApprovals(runtime, filter) {
|
|
25
|
+
return runtime.listApprovals(filter);
|
|
41
26
|
}
|
|
42
|
-
export async function
|
|
43
|
-
return
|
|
27
|
+
export async function getApproval(runtime, approvalId) {
|
|
28
|
+
return runtime.getApproval(approvalId);
|
|
44
29
|
}
|
|
45
|
-
export async function stop(
|
|
46
|
-
|
|
47
|
-
return instance.close();
|
|
30
|
+
export async function stop(runtime) {
|
|
31
|
+
return runtime.stop();
|
|
48
32
|
}
|
|
49
|
-
export async function createToolMcpServer(
|
|
50
|
-
return
|
|
33
|
+
export async function createToolMcpServer(runtime, options) {
|
|
34
|
+
return runtime.createToolMcpServer(options);
|
|
51
35
|
}
|
|
52
|
-
export async function serveToolsOverStdio(
|
|
53
|
-
return
|
|
36
|
+
export async function serveToolsOverStdio(runtime, options) {
|
|
37
|
+
return runtime.serveToolsOverStdio(options);
|
|
54
38
|
}
|
|
@@ -25,5 +25,5 @@ spec:
|
|
|
25
25
|
# ======================
|
|
26
26
|
# agent-harness Features
|
|
27
27
|
# ======================
|
|
28
|
-
# This object is packaged and referenced through retrieval-oriented
|
|
29
|
-
# and
|
|
28
|
+
# This object is packaged and referenced through retrieval-oriented workspace tools such as the RAG index builder
|
|
29
|
+
# and query tool, not through `agent.modelRef`.
|
|
@@ -22,14 +22,48 @@ spec:
|
|
|
22
22
|
# Value options: relative workspace path like `./.agent`, or an absolute filesystem path.
|
|
23
23
|
runRoot: ./.agent
|
|
24
24
|
|
|
25
|
-
# agent-harness feature: optional host-router prompt override used when the
|
|
26
|
-
# top-level host agents such as
|
|
25
|
+
# agent-harness feature: optional host-router prompt override used when the runtime chooses between
|
|
26
|
+
# top-level host agents such as a main DeepAgent host and an optional low-latency side host.
|
|
27
27
|
# Use placeholders so the same prompt can survive host renames:
|
|
28
28
|
# - {{primaryAgentId}}
|
|
29
29
|
# - {{primaryDescription}}
|
|
30
30
|
# - {{secondaryAgentId}}
|
|
31
31
|
# - {{secondaryDescription}}
|
|
32
32
|
routing:
|
|
33
|
+
# agent-harness feature: DeepAgents-first default host selected when no explicit routing rule matches.
|
|
34
|
+
# Best practice is to point this at the main DeepAgent entry host and treat lighter agents as explicit opt-in.
|
|
35
|
+
defaultAgentId: orchestra
|
|
36
|
+
# agent-harness feature: optional model-driven host classification fallback.
|
|
37
|
+
# Keep this disabled unless you specifically need host-level model selection.
|
|
38
|
+
modelRouting: false
|
|
39
|
+
# agent-harness feature: ordered host-routing rules evaluated before model-driven classification.
|
|
40
|
+
# These rules only choose which host profile starts the run; DeepAgents still owns planning, tools, and long-running execution.
|
|
41
|
+
# The first matching rule wins. Use this when you want stable routing behavior in YAML instead of code.
|
|
42
|
+
#
|
|
43
|
+
# Supported match fields on each rule:
|
|
44
|
+
# - `equals`: exact request text match (string or list)
|
|
45
|
+
# - `startsWith`: request prefix match (string or list)
|
|
46
|
+
# - `contains`: substring match (string or list)
|
|
47
|
+
# - `regex`: regular-expression match (string or list)
|
|
48
|
+
# - `minLength` / `maxLength`: request text length bounds
|
|
49
|
+
# - `minLines` / `maxLines`: request line-count bounds
|
|
50
|
+
# - `hasThreadId`: require a new turn (`false`) or existing thread follow-up (`true`)
|
|
51
|
+
# - `caseSensitive`: default `false`
|
|
52
|
+
#
|
|
53
|
+
# Example:
|
|
54
|
+
# rules:
|
|
55
|
+
# - agentId: research-lite
|
|
56
|
+
# contains: ["latest", "today", "news", "最近", "最新", "新闻"]
|
|
57
|
+
# - agentId: orchestra
|
|
58
|
+
# regex:
|
|
59
|
+
# - "\\b(create|build|implement|fix|review|debug|inspect|analy[sz]e|download|clone)\\b"
|
|
60
|
+
rules:
|
|
61
|
+
- agentId: research-lite
|
|
62
|
+
contains: ["latest", "recent", "today", "current", "news", "最新", "最近", "今天", "当前", "新闻", "头条", "研究", "调研"]
|
|
63
|
+
- agentId: orchestra
|
|
64
|
+
regex:
|
|
65
|
+
- "\\b(create|build|implement|fix|debug|refactor|review|test|ship|release|deploy|code|bug|repo|repository|file|files|download|clone|inspect|analy[sz]e|explore)\\b"
|
|
66
|
+
- "(写代码|实现|修复|排查|调试|重构|评审|测试|发布|部署|仓库|代码|文件|下载|克隆|分析|检查|探索)"
|
|
33
67
|
systemPrompt: |-
|
|
34
68
|
You are a routing classifier for an agent harness. Reply with exactly one agent id:
|
|
35
69
|
{{primaryAgentId}} or {{secondaryAgentId}}.
|
|
@@ -47,7 +81,7 @@ spec:
|
|
|
47
81
|
When uncertain, prefer {{secondaryAgentId}}.
|
|
48
82
|
|
|
49
83
|
# agent-harness feature: optional workspace-level background maintenance policies.
|
|
50
|
-
# This is the
|
|
84
|
+
# This is the runtime-owned place to configure periodic housekeeping that should run without
|
|
51
85
|
# coupling cleanup to user-triggered checkpoint reads or writes.
|
|
52
86
|
#
|
|
53
87
|
# Current support:
|
|
@@ -183,7 +183,6 @@ export type CompiledAgentBinding = {
|
|
|
183
183
|
export type WorkspaceBundle = {
|
|
184
184
|
workspaceRoot: string;
|
|
185
185
|
resourceSources: string[];
|
|
186
|
-
builtinSources?: string[];
|
|
187
186
|
refs: Map<string, WorkspaceObject | ParsedAgentObject>;
|
|
188
187
|
models: Map<string, ParsedModelObject>;
|
|
189
188
|
embeddings: Map<string, ParsedEmbeddingModelObject>;
|
|
@@ -196,7 +195,6 @@ export type WorkspaceBundle = {
|
|
|
196
195
|
export type WorkspaceLoadOptions = {
|
|
197
196
|
overlayRoots?: string[];
|
|
198
197
|
resourceSources?: string[];
|
|
199
|
-
builtinSources?: string[];
|
|
200
198
|
};
|
|
201
199
|
export type ThreadSummary = {
|
|
202
200
|
agentId: string;
|
|
@@ -207,9 +205,11 @@ export type ThreadSummary = {
|
|
|
207
205
|
status: RunState;
|
|
208
206
|
};
|
|
209
207
|
export type SessionRecord = ThreadSummary;
|
|
208
|
+
export type KnownHarnessEventType = "run.created" | "run.state.changed" | "run.resumed" | "approval.requested" | "approval.resolved" | "artifact.created" | "output.delta" | "reasoning.delta" | "runtime.synthetic_fallback";
|
|
209
|
+
export type HarnessEventType = KnownHarnessEventType | (string & {});
|
|
210
210
|
export type HarnessEvent = {
|
|
211
211
|
eventId: string;
|
|
212
|
-
eventType:
|
|
212
|
+
eventType: HarnessEventType;
|
|
213
213
|
timestamp: string;
|
|
214
214
|
threadId: string;
|
|
215
215
|
runId: string;
|
|
@@ -217,6 +217,17 @@ export type HarnessEvent = {
|
|
|
217
217
|
source: "runtime" | "policy" | "surface" | "worker";
|
|
218
218
|
payload: Record<string, unknown>;
|
|
219
219
|
};
|
|
220
|
+
export type HarnessEventListener = (event: HarnessEvent) => void | Promise<void>;
|
|
221
|
+
export type HarnessEventProjection = {
|
|
222
|
+
name?: string;
|
|
223
|
+
shouldHandle?: (event: HarnessEvent) => boolean;
|
|
224
|
+
handleEvent: HarnessEventListener;
|
|
225
|
+
};
|
|
226
|
+
export type RuntimeEventSink = {
|
|
227
|
+
publish: (event: HarnessEvent) => void;
|
|
228
|
+
subscribe: (listener: HarnessEventListener) => () => void;
|
|
229
|
+
registerProjection: (projection: HarnessEventProjection) => () => void;
|
|
230
|
+
};
|
|
220
231
|
export type RunResult = {
|
|
221
232
|
threadId: string;
|
|
222
233
|
runId: string;
|
|
@@ -236,6 +247,7 @@ export type RunListeners = {
|
|
|
236
247
|
onToolResult?: (item: {
|
|
237
248
|
toolName: string;
|
|
238
249
|
output: unknown;
|
|
250
|
+
isError?: boolean;
|
|
239
251
|
}) => void | Promise<void>;
|
|
240
252
|
};
|
|
241
253
|
export type MessageContentPart = {
|
|
@@ -289,6 +301,7 @@ export type HarnessStreamItem = {
|
|
|
289
301
|
agentId: string;
|
|
290
302
|
toolName: string;
|
|
291
303
|
output: unknown;
|
|
304
|
+
isError?: boolean;
|
|
292
305
|
};
|
|
293
306
|
export type TranscriptMessage = {
|
|
294
307
|
role: "user" | "assistant";
|
|
@@ -438,8 +451,5 @@ export type PolicyEvaluator = {
|
|
|
438
451
|
};
|
|
439
452
|
export type EventSubscriber = {
|
|
440
453
|
kind: string;
|
|
441
|
-
onEvent:
|
|
442
|
-
};
|
|
443
|
-
export type AgentHarnessHandle = {
|
|
444
|
-
readonly kind: "AgentHarnessHandle";
|
|
454
|
+
onEvent: HarnessEventListener;
|
|
445
455
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { createAgentHarness, createToolMcpServer, getThread, run, serveToolsOverStdio, subscribe, stop } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
2
2
|
export type { ToolMcpServerOptions } from "./mcp.js";
|
|
3
3
|
export { tool } from "./tools.js";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createAgentHarness, createToolMcpServer, getThread, run, serveToolsOverStdio, subscribe, stop } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, getApproval, getThread, listApprovals, listThreads, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
2
2
|
export { tool } from "./tools.js";
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { CompiledTool, ParsedToolObject } from "./contracts/types.js";
|
|
3
3
|
export type ToolMcpServerOptions = {
|
|
4
4
|
agentId: string;
|
|
5
5
|
serverInfo?: {
|
|
@@ -8,5 +8,10 @@ export type ToolMcpServerOptions = {
|
|
|
8
8
|
};
|
|
9
9
|
includeToolNames?: string[];
|
|
10
10
|
};
|
|
11
|
-
export
|
|
12
|
-
|
|
11
|
+
export type ToolMcpServerTool = {
|
|
12
|
+
compiledTool: CompiledTool;
|
|
13
|
+
resolvedTool: unknown;
|
|
14
|
+
sourceTool?: ParsedToolObject;
|
|
15
|
+
};
|
|
16
|
+
export declare function createToolMcpServerFromTools(tools: ToolMcpServerTool[], options: ToolMcpServerOptions): Promise<McpServer>;
|
|
17
|
+
export declare function serveToolsOverStdioFromHarness(tools: ToolMcpServerTool[], options: ToolMcpServerOptions): Promise<McpServer>;
|