@botbotgo/agent-harness 0.0.38 → 0.0.40
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 +15 -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/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 +70 -31
- package/dist/runtime/index.d.ts +3 -1
- package/dist/runtime/index.js +2 -1
- package/dist/runtime/support/harness-support.js +11 -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 +16 -2
- 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
|
@@ -4,11 +4,14 @@ import { defaultResourceConfigRoot, defaultResourceSkillsRoot } from "../../reso
|
|
|
4
4
|
import { validateSkillMetadata } from "../../runtime/support/skill-metadata.js";
|
|
5
5
|
import { ensureExternalResourceSource, isDirectoryPath, isExternalSourceLocator, resolveExternalResourcePath, resolveResourcePackageRoot, } from "../../resource/sources.js";
|
|
6
6
|
import { parseAgentItem, readYamlItems } from "../object-loader.js";
|
|
7
|
-
function
|
|
8
|
-
|
|
7
|
+
function isBundledResourceRef(ref) {
|
|
8
|
+
return ref.startsWith("resource://") || ref.startsWith("builtin://");
|
|
9
|
+
}
|
|
10
|
+
function resolveBundledResourcePath(kind, ref) {
|
|
11
|
+
const normalized = ref.replace(/^(resource|builtin):\/\//, "").replace(/^\/+/, "");
|
|
9
12
|
if (kind === "skills") {
|
|
10
13
|
if (!normalized.startsWith("skills")) {
|
|
11
|
-
throw new Error(`Unsupported
|
|
14
|
+
throw new Error(`Unsupported resource skill discovery path ${ref}`);
|
|
12
15
|
}
|
|
13
16
|
const suffix = normalized.replace(/^skills\/?/, "");
|
|
14
17
|
const root = defaultResourceSkillsRoot();
|
|
@@ -28,7 +31,7 @@ function resolveBuiltinPath(kind, ref) {
|
|
|
28
31
|
return candidate;
|
|
29
32
|
}
|
|
30
33
|
if (!normalized.startsWith("agents")) {
|
|
31
|
-
throw new Error(`Unsupported
|
|
34
|
+
throw new Error(`Unsupported resource subagent discovery path ${ref}`);
|
|
32
35
|
}
|
|
33
36
|
const suffix = normalized.replace(/^agents\/?/, "");
|
|
34
37
|
const root = path.join(defaultResourceConfigRoot(), "agents");
|
|
@@ -69,8 +72,8 @@ export async function ensureDiscoverySources(locators, workspaceRoot) {
|
|
|
69
72
|
.map((locator) => ensureExternalResourceSource(locator, workspaceRoot)));
|
|
70
73
|
}
|
|
71
74
|
export function resolveDiscoveryRoot(ref, workspaceRoot, kind) {
|
|
72
|
-
if (ref
|
|
73
|
-
return
|
|
75
|
+
if (isBundledResourceRef(ref)) {
|
|
76
|
+
return resolveBundledResourcePath(kind, ref);
|
|
74
77
|
}
|
|
75
78
|
if (isExternalSourceLocator(ref)) {
|
|
76
79
|
return preferPackageConvention(resolveExternalResourcePath(ref, workspaceRoot), kind);
|
|
@@ -78,8 +81,8 @@ export function resolveDiscoveryRoot(ref, workspaceRoot, kind) {
|
|
|
78
81
|
return preferPackageConvention(path.resolve(workspaceRoot, ref), kind);
|
|
79
82
|
}
|
|
80
83
|
async function resolveDiscoveryRootAsync(ref, workspaceRoot, kind) {
|
|
81
|
-
if (ref
|
|
82
|
-
return
|
|
84
|
+
if (isBundledResourceRef(ref)) {
|
|
85
|
+
return resolveBundledResourcePath(kind, ref);
|
|
83
86
|
}
|
|
84
87
|
if (isExternalSourceLocator(ref)) {
|
|
85
88
|
return preferPackageConvention(await ensureExternalResourceSource(ref, workspaceRoot), kind);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isExternalSourceLocator } from "../../resource/sources.js";
|
|
2
2
|
export function collectToolSourceRefs(tools, agents, options) {
|
|
3
|
-
const refs = new Set(options.resourceSources ??
|
|
3
|
+
const refs = new Set(options.resourceSources ?? []);
|
|
4
4
|
for (const tool of tools.values()) {
|
|
5
5
|
for (const ref of tool.bundleRefs) {
|
|
6
6
|
if (isExternalSourceLocator(ref)) {
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { ParsedAgentObject, WorkspaceObject } from "../../contracts/types.js";
|
|
2
|
+
export type RoutingRule = {
|
|
3
|
+
agentId: string;
|
|
4
|
+
equals?: string[];
|
|
5
|
+
startsWith?: string[];
|
|
6
|
+
contains?: string[];
|
|
7
|
+
regex?: string[];
|
|
8
|
+
minLength?: number;
|
|
9
|
+
maxLength?: number;
|
|
10
|
+
minLines?: number;
|
|
11
|
+
maxLines?: number;
|
|
12
|
+
hasThreadId?: boolean;
|
|
13
|
+
caseSensitive?: boolean;
|
|
14
|
+
};
|
|
2
15
|
export declare function getWorkspaceObject(refs: Map<string, WorkspaceObject | ParsedAgentObject>, ref: string | undefined): WorkspaceObject | undefined;
|
|
3
16
|
export declare function getRuntimeDefaults(refs: Map<string, WorkspaceObject | ParsedAgentObject>): Record<string, unknown> | undefined;
|
|
4
17
|
export declare function getRoutingSystemPrompt(refs: Map<string, WorkspaceObject | ParsedAgentObject>): string | undefined;
|
|
18
|
+
export declare function getRoutingDefaultAgentId(refs: Map<string, WorkspaceObject | ParsedAgentObject>): string | undefined;
|
|
19
|
+
export declare function isModelRoutingEnabled(refs: Map<string, WorkspaceObject | ParsedAgentObject>): boolean;
|
|
20
|
+
export declare function getRoutingRules(refs: Map<string, WorkspaceObject | ParsedAgentObject>): RoutingRule[];
|
|
21
|
+
export declare function matchRoutingRule(input: string, rule: RoutingRule, options?: {
|
|
22
|
+
threadId?: string;
|
|
23
|
+
}): boolean;
|
|
5
24
|
export declare function resolvePromptValue(promptConfig: unknown): string | undefined;
|
|
6
25
|
export declare function resolveRefId(ref: string): string;
|
|
7
26
|
export declare function resolvePathList(refs: Map<string, WorkspaceObject | ParsedAgentObject>, workspaceRoot: string, refList: string[]): string[];
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
function getRoutingObject(refs) {
|
|
3
|
+
const runtimeDefaults = getRuntimeDefaults(refs);
|
|
4
|
+
return typeof runtimeDefaults?.routing === "object" && runtimeDefaults.routing
|
|
5
|
+
? runtimeDefaults.routing
|
|
6
|
+
: undefined;
|
|
7
|
+
}
|
|
2
8
|
export function getWorkspaceObject(refs, ref) {
|
|
3
9
|
if (!ref) {
|
|
4
10
|
return undefined;
|
|
@@ -20,12 +26,108 @@ export function getRuntimeDefaults(refs) {
|
|
|
20
26
|
return runtimes[0].value;
|
|
21
27
|
}
|
|
22
28
|
export function getRoutingSystemPrompt(refs) {
|
|
23
|
-
const
|
|
24
|
-
const routing = typeof runtimeDefaults?.routing === "object" && runtimeDefaults.routing
|
|
25
|
-
? runtimeDefaults.routing
|
|
26
|
-
: undefined;
|
|
29
|
+
const routing = getRoutingObject(refs);
|
|
27
30
|
return typeof routing?.systemPrompt === "string" && routing.systemPrompt.trim() ? routing.systemPrompt : undefined;
|
|
28
31
|
}
|
|
32
|
+
export function getRoutingDefaultAgentId(refs) {
|
|
33
|
+
const routing = getRoutingObject(refs);
|
|
34
|
+
return typeof routing?.defaultAgentId === "string" && routing.defaultAgentId.trim()
|
|
35
|
+
? routing.defaultAgentId.trim()
|
|
36
|
+
: undefined;
|
|
37
|
+
}
|
|
38
|
+
export function isModelRoutingEnabled(refs) {
|
|
39
|
+
const routing = getRoutingObject(refs);
|
|
40
|
+
return routing?.modelRouting === true;
|
|
41
|
+
}
|
|
42
|
+
function toStringList(value) {
|
|
43
|
+
if (typeof value === "string" && value.trim()) {
|
|
44
|
+
return [value];
|
|
45
|
+
}
|
|
46
|
+
if (!Array.isArray(value)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const items = value
|
|
50
|
+
.filter((item) => typeof item === "string" && item.trim().length > 0)
|
|
51
|
+
.map((item) => item.trim());
|
|
52
|
+
return items.length > 0 ? items : undefined;
|
|
53
|
+
}
|
|
54
|
+
function toPositiveNumber(value) {
|
|
55
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
56
|
+
}
|
|
57
|
+
export function getRoutingRules(refs) {
|
|
58
|
+
const routing = getRoutingObject(refs);
|
|
59
|
+
if (!Array.isArray(routing?.rules)) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
return routing.rules.flatMap((rule, index) => {
|
|
63
|
+
if (typeof rule !== "object" || rule === null || Array.isArray(rule)) {
|
|
64
|
+
throw new Error(`Runtime routing.rules[${index}] must be an object`);
|
|
65
|
+
}
|
|
66
|
+
const typed = rule;
|
|
67
|
+
if (typeof typed.agentId !== "string" || !typed.agentId.trim()) {
|
|
68
|
+
throw new Error(`Runtime routing.rules[${index}] requires a non-empty agentId`);
|
|
69
|
+
}
|
|
70
|
+
const regex = toStringList(typed.regex);
|
|
71
|
+
if (regex) {
|
|
72
|
+
for (const pattern of regex) {
|
|
73
|
+
try {
|
|
74
|
+
new RegExp(pattern);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
78
|
+
throw new Error(`Runtime routing.rules[${index}] has invalid regex ${JSON.stringify(pattern)}: ${detail}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return [{
|
|
83
|
+
agentId: typed.agentId.trim(),
|
|
84
|
+
equals: toStringList(typed.equals),
|
|
85
|
+
startsWith: toStringList(typed.startsWith),
|
|
86
|
+
contains: toStringList(typed.contains),
|
|
87
|
+
regex,
|
|
88
|
+
minLength: toPositiveNumber(typed.minLength),
|
|
89
|
+
maxLength: toPositiveNumber(typed.maxLength),
|
|
90
|
+
minLines: toPositiveNumber(typed.minLines),
|
|
91
|
+
maxLines: toPositiveNumber(typed.maxLines),
|
|
92
|
+
hasThreadId: typeof typed.hasThreadId === "boolean" ? typed.hasThreadId : undefined,
|
|
93
|
+
caseSensitive: typed.caseSensitive === true,
|
|
94
|
+
}];
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
export function matchRoutingRule(input, rule, options = {}) {
|
|
98
|
+
const text = input.trim();
|
|
99
|
+
const source = rule.caseSensitive ? text : text.toLowerCase();
|
|
100
|
+
const lineCount = text ? text.split(/\n+/).length : 0;
|
|
101
|
+
const normalize = (value) => (rule.caseSensitive ? value : value.toLowerCase());
|
|
102
|
+
if (rule.hasThreadId !== undefined && rule.hasThreadId !== Boolean(options.threadId)) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (rule.minLength !== undefined && text.length < rule.minLength) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (rule.maxLength !== undefined && text.length > rule.maxLength) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (rule.minLines !== undefined && lineCount < rule.minLines) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (rule.maxLines !== undefined && lineCount > rule.maxLines) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (rule.equals && !rule.equals.some((candidate) => source === normalize(candidate.trim()))) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if (rule.startsWith && !rule.startsWith.some((candidate) => source.startsWith(normalize(candidate.trim())))) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
if (rule.contains && !rule.contains.some((candidate) => source.includes(normalize(candidate.trim())))) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
if (rule.regex && !rule.regex.some((pattern) => new RegExp(pattern, rule.caseSensitive ? undefined : "i").test(text))) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
29
131
|
export function resolvePromptValue(promptConfig) {
|
|
30
132
|
if (typeof promptConfig === "string" && promptConfig.trim()) {
|
|
31
133
|
return promptConfig;
|
|
@@ -33,10 +135,14 @@ export function resolvePromptValue(promptConfig) {
|
|
|
33
135
|
return undefined;
|
|
34
136
|
}
|
|
35
137
|
export function resolveRefId(ref) {
|
|
36
|
-
|
|
138
|
+
const [namespace, ...rest] = ref.split("/");
|
|
139
|
+
if (rest.length === 0) {
|
|
37
140
|
return ref;
|
|
38
141
|
}
|
|
39
|
-
|
|
142
|
+
if (["agent", "embedding-model", "mcp", "model", "object", "prompt", "runtime", "tool", "vector-store"].includes(namespace)) {
|
|
143
|
+
return rest.join("/");
|
|
144
|
+
}
|
|
145
|
+
return ref;
|
|
40
146
|
}
|
|
41
147
|
export function resolvePathList(refs, workspaceRoot, refList) {
|
|
42
148
|
return refList.map((ref) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.40",
|
|
4
|
+
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
|
|
52
52
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
53
|
-
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/stock-research-app-run.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts test/llamaindex-dependency-compat.test.ts",
|
|
53
|
+
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/stock-research-app-run.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts test/llamaindex-dependency-compat.test.ts test/skill-standard.test.ts test/routing-config.test.ts test/workspace-compat-regressions.test.ts",
|
|
54
54
|
"test:real-providers": "vitest run test/real-provider-harness.test.ts",
|
|
55
55
|
"release:prepare": "npm version patch --no-git-tag-version && node ./scripts/sync-example-version.mjs",
|
|
56
56
|
"release:pack": "npm pack --dry-run",
|