@botbotgo/agent-harness 0.0.69 → 0.0.70
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 +13 -2
- package/README.zh.md +12 -1
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/tool-modules.d.ts +3 -8
- package/dist/tool-modules.js +3 -115
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ The runtime provides:
|
|
|
53
53
|
- `createAgentHarness(workspaceRoot)`, `run(...)`, `resolveApproval(...)`, `subscribe(...)`, inspection methods, and `stop(...)`
|
|
54
54
|
- YAML-defined workspace assembly for routing, models, tools, stores, backends, MCP, recovery, and maintenance
|
|
55
55
|
- backend-adapted execution with current LangChain v1 and DeepAgents adapters
|
|
56
|
-
- local `resources/tools/` and `resources/skills/` discovery
|
|
56
|
+
- local `resources/tools/` `tool({...})` modules and `resources/skills/` discovery
|
|
57
57
|
- persisted threads, runs, approvals, events, queue state, and recovery metadata
|
|
58
58
|
|
|
59
59
|
The repository-owned default config layer is intentionally full-shaped. The shipped YAML keeps explicit defaults for the important runtime and agent knobs so teams can start from concrete config instead of reverse-engineering adapter behavior from source.
|
|
@@ -157,7 +157,7 @@ If you want the shortest possible mental model:
|
|
|
157
157
|
- Small public runtime contract
|
|
158
158
|
- YAML-defined host routing and runtime policy
|
|
159
159
|
- LangChain v1 and DeepAgents backend adaptation
|
|
160
|
-
- Auto-discovered local tools and SKILL packages
|
|
160
|
+
- Auto-discovered local `tool({...})` tools and SKILL packages
|
|
161
161
|
- provider-native tools, MCP tools, and workspace-local tool modules
|
|
162
162
|
- persisted threads, runs, approvals, lifecycle events, and queued runs
|
|
163
163
|
- runtime-managed recovery and checkpoint maintenance
|
|
@@ -345,6 +345,9 @@ Core workspace files:
|
|
|
345
345
|
- `resources/tools/`
|
|
346
346
|
- `resources/skills/`
|
|
347
347
|
|
|
348
|
+
Workspace-local tool modules in `resources/tools/` should be exported with `tool({...})`.
|
|
349
|
+
Any other local module shape is not supported, and unsupported shapes are rejected at load time.
|
|
350
|
+
|
|
348
351
|
There are three main configuration layers:
|
|
349
352
|
|
|
350
353
|
- runtime policy in `config/workspace.yaml`
|
|
@@ -379,12 +382,18 @@ Important fields:
|
|
|
379
382
|
- `routing.systemPrompt`
|
|
380
383
|
- `routing.modelRouting`
|
|
381
384
|
- `maintenance.checkpoints`
|
|
385
|
+
- `maintenance.records`
|
|
382
386
|
- `recovery.enabled`
|
|
383
387
|
- `recovery.resumeResumingRunsOnStartup`
|
|
384
388
|
- `recovery.maxRecoveryAttempts`
|
|
385
389
|
|
|
386
390
|
`recovery.resumeResumingRunsOnStartup` keeps checkpoint resume a runtime-owned lifecycle behavior instead of exposing checkpoint orchestration as public API.
|
|
387
391
|
|
|
392
|
+
`maintenance.checkpoints` and `maintenance.records` are separate retention layers:
|
|
393
|
+
|
|
394
|
+
- `maintenance.checkpoints` trims backend checkpoint state used for resume/recovery
|
|
395
|
+
- `maintenance.records` trims harness-owned terminal thread/run records stored in `runtime.sqlite`
|
|
396
|
+
|
|
388
397
|
Example:
|
|
389
398
|
|
|
390
399
|
```yaml
|
|
@@ -402,6 +411,8 @@ spec:
|
|
|
402
411
|
maintenance:
|
|
403
412
|
checkpoints:
|
|
404
413
|
enabled: true
|
|
414
|
+
records:
|
|
415
|
+
enabled: false
|
|
405
416
|
recovery:
|
|
406
417
|
enabled: true
|
|
407
418
|
resumeResumingRunsOnStartup: true
|
package/README.zh.md
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
- `createAgentHarness(workspaceRoot)`、`run(...)`、`resolveApproval(...)`、`subscribe(...)`、各类查询方法,以及 `stop(...)`
|
|
54
54
|
- 以 YAML 描述的工作区装配:路由、模型、工具、存储、后端、MCP、恢复与维护等
|
|
55
55
|
- 通过适配器对接当前的 LangChain v1 与 DeepAgents 执行
|
|
56
|
-
- 本地 `resources/tools/`
|
|
56
|
+
- 本地 `resources/tools/` 中 `tool({...})` 工具模块与 `resources/skills/` 的发现
|
|
57
57
|
- 持久化的线程、运行、审批、事件、队列状态与恢复元数据
|
|
58
58
|
|
|
59
59
|
仓库自带的默认配置刻意做成「形状完整」。随仓库提供的 YAML 对重要的运行时与 agent 开关给出显式默认值,便于从具体配置起步,而不必从源码反推适配器行为。
|
|
@@ -343,6 +343,9 @@ await stop(runtime);
|
|
|
343
343
|
- `resources/tools/`
|
|
344
344
|
- `resources/skills/`
|
|
345
345
|
|
|
346
|
+
`resources/tools/` 下的工作区本地工具模块应统一用 `tool({...})` 导出。
|
|
347
|
+
不支持历史/兼容写法,任何不带该导出形式的工具模块都会在工作区加载时被拒绝。
|
|
348
|
+
|
|
346
349
|
主要有三层配置:
|
|
347
350
|
|
|
348
351
|
- `config/workspace.yaml` 中的运行时策略
|
|
@@ -377,12 +380,18 @@ await stop(runtime);
|
|
|
377
380
|
- `routing.systemPrompt`
|
|
378
381
|
- `routing.modelRouting`
|
|
379
382
|
- `maintenance.checkpoints`
|
|
383
|
+
- `maintenance.records`
|
|
380
384
|
- `recovery.enabled`
|
|
381
385
|
- `recovery.resumeResumingRunsOnStartup`
|
|
382
386
|
- `recovery.maxRecoveryAttempts`
|
|
383
387
|
|
|
384
388
|
`recovery.resumeResumingRunsOnStartup` 将 checkpoint 恢复保持为运行时拥有的生命周期行为,而不是把 checkpoint 编排暴露为主 API。
|
|
385
389
|
|
|
390
|
+
`maintenance.checkpoints` 与 `maintenance.records` 是两层独立的保留策略:
|
|
391
|
+
|
|
392
|
+
- `maintenance.checkpoints` 清理后端用于 resume/recovery 的 checkpoint 状态
|
|
393
|
+
- `maintenance.records` 清理 harness 自己保存在 `runtime.sqlite` 中、已结束的 thread/run 记录
|
|
394
|
+
|
|
386
395
|
示例:
|
|
387
396
|
|
|
388
397
|
```yaml
|
|
@@ -400,6 +409,8 @@ spec:
|
|
|
400
409
|
maintenance:
|
|
401
410
|
checkpoints:
|
|
402
411
|
enabled: true
|
|
412
|
+
records:
|
|
413
|
+
enabled: false
|
|
403
414
|
recovery:
|
|
404
415
|
enabled: true
|
|
405
416
|
resumeResumingRunsOnStartup: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.69";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.69";
|
package/dist/tool-modules.d.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
+
import { normalizeToolSchema } from "./tools.js";
|
|
1
2
|
type ImportedToolModule = Record<string, unknown>;
|
|
2
|
-
type SchemaLike = {
|
|
3
|
-
parse: (input: unknown) => unknown;
|
|
4
|
-
description?: string;
|
|
5
|
-
shape?: Record<string, unknown>;
|
|
6
|
-
};
|
|
7
3
|
export type LoadedToolModule = {
|
|
8
4
|
implementationName: string;
|
|
9
5
|
invoke: (input: unknown, context?: Record<string, unknown>) => Promise<unknown> | unknown;
|
|
10
|
-
schema:
|
|
6
|
+
schema: ReturnType<typeof normalizeToolSchema>;
|
|
11
7
|
description: string;
|
|
12
8
|
retryable?: boolean;
|
|
13
9
|
};
|
|
14
10
|
export declare function isSupportedToolModulePath(filePath: string): boolean;
|
|
15
|
-
export declare function
|
|
16
|
-
export declare function discoverToolModuleDefinitions(sourceText: string, imported: ImportedToolModule): LoadedToolModule[];
|
|
11
|
+
export declare function discoverToolModuleDefinitions(_sourceText: string, imported: ImportedToolModule): LoadedToolModule[];
|
|
17
12
|
export declare function loadToolModuleDefinition(imported: ImportedToolModule, implementationName: string): LoadedToolModule;
|
|
18
13
|
export {};
|
package/dist/tool-modules.js
CHANGED
|
@@ -1,65 +1,9 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { z } from "zod";
|
|
3
2
|
import { TOOL_DEFINITION_MARKER, normalizeToolSchema } from "./tools.js";
|
|
4
3
|
const TOOL_MODULE_EXTENSIONS = new Set([".mjs", ".js", ".cjs"]);
|
|
5
|
-
const ANNOTATED_TOOL_EXPORT_PATTERN = /(?:\/\*\*?[\s\S]*?@tool[\s\S]*?\*\/\s*|\/\/[^\n]*@tool[^\n]*\n\s*)export\s+(?:async\s+)?(?:function\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(|const\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?:async\s*)?(?:function\b|\())/g;
|
|
6
|
-
function asRecord(value) {
|
|
7
|
-
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
8
|
-
? value
|
|
9
|
-
: undefined;
|
|
10
|
-
}
|
|
11
|
-
function isSchemaLike(value) {
|
|
12
|
-
return typeof value === "object" && value !== null && typeof value.parse === "function";
|
|
13
|
-
}
|
|
14
4
|
function isToolDefinitionObject(value) {
|
|
15
5
|
return typeof value === "object" && value !== null && value[TOOL_DEFINITION_MARKER] === true;
|
|
16
6
|
}
|
|
17
|
-
function buildSchemaFromShape(shape, description) {
|
|
18
|
-
const record = asRecord(shape);
|
|
19
|
-
if (!record) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
const schema = z.object(record);
|
|
23
|
-
return description ? schema.describe(description) : schema;
|
|
24
|
-
}
|
|
25
|
-
function readToolDescription(imported, implementationName, schema) {
|
|
26
|
-
const explicit = typeof imported[`${implementationName}Description`] === "string"
|
|
27
|
-
? String(imported[`${implementationName}Description`])
|
|
28
|
-
: typeof imported.description === "string"
|
|
29
|
-
? String(imported.description)
|
|
30
|
-
: undefined;
|
|
31
|
-
return explicit?.trim() || schema.description?.trim() || `Auto-discovered tool ${implementationName}`;
|
|
32
|
-
}
|
|
33
|
-
function resolveToolSchema(imported, implementationName, allowGenericExports) {
|
|
34
|
-
const namedSchema = imported[`${implementationName}Schema`];
|
|
35
|
-
if (isSchemaLike(namedSchema)) {
|
|
36
|
-
return namedSchema;
|
|
37
|
-
}
|
|
38
|
-
const namedShape = imported[`${implementationName}SchemaShape`];
|
|
39
|
-
const namedDescription = typeof imported[`${implementationName}Description`] === "string"
|
|
40
|
-
? String(imported[`${implementationName}Description`])
|
|
41
|
-
: undefined;
|
|
42
|
-
const schemaFromNamedShape = buildSchemaFromShape(namedShape, namedDescription);
|
|
43
|
-
if (schemaFromNamedShape) {
|
|
44
|
-
return schemaFromNamedShape;
|
|
45
|
-
}
|
|
46
|
-
if (!allowGenericExports) {
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
const genericSchema = imported.schema;
|
|
50
|
-
if (isSchemaLike(genericSchema)) {
|
|
51
|
-
return genericSchema;
|
|
52
|
-
}
|
|
53
|
-
const genericShape = imported.schemaShape ?? imported.schema;
|
|
54
|
-
const genericDescription = typeof imported.description === "string" ? String(imported.description) : undefined;
|
|
55
|
-
return buildSchemaFromShape(genericShape, genericDescription);
|
|
56
|
-
}
|
|
57
|
-
function discoverExportedFunctionNames(imported) {
|
|
58
|
-
return Object.entries(imported)
|
|
59
|
-
.filter(([name, value]) => name !== "default" && typeof value === "function")
|
|
60
|
-
.map(([name]) => name)
|
|
61
|
-
.sort();
|
|
62
|
-
}
|
|
63
7
|
function discoverExportedToolObjectNames(imported) {
|
|
64
8
|
return Object.entries(imported)
|
|
65
9
|
.filter(([name, value]) => name !== "default" && isToolDefinitionObject(value))
|
|
@@ -82,46 +26,10 @@ function loadToolObjectDefinition(imported, exportName) {
|
|
|
82
26
|
export function isSupportedToolModulePath(filePath) {
|
|
83
27
|
return TOOL_MODULE_EXTENSIONS.has(path.extname(filePath));
|
|
84
28
|
}
|
|
85
|
-
export function
|
|
86
|
-
|
|
87
|
-
return Array.from(matches, (match) => match[1] ?? match[2]).filter((name) => Boolean(name));
|
|
88
|
-
}
|
|
89
|
-
export function discoverToolModuleDefinitions(sourceText, imported) {
|
|
90
|
-
const objectDefinitions = discoverExportedToolObjectNames(imported)
|
|
29
|
+
export function discoverToolModuleDefinitions(_sourceText, imported) {
|
|
30
|
+
return discoverExportedToolObjectNames(imported)
|
|
91
31
|
.map((exportName) => loadToolObjectDefinition(imported, exportName))
|
|
92
32
|
.filter((definition) => Boolean(definition));
|
|
93
|
-
if (objectDefinitions.length > 0) {
|
|
94
|
-
return objectDefinitions;
|
|
95
|
-
}
|
|
96
|
-
const annotatedNames = new Set(discoverAnnotatedFunctionNames(sourceText));
|
|
97
|
-
const functionNames = discoverExportedFunctionNames(imported);
|
|
98
|
-
const allowGenericExports = functionNames.length === 1;
|
|
99
|
-
const discovered = [];
|
|
100
|
-
for (const implementationName of functionNames) {
|
|
101
|
-
const invoke = imported[implementationName];
|
|
102
|
-
if (typeof invoke !== "function") {
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
const schema = resolveToolSchema(imported, implementationName, allowGenericExports);
|
|
106
|
-
if (!schema && !annotatedNames.has(implementationName)) {
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
if (!schema) {
|
|
110
|
-
throw new Error(`Tool module must export ${implementationName}Schema, ${implementationName}SchemaShape, or generic schema/schemaShape metadata.`);
|
|
111
|
-
}
|
|
112
|
-
discovered.push({
|
|
113
|
-
implementationName,
|
|
114
|
-
invoke: invoke,
|
|
115
|
-
schema,
|
|
116
|
-
description: readToolDescription(imported, implementationName, schema),
|
|
117
|
-
retryable: typeof imported[`${implementationName}Retryable`] === "boolean"
|
|
118
|
-
? imported[`${implementationName}Retryable`] === true
|
|
119
|
-
: typeof imported.retryable === "boolean"
|
|
120
|
-
? imported.retryable === true
|
|
121
|
-
: undefined,
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
return discovered;
|
|
125
33
|
}
|
|
126
34
|
export function loadToolModuleDefinition(imported, implementationName) {
|
|
127
35
|
for (const exportName of discoverExportedToolObjectNames(imported)) {
|
|
@@ -130,25 +38,5 @@ export function loadToolModuleDefinition(imported, implementationName) {
|
|
|
130
38
|
return loaded;
|
|
131
39
|
}
|
|
132
40
|
}
|
|
133
|
-
|
|
134
|
-
const allowGenericExports = functionNames.length === 1;
|
|
135
|
-
const invoke = imported[implementationName];
|
|
136
|
-
if (typeof invoke !== "function") {
|
|
137
|
-
throw new Error(`Tool module must export function ${implementationName}.`);
|
|
138
|
-
}
|
|
139
|
-
const schema = resolveToolSchema(imported, implementationName, allowGenericExports);
|
|
140
|
-
if (!schema) {
|
|
141
|
-
throw new Error(`Tool module must export ${implementationName}Schema, ${implementationName}SchemaShape, or generic schema/schemaShape metadata.`);
|
|
142
|
-
}
|
|
143
|
-
return {
|
|
144
|
-
implementationName,
|
|
145
|
-
invoke: invoke,
|
|
146
|
-
schema,
|
|
147
|
-
description: readToolDescription(imported, implementationName, schema),
|
|
148
|
-
retryable: typeof imported[`${implementationName}Retryable`] === "boolean"
|
|
149
|
-
? imported[`${implementationName}Retryable`] === true
|
|
150
|
-
: typeof imported.retryable === "boolean"
|
|
151
|
-
? imported.retryable === true
|
|
152
|
-
: undefined,
|
|
153
|
-
};
|
|
41
|
+
throw new Error(`Tool module must export a tool({...}) definition named ${implementationName}.`);
|
|
154
42
|
}
|