@botbotgo/agent-harness 0.0.267 → 0.0.268
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 +8 -0
- package/README.zh.md +7 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/workspace/compile.js +6 -5
- package/dist/workspace/object-loader.d.ts +4 -1
- package/dist/workspace/object-loader.js +13 -5
- package/dist/workspace/support/workspace-ref-utils.d.ts +5 -0
- package/dist/workspace/support/workspace-ref-utils.js +9 -0
- package/dist/workspace/tool-hydration.d.ts +2 -1
- package/dist/workspace/tool-hydration.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -752,6 +752,7 @@ Important fields:
|
|
|
752
752
|
- `concurrency.maxConcurrentRuns`
|
|
753
753
|
- `routing.defaultAgentId`
|
|
754
754
|
- `routing.rules`
|
|
755
|
+
- `toolModuleDiscovery.scope`
|
|
755
756
|
- `maintenance.checkpoints`
|
|
756
757
|
- `maintenance.records`
|
|
757
758
|
- `recovery.enabled`
|
|
@@ -765,6 +766,11 @@ Important fields:
|
|
|
765
766
|
- `maintenance.checkpoints` trims backend checkpoint state used for resume/recovery
|
|
766
767
|
- `maintenance.records` trims harness-owned terminal session/request records stored in `runtime.sqlite`
|
|
767
768
|
|
|
769
|
+
`toolModuleDiscovery.scope` controls how local `resources/tools/`-style module discovery walks tool directories:
|
|
770
|
+
|
|
771
|
+
- `recursive` is the default and keeps scanning nested folders
|
|
772
|
+
- `top-level` limits module discovery to files directly under each tool root while leaving YAML catalogs recursive
|
|
773
|
+
|
|
768
774
|
When libSQL reports an error against harness runtime persistence, the message is prefixed with the absolute path to `runtime.sqlite`. For constraint-class failures (or whenever you set `AGENT_HARNESS_RUNTIME_SQLITE_DEBUG=1`), the message also includes a truncated copy of the failing SQL so you can tell harness persistence apart from other SQLite databases in the same process.
|
|
769
775
|
|
|
770
776
|
Example:
|
|
@@ -776,6 +782,8 @@ metadata:
|
|
|
776
782
|
name: default
|
|
777
783
|
spec:
|
|
778
784
|
runRoot: ./.agent
|
|
785
|
+
toolModuleDiscovery:
|
|
786
|
+
scope: top-level
|
|
779
787
|
concurrency:
|
|
780
788
|
maxConcurrentRuns: 3
|
|
781
789
|
routing:
|
package/README.zh.md
CHANGED
|
@@ -724,6 +724,11 @@ await stop(runtime);
|
|
|
724
724
|
- `maintenance.checkpoints` 清理后端用于 resume/recovery 的 checkpoint 状态
|
|
725
725
|
- `maintenance.records` 清理 harness 自己保存在 `runtime.sqlite` 中、已结束的 session/request 记录
|
|
726
726
|
|
|
727
|
+
`toolModuleDiscovery.scope` 用来控制本地 `resources/tools/` 这类 tool module 目录的发现范围:
|
|
728
|
+
|
|
729
|
+
- `recursive` 是默认值,会继续扫描嵌套目录
|
|
730
|
+
- `top-level` 只发现每个工具根目录下一层文件,同时保留 YAML catalog 的递归发现
|
|
731
|
+
|
|
727
732
|
当 libSQL 对 harness 运行时持久化报错时,错误信息会带上 `runtime.sqlite` 的绝对路径。对约束类错误(或设置环境变量 `AGENT_HARNESS_RUNTIME_SQLITE_DEBUG=1` 时),信息中还会包含被截断的失败 SQL,便于在同一进程里区分 harness 与其它 SQLite 数据库。
|
|
728
733
|
|
|
729
734
|
示例:
|
|
@@ -735,6 +740,8 @@ metadata:
|
|
|
735
740
|
name: default
|
|
736
741
|
spec:
|
|
737
742
|
runRoot: ./.agent
|
|
743
|
+
toolModuleDiscovery:
|
|
744
|
+
scope: top-level
|
|
738
745
|
concurrency:
|
|
739
746
|
maxConcurrentRuns: 3
|
|
740
747
|
routing:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.267";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.267";
|
|
@@ -10,7 +10,7 @@ import { validateAgent, validateTopology } from "./validate.js";
|
|
|
10
10
|
import { compileBinding } from "./agent-binding-compiler.js";
|
|
11
11
|
import { discoverSubagents, ensureDiscoverySources } from "./support/discovery.js";
|
|
12
12
|
import { collectAgentDiscoverySourceRefs, collectToolSourceRefs } from "./support/source-collectors.js";
|
|
13
|
-
import { getRoutingDefaultAgentId, getRuntimeResources, getRoutingRules, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
13
|
+
import { getRoutingDefaultAgentId, getRuntimeResources, getToolModuleDiscoveryConfig, getRoutingRules, resolveRefId, } from "./support/workspace-ref-utils.js";
|
|
14
14
|
import { hydrateAgentMcpTools, hydrateResourceAndExternalTools } from "./tool-hydration.js";
|
|
15
15
|
import { traceStartupStage } from "../runtime/startup-tracing.js";
|
|
16
16
|
import { shouldSkipScanDirectory } from "../utils/fs.js";
|
|
@@ -123,7 +123,7 @@ async function resolveConfiguredResources(entries, workspaceRoot) {
|
|
|
123
123
|
}
|
|
124
124
|
return resolved;
|
|
125
125
|
}
|
|
126
|
-
async function registerAttachedResourceTools(tools, resourceRoot) {
|
|
126
|
+
async function registerAttachedResourceTools(tools, resourceRoot, toolModuleDiscoveryScope) {
|
|
127
127
|
const toolsRoot = path.join(resourceRoot, "tools");
|
|
128
128
|
for (const { item, sourcePath } of await readYamlItems(toolsRoot, undefined, { recursive: true })) {
|
|
129
129
|
const parsed = parseToolObject({
|
|
@@ -134,7 +134,7 @@ async function registerAttachedResourceTools(tools, resourceRoot) {
|
|
|
134
134
|
});
|
|
135
135
|
tools.set(parsed.id, parsed);
|
|
136
136
|
}
|
|
137
|
-
for (const { item, sourcePath } of await readToolModuleItems(toolsRoot)) {
|
|
137
|
+
for (const { item, sourcePath } of await readToolModuleItems(toolsRoot, { scope: toolModuleDiscoveryScope })) {
|
|
138
138
|
const parsed = parseToolObject({
|
|
139
139
|
id: String(item.id),
|
|
140
140
|
kind: "tool",
|
|
@@ -221,6 +221,7 @@ export async function loadWorkspace(workspaceRoot, options = {}) {
|
|
|
221
221
|
loaded.refs.set(`agent/${agent.id}`, agent);
|
|
222
222
|
}
|
|
223
223
|
const { embeddings, mcpServers, models, vectorStores, tools } = collectParsedResources(loaded.refs);
|
|
224
|
+
const toolModuleDiscoveryConfig = getToolModuleDiscoveryConfig(loaded.refs);
|
|
224
225
|
await traceStartupStage("workspace.hydrate.agentMcpTools", () => hydrateAgentMcpTools(loaded.agents, mcpServers, tools), {
|
|
225
226
|
workspaceRoot,
|
|
226
227
|
agentCount: loaded.agents.length,
|
|
@@ -234,7 +235,7 @@ export async function loadWorkspace(workspaceRoot, options = {}) {
|
|
|
234
235
|
configuredResourceCount: configuredResources.length,
|
|
235
236
|
});
|
|
236
237
|
for (const resource of resolvedConfiguredResources) {
|
|
237
|
-
await traceStartupStage("workspace.register.attachedResourceTools", () => registerAttachedResourceTools(tools, resource.root), {
|
|
238
|
+
await traceStartupStage("workspace.register.attachedResourceTools", () => registerAttachedResourceTools(tools, resource.root, toolModuleDiscoveryConfig.scope), {
|
|
238
239
|
workspaceRoot,
|
|
239
240
|
resourceRoot: resource.root,
|
|
240
241
|
});
|
|
@@ -259,7 +260,7 @@ export async function loadWorkspace(workspaceRoot, options = {}) {
|
|
|
259
260
|
workspaceRoot,
|
|
260
261
|
externalResourceCount: externalResources.length,
|
|
261
262
|
});
|
|
262
|
-
await traceStartupStage("workspace.hydrate.externalTools", () => hydrateResourceAndExternalTools(tools, externalResources, workspaceRoot), {
|
|
263
|
+
await traceStartupStage("workspace.hydrate.externalTools", () => hydrateResourceAndExternalTools(tools, externalResources, workspaceRoot, toolModuleDiscoveryConfig.scope), {
|
|
263
264
|
workspaceRoot,
|
|
264
265
|
externalResourceCount: externalResources.length,
|
|
265
266
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ParsedAgentObject, WorkspaceLoadOptions, WorkspaceObject } from "../contracts/types.js";
|
|
2
|
+
import type { ToolModuleDiscoveryScope } from "./support/workspace-ref-utils.js";
|
|
2
3
|
export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
|
|
3
4
|
type RefMap = Map<string, WorkspaceObject | ParsedAgentObject>;
|
|
4
5
|
export type WorkspaceObjects = {
|
|
@@ -7,7 +8,9 @@ export type WorkspaceObjects = {
|
|
|
7
8
|
};
|
|
8
9
|
export declare function conventionalPackageRoots(root: string, relativeDir: "tools" | "skills"): string[];
|
|
9
10
|
export declare function parseAgentItem(item: Record<string, unknown>, sourcePath: string): ParsedAgentObject;
|
|
10
|
-
export declare function readToolModuleItems(root: string
|
|
11
|
+
export declare function readToolModuleItems(root: string, options?: {
|
|
12
|
+
scope?: ToolModuleDiscoveryScope;
|
|
13
|
+
}): Promise<Array<{
|
|
11
14
|
item: Record<string, unknown>;
|
|
12
15
|
sourcePath: string;
|
|
13
16
|
}>>;
|
|
@@ -613,7 +613,14 @@ async function loadModuleAgentsForRoot(root, mergedAgents) {
|
|
|
613
613
|
}
|
|
614
614
|
}
|
|
615
615
|
}
|
|
616
|
-
|
|
616
|
+
function getMergedToolModuleDiscoveryScope(mergedObjects) {
|
|
617
|
+
const runtimeDefaults = mergedObjects.get("runtime/default")?.item;
|
|
618
|
+
const toolModuleDiscovery = typeof runtimeDefaults?.toolModuleDiscovery === "object" && runtimeDefaults.toolModuleDiscovery
|
|
619
|
+
? runtimeDefaults.toolModuleDiscovery
|
|
620
|
+
: {};
|
|
621
|
+
return toolModuleDiscovery.scope === "top-level" ? "top-level" : "recursive";
|
|
622
|
+
}
|
|
623
|
+
async function loadConventionalObjectsForRoot(root, mergedObjects, toolModuleDiscoveryScope) {
|
|
617
624
|
for (const directory of CONVENTIONAL_OBJECT_DIRECTORIES) {
|
|
618
625
|
for (const objectRoot of conventionalDirectoryRoots(root, directory)) {
|
|
619
626
|
for (const { item, sourcePath } of await readYamlItemsIgnoringNodeModules(objectRoot)) {
|
|
@@ -623,7 +630,7 @@ async function loadConventionalObjectsForRoot(root, mergedObjects) {
|
|
|
623
630
|
}
|
|
624
631
|
mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
|
|
625
632
|
}
|
|
626
|
-
for (const { item, sourcePath } of await readToolModuleItems(objectRoot)) {
|
|
633
|
+
for (const { item, sourcePath } of await readToolModuleItems(objectRoot, { scope: toolModuleDiscoveryScope })) {
|
|
627
634
|
const workspaceObject = parseWorkspaceObject(item, sourcePath);
|
|
628
635
|
if (!workspaceObject) {
|
|
629
636
|
continue;
|
|
@@ -785,10 +792,11 @@ async function loadRootObjects(root, mergedObjects) {
|
|
|
785
792
|
function isAgentKind(kind) {
|
|
786
793
|
return kind === "agent";
|
|
787
794
|
}
|
|
788
|
-
export async function readToolModuleItems(root) {
|
|
795
|
+
export async function readToolModuleItems(root, options = {}) {
|
|
789
796
|
if (!(await fileExists(root))) {
|
|
790
797
|
return [];
|
|
791
798
|
}
|
|
799
|
+
const scope = options.scope === "top-level" ? "top-level" : "recursive";
|
|
792
800
|
const files = [];
|
|
793
801
|
const pending = [root];
|
|
794
802
|
while (pending.length > 0) {
|
|
@@ -798,7 +806,7 @@ export async function readToolModuleItems(root) {
|
|
|
798
806
|
const entryPath = path.join(current, entry.name);
|
|
799
807
|
const entryType = await resolveScanEntryType(entryPath, entry);
|
|
800
808
|
if (entryType === "directory") {
|
|
801
|
-
if (shouldSkipScanDirectory(entry.name)) {
|
|
809
|
+
if (shouldSkipScanDirectory(entry.name) || scope === "top-level") {
|
|
802
810
|
continue;
|
|
803
811
|
}
|
|
804
812
|
pending.push(entryPath);
|
|
@@ -886,7 +894,7 @@ export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
|
|
|
886
894
|
const configRoot = conventionalConfigRoot(root) ?? root;
|
|
887
895
|
await loadConfigYamlForRoot(root, configRoot, mergedAgents, mergedObjects);
|
|
888
896
|
await loadModuleAgentsForRoot(root, mergedAgents);
|
|
889
|
-
await loadConventionalObjectsForRoot(root, mergedObjects);
|
|
897
|
+
await loadConventionalObjectsForRoot(root, mergedObjects, getMergedToolModuleDiscoveryScope(mergedObjects));
|
|
890
898
|
await loadModuleObjectsForRoot(root, mergedObjects);
|
|
891
899
|
await loadRootObjects(root, mergedObjects);
|
|
892
900
|
}
|
|
@@ -31,9 +31,14 @@ export type ProviderRetryConfig = {
|
|
|
31
31
|
export type ResilienceConfig = {
|
|
32
32
|
providerRetries: ProviderRetryConfig;
|
|
33
33
|
};
|
|
34
|
+
export type ToolModuleDiscoveryScope = "recursive" | "top-level";
|
|
35
|
+
export type ToolModuleDiscoveryConfig = {
|
|
36
|
+
scope: ToolModuleDiscoveryScope;
|
|
37
|
+
};
|
|
34
38
|
export declare function getWorkspaceObject(refs: Map<string, WorkspaceObject | ParsedAgentObject>, ref: string | undefined): WorkspaceObject | undefined;
|
|
35
39
|
export declare function getRuntimeDefaults(refs: Map<string, WorkspaceObject | ParsedAgentObject>): Record<string, unknown> | undefined;
|
|
36
40
|
export declare function getRuntimeResources(refs: Map<string, WorkspaceObject | ParsedAgentObject>): string[];
|
|
41
|
+
export declare function getToolModuleDiscoveryConfig(refs: Map<string, WorkspaceObject | ParsedAgentObject>): ToolModuleDiscoveryConfig;
|
|
37
42
|
export declare function getRuntimeMemoryDefaults(refs: Map<string, WorkspaceObject | ParsedAgentObject>): Record<string, unknown> | undefined;
|
|
38
43
|
export declare function getRecoveryConfig(refs: Map<string, WorkspaceObject | ParsedAgentObject>): RecoveryConfig;
|
|
39
44
|
export declare function getConcurrencyConfig(refs: Map<string, WorkspaceObject | ParsedAgentObject>): ConcurrencyConfig;
|
|
@@ -35,6 +35,15 @@ export function getRuntimeResources(refs) {
|
|
|
35
35
|
.filter((value) => typeof value === "string" && value.trim().length > 0)
|
|
36
36
|
.map((value) => value.trim());
|
|
37
37
|
}
|
|
38
|
+
export function getToolModuleDiscoveryConfig(refs) {
|
|
39
|
+
const runtimeDefaults = getRuntimeDefaults(refs);
|
|
40
|
+
const toolModuleDiscovery = typeof runtimeDefaults?.toolModuleDiscovery === "object" && runtimeDefaults.toolModuleDiscovery
|
|
41
|
+
? runtimeDefaults.toolModuleDiscovery
|
|
42
|
+
: {};
|
|
43
|
+
return {
|
|
44
|
+
scope: toolModuleDiscovery.scope === "top-level" ? "top-level" : "recursive",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
38
47
|
export function getRuntimeMemoryDefaults(refs) {
|
|
39
48
|
const runtimeMemories = Array.from(refs.values()).filter((object) => !("executionMode" in object) && object.kind === "runtime-memory");
|
|
40
49
|
if (runtimeMemories.length === 0) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ParsedAgentObject, ParsedMcpServerObject, ParsedToolObject } from "../contracts/types.js";
|
|
2
|
-
|
|
2
|
+
import type { ToolModuleDiscoveryScope } from "./support/workspace-ref-utils.js";
|
|
3
|
+
export declare function hydrateResourceAndExternalTools(tools: Map<string, ParsedToolObject>, toolSourceRefs: string[], workspaceRoot: string, toolModuleDiscoveryScope?: ToolModuleDiscoveryScope): Promise<void>;
|
|
3
4
|
export declare function hydrateAgentMcpTools(agents: ParsedAgentObject[], mcpServers: Map<string, ParsedMcpServerObject>, tools: Map<string, ParsedToolObject>): Promise<void>;
|
|
@@ -144,11 +144,11 @@ function mergeReferencedMcpServer(referencedServer, item, agentId, name, sourceP
|
|
|
144
144
|
sourcePath,
|
|
145
145
|
};
|
|
146
146
|
}
|
|
147
|
-
async function hydrateExternalToolSource(tools, source, workspaceRoot) {
|
|
147
|
+
async function hydrateExternalToolSource(tools, source, workspaceRoot, toolModuleDiscoveryScope) {
|
|
148
148
|
const externalRoot = await ensureExternalResourceSource(source, workspaceRoot);
|
|
149
149
|
const discoveredToolRefs = [];
|
|
150
150
|
const sourcePrefix = `external.${createHash("sha256").update(source).digest("hex").slice(0, 12)}`;
|
|
151
|
-
for (const { item, sourcePath } of await readToolModuleItems(path.join(externalRoot, "tools"))) {
|
|
151
|
+
for (const { item, sourcePath } of await readToolModuleItems(path.join(externalRoot, "tools"), { scope: toolModuleDiscoveryScope })) {
|
|
152
152
|
const toolId = typeof item.id === "string" ? item.id : undefined;
|
|
153
153
|
if (!toolId) {
|
|
154
154
|
continue;
|
|
@@ -179,10 +179,10 @@ async function hydrateExternalToolSource(tools, source, workspaceRoot) {
|
|
|
179
179
|
});
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
|
-
export async function hydrateResourceAndExternalTools(tools, toolSourceRefs, workspaceRoot) {
|
|
182
|
+
export async function hydrateResourceAndExternalTools(tools, toolSourceRefs, workspaceRoot, toolModuleDiscoveryScope = "recursive") {
|
|
183
183
|
for (const source of toolSourceRefs) {
|
|
184
184
|
if (isExternalSourceLocator(source)) {
|
|
185
|
-
await hydrateExternalToolSource(tools, source, workspaceRoot);
|
|
185
|
+
await hydrateExternalToolSource(tools, source, workspaceRoot, toolModuleDiscoveryScope);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
for (const resourceTool of await listResourceTools(toolSourceRefs, workspaceRoot)) {
|