@botbotgo/agent-harness 0.0.70 → 0.0.72
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 +20 -0
- package/README.zh.md +20 -0
- package/dist/api.d.ts +7 -0
- package/dist/api.js +4 -0
- package/dist/contracts/types.d.ts +6 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/workspace/bootstrap.d.ts +29 -0
- package/dist/workspace/bootstrap.js +131 -0
- package/dist/workspace/object-loader.d.ts +12 -0
- package/dist/workspace/object-loader.js +12 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,6 +184,26 @@ const runtime: AgentHarnessRuntime = await createAgentHarness("/absolute/path/to
|
|
|
184
184
|
|
|
185
185
|
`createAgentHarness(...)` loads the workspace, resolves `resources/`, initializes persistence under `runRoot`, and starts runtime maintenance.
|
|
186
186
|
|
|
187
|
+
`createAgentHarness(..., { load })` accepts workspace loading controls.
|
|
188
|
+
|
|
189
|
+
Merge order is deterministic:
|
|
190
|
+
|
|
191
|
+
- framework defaults
|
|
192
|
+
- each `overlayRoots` entry in order
|
|
193
|
+
- workspace root
|
|
194
|
+
|
|
195
|
+
Later values always override earlier values. Arrays are replaced, while plain objects are deep-merged.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { createAgentHarness } from "@botbotgo/agent-harness";
|
|
199
|
+
|
|
200
|
+
const runtime = await createAgentHarness("/path/to/workspace", {
|
|
201
|
+
load: {
|
|
202
|
+
overlayRoots: ["/path/to/framework-defaults", "/path/to/product-overrides"],
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
187
207
|
### Run A Request
|
|
188
208
|
|
|
189
209
|
```ts
|
package/README.zh.md
CHANGED
|
@@ -183,6 +183,26 @@ const runtime: AgentHarnessRuntime = await createAgentHarness("/absolute/path/to
|
|
|
183
183
|
|
|
184
184
|
`createAgentHarness(...)` 会加载工作区、解析 `resources/`、在 `runRoot` 下初始化持久化,并启动运行时维护任务。
|
|
185
185
|
|
|
186
|
+
`createAgentHarness(..., { load })` 支持工作区加载控制。
|
|
187
|
+
|
|
188
|
+
合并顺序是确定性的:
|
|
189
|
+
|
|
190
|
+
- 框架默认配置
|
|
191
|
+
- 每个 `overlayRoots` 条目(按数组顺序)
|
|
192
|
+
- workspace 根目录
|
|
193
|
+
|
|
194
|
+
后者会覆盖前者;数组会被直接替换,普通对象会执行深度合并。
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import { createAgentHarness } from "@botbotgo/agent-harness";
|
|
198
|
+
|
|
199
|
+
const runtime = await createAgentHarness("/path/to/workspace", {
|
|
200
|
+
load: {
|
|
201
|
+
overlayRoots: ["/path/to/framework-defaults", "/path/to/product-overrides"],
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
186
206
|
### 发起一次运行
|
|
187
207
|
|
|
188
208
|
```ts
|
package/dist/api.d.ts
CHANGED
|
@@ -3,8 +3,14 @@ import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
|
3
3
|
import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/inventory.js";
|
|
4
4
|
import type { RequirementAssessmentOptions } from "./runtime/skill-requirements.js";
|
|
5
5
|
import type { ToolMcpServerOptions } from "./mcp.js";
|
|
6
|
+
import type { PrepareWorkspaceMetadata, PrepareWorkspaceOptions } from "./workspace/bootstrap.js";
|
|
6
7
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
8
|
+
export type { PrepareWorkspaceMetadata, PrepareWorkspaceOptions };
|
|
7
9
|
type CreateAgentHarnessOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Workspace loading behavior.
|
|
12
|
+
* overlayRoots are merged after framework defaults and before workspaceRoot.
|
|
13
|
+
*/
|
|
8
14
|
load?: WorkspaceLoadOptions;
|
|
9
15
|
adapter?: RuntimeAdapterOptions;
|
|
10
16
|
};
|
|
@@ -28,3 +34,4 @@ export declare function resolveApproval(runtime: AgentHarnessRuntime, options: R
|
|
|
28
34
|
export declare function stop(runtime: AgentHarnessRuntime): Promise<void>;
|
|
29
35
|
export declare function createToolMcpServer(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
|
30
36
|
export declare function serveToolsOverStdio(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
|
|
37
|
+
export declare function prepareWorkspace(workspaceRoot: string, options?: PrepareWorkspaceOptions): Promise<PrepareWorkspaceMetadata>;
|
package/dist/api.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
2
2
|
import { loadWorkspace } from "./workspace/compile.js";
|
|
3
|
+
import { prepareWorkspace as prepareWorkspaceFromBootstrap } from "./workspace/bootstrap.js";
|
|
3
4
|
export { AgentHarnessRuntime } from "./runtime/harness.js";
|
|
4
5
|
export async function createAgentHarness(workspaceRoot = process.cwd(), options = {}) {
|
|
5
6
|
const workspace = await loadWorkspace(workspaceRoot, options.load ?? {});
|
|
@@ -52,3 +53,6 @@ export async function createToolMcpServer(runtime, options) {
|
|
|
52
53
|
export async function serveToolsOverStdio(runtime, options) {
|
|
53
54
|
return runtime.serveToolsOverStdio(options);
|
|
54
55
|
}
|
|
56
|
+
export function prepareWorkspace(workspaceRoot, options) {
|
|
57
|
+
return prepareWorkspaceFromBootstrap(workspaceRoot, options);
|
|
58
|
+
}
|
|
@@ -220,6 +220,12 @@ export type WorkspaceBundle = {
|
|
|
220
220
|
bindings: Map<string, CompiledAgentBinding>;
|
|
221
221
|
};
|
|
222
222
|
export type WorkspaceLoadOptions = {
|
|
223
|
+
/**
|
|
224
|
+
* Additional workspace roots to load before the runtime workspace root.
|
|
225
|
+
* Merge order is deterministic:
|
|
226
|
+
* framework defaults -> each overlayRoot (in order) -> workspaceRoot.
|
|
227
|
+
* Later values always override earlier values.
|
|
228
|
+
*/
|
|
223
229
|
overlayRoots?: string[];
|
|
224
230
|
resourceSources?: string[];
|
|
225
231
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, createAgentHarness, prepareWorkspace, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, 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 { AgentHarnessRuntime, createAgentHarness, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
1
|
+
export { AgentHarnessRuntime, createAgentHarness, prepareWorkspace, createToolMcpServer, deleteThread, describeInventory, getApproval, getRun, getThread, listAgentSkills, listApprovals, listRuns, listThreads, resolveApproval, run, serveToolsOverStdio, subscribe, stop, } from "./api.js";
|
|
2
2
|
export { tool } from "./tools.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.71";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.71";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type WorkspaceBootstrapOptions = {
|
|
2
|
+
sourceConfigRoot?: string;
|
|
3
|
+
sourceResourcesRoot?: string;
|
|
4
|
+
removePatterns?: string[];
|
|
5
|
+
postCopyRemoveFiles?: string[];
|
|
6
|
+
lock?: {
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
path?: string;
|
|
9
|
+
maxAttempts?: number;
|
|
10
|
+
retryDelayMs?: number;
|
|
11
|
+
};
|
|
12
|
+
operations?: {
|
|
13
|
+
copy?: (source: string, destination: string) => Promise<void>;
|
|
14
|
+
remove?: (target: string) => Promise<void>;
|
|
15
|
+
mkdir?: (target: string) => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export type PrepareWorkspaceOptions = WorkspaceBootstrapOptions;
|
|
19
|
+
export type PrepareWorkspaceMetadata = {
|
|
20
|
+
workspaceRoot: string;
|
|
21
|
+
configRoot: string;
|
|
22
|
+
resourcesRoot: string;
|
|
23
|
+
sourceConfigRoot: string;
|
|
24
|
+
sourceResourcesRoot: string;
|
|
25
|
+
removed: string[];
|
|
26
|
+
copied: string[];
|
|
27
|
+
};
|
|
28
|
+
export declare function prepareWorkspace(workspaceRoot: string, options?: PrepareWorkspaceOptions): Promise<PrepareWorkspaceMetadata>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { cp, mkdir, rm, stat } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const DEFAULT_REMOVE_PATTERNS = [
|
|
5
|
+
"direct.yaml",
|
|
6
|
+
"orchestra.yaml",
|
|
7
|
+
"runtime.yaml",
|
|
8
|
+
"agent.yaml",
|
|
9
|
+
"memory.yaml",
|
|
10
|
+
"model.yaml",
|
|
11
|
+
"tool.yaml",
|
|
12
|
+
"toolkit.yaml",
|
|
13
|
+
"agents",
|
|
14
|
+
"config",
|
|
15
|
+
"resources",
|
|
16
|
+
];
|
|
17
|
+
const DEFAULT_POST_COPY_REMOVE_FILES = ["agent.yaml", "memory.yaml", "model.yaml", "tool.yaml", "toolkit.yaml"];
|
|
18
|
+
function resolveFrameworkRoot() {
|
|
19
|
+
const base = path.dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const resolved = path.resolve(base, "..", "..");
|
|
21
|
+
return resolved;
|
|
22
|
+
}
|
|
23
|
+
function resolveFrameworkConfigRoot() {
|
|
24
|
+
return path.join(resolveFrameworkRoot(), "config");
|
|
25
|
+
}
|
|
26
|
+
function resolveFrameworkResourcesRoot() {
|
|
27
|
+
return path.join(resolveFrameworkRoot(), "resources");
|
|
28
|
+
}
|
|
29
|
+
function sleep(ms) {
|
|
30
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
}
|
|
32
|
+
function isErrnoCode(error, code) {
|
|
33
|
+
return error?.code === code;
|
|
34
|
+
}
|
|
35
|
+
async function exists(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
await stat(filePath);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (isErrnoCode(error, "ENOENT")) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function acquireWorkspaceBootstrapLock(lockPath, options) {
|
|
48
|
+
let attempt = 0;
|
|
49
|
+
// eslint-disable-next-line no-constant-condition
|
|
50
|
+
while (true) {
|
|
51
|
+
try {
|
|
52
|
+
await mkdir(lockPath);
|
|
53
|
+
return async () => {
|
|
54
|
+
await rm(lockPath, { recursive: true, force: true });
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
attempt += 1;
|
|
59
|
+
if (!isErrnoCode(error, "EEXIST") || attempt >= options.maxAttempts) {
|
|
60
|
+
throw new Error(`Failed to prepare workspace at ${lockPath}; lock was not released after ${attempt} attempts.`);
|
|
61
|
+
}
|
|
62
|
+
await sleep(options.retryDelayMs);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function prepareWorkspace(workspaceRoot, options = {}) {
|
|
67
|
+
const resolvedWorkspaceRoot = path.resolve(workspaceRoot);
|
|
68
|
+
const removePatterns = options.removePatterns && options.removePatterns.length > 0
|
|
69
|
+
? [...new Set(options.removePatterns.map((entry) => entry.trim()).filter(Boolean))]
|
|
70
|
+
: [...DEFAULT_REMOVE_PATTERNS];
|
|
71
|
+
const postCopyRemoveFiles = options.postCopyRemoveFiles && options.postCopyRemoveFiles.length > 0
|
|
72
|
+
? [...new Set(options.postCopyRemoveFiles.map((entry) => entry.trim()).filter(Boolean))]
|
|
73
|
+
: [...DEFAULT_POST_COPY_REMOVE_FILES];
|
|
74
|
+
const sourceConfigRoot = path.resolve(options.sourceConfigRoot ?? resolveFrameworkConfigRoot());
|
|
75
|
+
const sourceResourcesRoot = path.resolve(options.sourceResourcesRoot ?? resolveFrameworkResourcesRoot());
|
|
76
|
+
const configRoot = path.join(resolvedWorkspaceRoot, "config");
|
|
77
|
+
const resourcesRoot = path.join(resolvedWorkspaceRoot, "resources");
|
|
78
|
+
const lockOptions = options.lock?.enabled === false
|
|
79
|
+
? null
|
|
80
|
+
: {
|
|
81
|
+
path: options.lock?.path ?? path.join(resolvedWorkspaceRoot, ".agent-harness-bootstrap.lock"),
|
|
82
|
+
maxAttempts: options.lock?.maxAttempts ?? 40,
|
|
83
|
+
retryDelayMs: options.lock?.retryDelayMs ?? 25,
|
|
84
|
+
};
|
|
85
|
+
const operations = {
|
|
86
|
+
copy: options.operations?.copy ?? ((source, destination) => cp(source, destination, { recursive: true, force: true })),
|
|
87
|
+
remove: options.operations?.remove ?? ((target) => rm(target, { recursive: true, force: true })),
|
|
88
|
+
mkdir: options.operations?.mkdir ?? ((target) => mkdir(target, { recursive: true })),
|
|
89
|
+
};
|
|
90
|
+
await operations.mkdir(resolvedWorkspaceRoot);
|
|
91
|
+
const lock = await (lockOptions
|
|
92
|
+
? acquireWorkspaceBootstrapLock(lockOptions.path, lockOptions)
|
|
93
|
+
: async () => undefined);
|
|
94
|
+
const removed = [];
|
|
95
|
+
const copied = [];
|
|
96
|
+
try {
|
|
97
|
+
for (const pattern of removePatterns) {
|
|
98
|
+
const target = path.join(resolvedWorkspaceRoot, pattern);
|
|
99
|
+
removed.push(target);
|
|
100
|
+
await operations.remove(target);
|
|
101
|
+
}
|
|
102
|
+
await operations.mkdir(configRoot);
|
|
103
|
+
await operations.mkdir(path.join(configRoot, "agents"));
|
|
104
|
+
await operations.mkdir(resourcesRoot);
|
|
105
|
+
if (await exists(sourceConfigRoot)) {
|
|
106
|
+
await operations.copy(sourceConfigRoot, configRoot);
|
|
107
|
+
copied.push(configRoot);
|
|
108
|
+
}
|
|
109
|
+
if (await exists(sourceResourcesRoot)) {
|
|
110
|
+
await operations.copy(sourceResourcesRoot, resourcesRoot);
|
|
111
|
+
copied.push(resourcesRoot);
|
|
112
|
+
}
|
|
113
|
+
for (const file of postCopyRemoveFiles) {
|
|
114
|
+
await operations.remove(path.join(configRoot, file));
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
workspaceRoot: resolvedWorkspaceRoot,
|
|
118
|
+
configRoot,
|
|
119
|
+
resourcesRoot,
|
|
120
|
+
sourceConfigRoot,
|
|
121
|
+
sourceResourcesRoot,
|
|
122
|
+
removed,
|
|
123
|
+
copied,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
if (lockOptions) {
|
|
128
|
+
await lock();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -17,5 +17,17 @@ export declare function readToolModuleItems(root: string): Promise<Array<{
|
|
|
17
17
|
item: Record<string, unknown>;
|
|
18
18
|
sourcePath: string;
|
|
19
19
|
}>>;
|
|
20
|
+
/**
|
|
21
|
+
* Load and merge workspace objects in deterministic order:
|
|
22
|
+
* 1) framework workspace defaults
|
|
23
|
+
* 2) overlay roots in order
|
|
24
|
+
* 3) workspaceRoot
|
|
25
|
+
*
|
|
26
|
+
* Merge semantics:
|
|
27
|
+
* - later sources override earlier sources
|
|
28
|
+
* - arrays are replaced, not concatenated
|
|
29
|
+
* - plain objects are merged recursively
|
|
30
|
+
* - scalars and non-plain objects are replaced
|
|
31
|
+
*/
|
|
20
32
|
export declare function loadWorkspaceObjects(workspaceRoot: string, options?: WorkspaceLoadOptions): Promise<WorkspaceObjects>;
|
|
21
33
|
export {};
|
|
@@ -624,6 +624,18 @@ export async function readToolModuleItems(root) {
|
|
|
624
624
|
function inferExecutionMode(item, current) {
|
|
625
625
|
return resolveExecutionBackend(item, current);
|
|
626
626
|
}
|
|
627
|
+
/**
|
|
628
|
+
* Load and merge workspace objects in deterministic order:
|
|
629
|
+
* 1) framework workspace defaults
|
|
630
|
+
* 2) overlay roots in order
|
|
631
|
+
* 3) workspaceRoot
|
|
632
|
+
*
|
|
633
|
+
* Merge semantics:
|
|
634
|
+
* - later sources override earlier sources
|
|
635
|
+
* - arrays are replaced, not concatenated
|
|
636
|
+
* - plain objects are merged recursively
|
|
637
|
+
* - scalars and non-plain objects are replaced
|
|
638
|
+
*/
|
|
627
639
|
export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
|
|
628
640
|
const refs = new Map();
|
|
629
641
|
const mergedAgents = new Map();
|