@botbotgo/agent-harness 0.0.1
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/dist/api.d.ts +22 -0
- package/dist/api.js +48 -0
- package/dist/config/direct.yaml +48 -0
- package/dist/config/embedding-model.yaml +30 -0
- package/dist/config/model.yaml +44 -0
- package/dist/config/orchestra.yaml +92 -0
- package/dist/config/runtime.yaml +47 -0
- package/dist/config/vector-store.yaml +26 -0
- package/dist/contracts/types.d.ts +359 -0
- package/dist/contracts/types.js +1 -0
- package/dist/extensions.d.ts +16 -0
- package/dist/extensions.js +251 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/persistence/file-store.d.ts +39 -0
- package/dist/persistence/file-store.js +282 -0
- package/dist/presentation.d.ts +4 -0
- package/dist/presentation.js +175 -0
- package/dist/runtime/agent-runtime-adapter.d.ts +33 -0
- package/dist/runtime/agent-runtime-adapter.js +445 -0
- package/dist/runtime/event-bus.d.ts +6 -0
- package/dist/runtime/event-bus.js +15 -0
- package/dist/runtime/file-checkpoint-saver.d.ts +20 -0
- package/dist/runtime/file-checkpoint-saver.js +91 -0
- package/dist/runtime/harness.d.ts +57 -0
- package/dist/runtime/harness.js +696 -0
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/inventory.d.ts +25 -0
- package/dist/runtime/inventory.js +62 -0
- package/dist/runtime/parsing/index.d.ts +2 -0
- package/dist/runtime/parsing/index.js +2 -0
- package/dist/runtime/parsing/output-parsing.d.ts +12 -0
- package/dist/runtime/parsing/output-parsing.js +424 -0
- package/dist/runtime/parsing/stream-event-parsing.d.ts +27 -0
- package/dist/runtime/parsing/stream-event-parsing.js +161 -0
- package/dist/runtime/policy-engine.d.ts +9 -0
- package/dist/runtime/policy-engine.js +23 -0
- package/dist/runtime/store.d.ts +50 -0
- package/dist/runtime/store.js +118 -0
- package/dist/runtime/support/embedding-models.d.ts +4 -0
- package/dist/runtime/support/embedding-models.js +33 -0
- package/dist/runtime/support/harness-support.d.ts +27 -0
- package/dist/runtime/support/harness-support.js +116 -0
- package/dist/runtime/support/index.d.ts +4 -0
- package/dist/runtime/support/index.js +4 -0
- package/dist/runtime/support/llamaindex.d.ts +24 -0
- package/dist/runtime/support/llamaindex.js +108 -0
- package/dist/runtime/support/runtime-factories.d.ts +3 -0
- package/dist/runtime/support/runtime-factories.js +39 -0
- package/dist/runtime/support/skill-metadata.d.ts +1 -0
- package/dist/runtime/support/skill-metadata.js +34 -0
- package/dist/runtime/support/vector-stores.d.ts +7 -0
- package/dist/runtime/support/vector-stores.js +130 -0
- package/dist/runtime/thread-memory-sync.d.ts +14 -0
- package/dist/runtime/thread-memory-sync.js +88 -0
- package/dist/runtime/tool-hitl.d.ts +5 -0
- package/dist/runtime/tool-hitl.js +108 -0
- package/dist/utils/fs.d.ts +6 -0
- package/dist/utils/fs.js +39 -0
- package/dist/utils/id.d.ts +1 -0
- package/dist/utils/id.js +8 -0
- package/dist/vendor/builtins.d.ts +23 -0
- package/dist/vendor/builtins.js +103 -0
- package/dist/vendor/sources.d.ts +12 -0
- package/dist/vendor/sources.js +115 -0
- package/dist/workspace/agent-binding-compiler.d.ts +4 -0
- package/dist/workspace/agent-binding-compiler.js +181 -0
- package/dist/workspace/compile.d.ts +2 -0
- package/dist/workspace/compile.js +107 -0
- package/dist/workspace/index.d.ts +6 -0
- package/dist/workspace/index.js +6 -0
- package/dist/workspace/object-loader.d.ts +16 -0
- package/dist/workspace/object-loader.js +405 -0
- package/dist/workspace/resource-compilers.d.ts +13 -0
- package/dist/workspace/resource-compilers.js +182 -0
- package/dist/workspace/support/discovery.d.ts +5 -0
- package/dist/workspace/support/discovery.js +108 -0
- package/dist/workspace/support/index.d.ts +2 -0
- package/dist/workspace/support/index.js +2 -0
- package/dist/workspace/support/source-collectors.d.ts +3 -0
- package/dist/workspace/support/source-collectors.js +30 -0
- package/dist/workspace/support/workspace-ref-utils.d.ts +8 -0
- package/dist/workspace/support/workspace-ref-utils.js +50 -0
- package/dist/workspace/validate.d.ts +3 -0
- package/dist/workspace/validate.js +65 -0
- package/package.json +32 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { readdir } from "node:fs/promises";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseAllDocuments } from "yaml";
|
|
6
|
+
import { fileExists, listFilesRecursive, readYamlOrJson } from "../utils/fs.js";
|
|
7
|
+
const ROOT_AGENT_FILENAMES = [
|
|
8
|
+
"agent.yaml",
|
|
9
|
+
"agent.yml",
|
|
10
|
+
"orchestra.yaml",
|
|
11
|
+
"orchestra.yml",
|
|
12
|
+
"direct.yaml",
|
|
13
|
+
"direct.yml",
|
|
14
|
+
"research.yaml",
|
|
15
|
+
"research.yml",
|
|
16
|
+
];
|
|
17
|
+
const LEGACY_GLOBAL_AGENT_FILENAMES = ["agent.yaml", "agent.yml"];
|
|
18
|
+
function frameworkConfigRoot() {
|
|
19
|
+
const resolved = fileURLToPath(new URL("../../config", import.meta.url));
|
|
20
|
+
const distSegment = `${path.sep}dist${path.sep}config`;
|
|
21
|
+
if (!resolved.includes(distSegment)) {
|
|
22
|
+
return resolved;
|
|
23
|
+
}
|
|
24
|
+
const sourceConfigRoot = resolved.replace(distSegment, `${path.sep}config`);
|
|
25
|
+
if (!existsSync(sourceConfigRoot)) {
|
|
26
|
+
return resolved;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
return statSync(sourceConfigRoot).mtimeMs >= statSync(resolved).mtimeMs ? sourceConfigRoot : resolved;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return sourceConfigRoot;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function toArray(value) {
|
|
36
|
+
return Array.isArray(value) ? value : [];
|
|
37
|
+
}
|
|
38
|
+
function asObject(value) {
|
|
39
|
+
return typeof value === "object" && value ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
function normalizeKind(kind) {
|
|
42
|
+
switch (kind) {
|
|
43
|
+
case "LangChainAgent":
|
|
44
|
+
return "langchain-agent";
|
|
45
|
+
case "DeepAgent":
|
|
46
|
+
return "deepagent";
|
|
47
|
+
case "FileStore":
|
|
48
|
+
return "file-store";
|
|
49
|
+
case "InMemoryStore":
|
|
50
|
+
return "in-memory-store";
|
|
51
|
+
case "RedisStore":
|
|
52
|
+
return "redis-store";
|
|
53
|
+
case "PostgresStore":
|
|
54
|
+
return "postgres-store";
|
|
55
|
+
case "SqliteSaver":
|
|
56
|
+
return "sqlite-saver";
|
|
57
|
+
case "FileCheckpointer":
|
|
58
|
+
return "file-checkpointer";
|
|
59
|
+
case "Checkpointer":
|
|
60
|
+
return "checkpointer";
|
|
61
|
+
case "Model":
|
|
62
|
+
return "model";
|
|
63
|
+
case "EmbeddingModel":
|
|
64
|
+
return "embedding-model";
|
|
65
|
+
case "VectorStore":
|
|
66
|
+
return "vector-store";
|
|
67
|
+
case "Backend":
|
|
68
|
+
return "backend";
|
|
69
|
+
case "Store":
|
|
70
|
+
return "store";
|
|
71
|
+
case "Memory":
|
|
72
|
+
return "memory";
|
|
73
|
+
case "Tool":
|
|
74
|
+
return "tool";
|
|
75
|
+
case "Skill":
|
|
76
|
+
return "skill";
|
|
77
|
+
case "Runtime":
|
|
78
|
+
return "runtime";
|
|
79
|
+
case "Prompt":
|
|
80
|
+
return "prompt";
|
|
81
|
+
default:
|
|
82
|
+
return kind;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export function normalizeYamlItem(item) {
|
|
86
|
+
const metadata = asObject(item.metadata);
|
|
87
|
+
const spec = asObject(item.spec);
|
|
88
|
+
const kind = typeof item.kind === "string" ? normalizeKind(item.kind) : undefined;
|
|
89
|
+
const name = typeof metadata?.name === "string" ? metadata.name : undefined;
|
|
90
|
+
const description = typeof metadata?.description === "string" ? metadata.description : undefined;
|
|
91
|
+
if (!spec && !metadata) {
|
|
92
|
+
return kind ? { ...item, kind } : item;
|
|
93
|
+
}
|
|
94
|
+
if (!spec && metadata) {
|
|
95
|
+
return {
|
|
96
|
+
...item,
|
|
97
|
+
...(description ? { description } : {}),
|
|
98
|
+
...(name ? { id: name } : {}),
|
|
99
|
+
...(kind ? { kind } : {}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
...(spec ?? {}),
|
|
104
|
+
...(description ? { description } : {}),
|
|
105
|
+
...(name ? { id: name } : {}),
|
|
106
|
+
...(kind ? { kind } : {}),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function normalizeCatalogItem(item) {
|
|
110
|
+
if ("metadata" in item || "spec" in item || "path" in item || typeof item.name !== "string") {
|
|
111
|
+
return item;
|
|
112
|
+
}
|
|
113
|
+
const { name, description, kind, ...spec } = item;
|
|
114
|
+
return {
|
|
115
|
+
...(typeof kind === "string" ? { kind } : {}),
|
|
116
|
+
metadata: {
|
|
117
|
+
name,
|
|
118
|
+
...(typeof description === "string" ? { description } : {}),
|
|
119
|
+
},
|
|
120
|
+
spec,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function readRefArray(items) {
|
|
124
|
+
return toArray(items)
|
|
125
|
+
.map((item) => (typeof item === "object" && item && "ref" in item ? item.ref : undefined))
|
|
126
|
+
.filter((item) => Boolean(item));
|
|
127
|
+
}
|
|
128
|
+
function readPathArray(items) {
|
|
129
|
+
return toArray(items)
|
|
130
|
+
.map((item) => typeof item === "string"
|
|
131
|
+
? item
|
|
132
|
+
: typeof item === "object" && item && "path" in item && typeof item.path === "string"
|
|
133
|
+
? item.path
|
|
134
|
+
: undefined)
|
|
135
|
+
.filter((item) => Boolean(item));
|
|
136
|
+
}
|
|
137
|
+
function readSingleRef(value) {
|
|
138
|
+
if (typeof value === "string" && value.trim()) {
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
if (typeof value === "object" && value && "ref" in value && typeof value.ref === "string") {
|
|
142
|
+
return value.ref;
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
export function parseAgentItem(item, sourcePath) {
|
|
147
|
+
const subagentRefs = readRefArray(item.subagents);
|
|
148
|
+
const subagentPathRefs = readPathArray(item.subagents);
|
|
149
|
+
const kind = typeof item.kind === "string" ? item.kind : "agent";
|
|
150
|
+
const executionMode = String((kind === "langchain-agent" ? "langchain-v1" : undefined) ??
|
|
151
|
+
(kind === "deepagent" ? "deepagent" : undefined) ??
|
|
152
|
+
"deepagent");
|
|
153
|
+
return {
|
|
154
|
+
id: String(item.id),
|
|
155
|
+
executionMode: executionMode,
|
|
156
|
+
description: String(item.description ?? ""),
|
|
157
|
+
modelRef: readSingleRef(item.modelRef) ?? "",
|
|
158
|
+
runRoot: typeof item.runRoot === "string" ? item.runRoot : undefined,
|
|
159
|
+
toolRefs: readRefArray(item.tools),
|
|
160
|
+
skillPathRefs: readPathArray(item.skills),
|
|
161
|
+
memorySources: readPathArray(item.memory),
|
|
162
|
+
subagentRefs,
|
|
163
|
+
subagentPathRefs,
|
|
164
|
+
langchainAgentConfig: {
|
|
165
|
+
...(typeof item.systemPrompt === "string" || typeof item.interruptOn === "object" || typeof item.checkpointer === "object"
|
|
166
|
+
? {
|
|
167
|
+
...(typeof item.systemPrompt === "string" ? { systemPrompt: item.systemPrompt } : {}),
|
|
168
|
+
...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
|
|
169
|
+
...(typeof item.checkpointer === "object" && item.checkpointer ? { checkpointer: item.checkpointer } : {}),
|
|
170
|
+
}
|
|
171
|
+
: {}),
|
|
172
|
+
},
|
|
173
|
+
deepAgentConfig: {
|
|
174
|
+
...(typeof item.systemPrompt === "string" ||
|
|
175
|
+
typeof item.backend === "object" ||
|
|
176
|
+
typeof item.store === "object" ||
|
|
177
|
+
typeof item.checkpointer === "object" ||
|
|
178
|
+
typeof item.interruptOn === "object"
|
|
179
|
+
? {
|
|
180
|
+
...(typeof item.systemPrompt === "string" ? { systemPrompt: item.systemPrompt } : {}),
|
|
181
|
+
...(typeof item.backend === "object" && item.backend ? { backend: item.backend } : {}),
|
|
182
|
+
...(typeof item.store === "object" && item.store ? { store: item.store } : {}),
|
|
183
|
+
...(typeof item.checkpointer === "object" && item.checkpointer ? { checkpointer: item.checkpointer } : {}),
|
|
184
|
+
...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
|
|
185
|
+
}
|
|
186
|
+
: {}),
|
|
187
|
+
},
|
|
188
|
+
sourcePath,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function objectItemsFromDocument(document, sourcePath) {
|
|
192
|
+
if (typeof document !== "object" || !document) {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
const items = document.items;
|
|
196
|
+
if (Array.isArray(items)) {
|
|
197
|
+
const records = [];
|
|
198
|
+
for (const item of items) {
|
|
199
|
+
if (typeof item !== "object" || !item) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const typedItem = item;
|
|
203
|
+
if (typeof typedItem.path === "string" && typedItem.path.trim()) {
|
|
204
|
+
const referencedPath = path.isAbsolute(typedItem.path)
|
|
205
|
+
? typedItem.path
|
|
206
|
+
: path.join(path.dirname(sourcePath), typedItem.path);
|
|
207
|
+
if (existsSync(referencedPath) && statSync(referencedPath).isDirectory()) {
|
|
208
|
+
const discoveredItems = await readYamlItems(referencedPath, undefined, { recursive: true });
|
|
209
|
+
records.push(...discoveredItems.map(({ item }) => item));
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const parsedDocuments = parseAllDocuments(await readYamlOrJson(referencedPath));
|
|
213
|
+
for (const parsedDocument of parsedDocuments) {
|
|
214
|
+
records.push(...(await objectItemsFromDocument(parsedDocument.toJSON(), referencedPath)));
|
|
215
|
+
}
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
records.push(normalizeCatalogItem(typedItem));
|
|
219
|
+
}
|
|
220
|
+
return records;
|
|
221
|
+
}
|
|
222
|
+
return [document];
|
|
223
|
+
}
|
|
224
|
+
function parseWorkspaceObject(item, sourcePath) {
|
|
225
|
+
if (typeof item.id !== "string") {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
const inferredKind = typeof item.kind === "string"
|
|
229
|
+
? item.kind
|
|
230
|
+
: path.basename(sourcePath).replace(/\.(yaml|yml|json)$/i, "");
|
|
231
|
+
if (!inferredKind) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
id: item.id,
|
|
236
|
+
kind: inferredKind,
|
|
237
|
+
sourcePath,
|
|
238
|
+
value: item,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function mergeValues(base, override) {
|
|
242
|
+
if (override === undefined) {
|
|
243
|
+
return base;
|
|
244
|
+
}
|
|
245
|
+
if (Array.isArray(base) && Array.isArray(override)) {
|
|
246
|
+
return override;
|
|
247
|
+
}
|
|
248
|
+
if (typeof base === "object" && base && typeof override === "object" && override && !Array.isArray(base) && !Array.isArray(override)) {
|
|
249
|
+
const merged = { ...base };
|
|
250
|
+
for (const [key, value] of Object.entries(override)) {
|
|
251
|
+
merged[key] = key in merged ? mergeValues(merged[key], value) : value;
|
|
252
|
+
}
|
|
253
|
+
return merged;
|
|
254
|
+
}
|
|
255
|
+
return override;
|
|
256
|
+
}
|
|
257
|
+
export async function readYamlItems(root, relativeDir, options = {}) {
|
|
258
|
+
const targetRoot = relativeDir ? path.join(root, relativeDir) : root;
|
|
259
|
+
if (!(await fileExists(targetRoot))) {
|
|
260
|
+
return [];
|
|
261
|
+
}
|
|
262
|
+
const files = options.recursive
|
|
263
|
+
? await listFilesRecursive(targetRoot, ".yaml")
|
|
264
|
+
: (await readdir(targetRoot, { withFileTypes: true }))
|
|
265
|
+
.filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name))
|
|
266
|
+
.map((entry) => path.join(targetRoot, entry.name))
|
|
267
|
+
.sort();
|
|
268
|
+
const records = [];
|
|
269
|
+
for (const filePath of files) {
|
|
270
|
+
const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
|
|
271
|
+
for (const parsedDocument of parsedDocuments) {
|
|
272
|
+
for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
|
|
273
|
+
records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return records;
|
|
278
|
+
}
|
|
279
|
+
async function readNamedYamlItems(root, filenames) {
|
|
280
|
+
const records = [];
|
|
281
|
+
for (const filename of filenames) {
|
|
282
|
+
const filePath = path.join(root, filename);
|
|
283
|
+
if (!(await fileExists(filePath))) {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
|
|
287
|
+
for (const parsedDocument of parsedDocuments) {
|
|
288
|
+
for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
|
|
289
|
+
records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return records;
|
|
294
|
+
}
|
|
295
|
+
function isPrimaryAgentFile(sourcePath) {
|
|
296
|
+
const base = path.basename(sourcePath).toLowerCase();
|
|
297
|
+
return ROOT_AGENT_FILENAMES.includes(base);
|
|
298
|
+
}
|
|
299
|
+
function inferExecutionMode(item, current) {
|
|
300
|
+
const kind = typeof item.kind === "string" ? item.kind : typeof current?.kind === "string" ? current.kind : undefined;
|
|
301
|
+
if (kind === "langchain-agent") {
|
|
302
|
+
return "langchain-v1";
|
|
303
|
+
}
|
|
304
|
+
if (kind === "deepagent") {
|
|
305
|
+
return "deepagent";
|
|
306
|
+
}
|
|
307
|
+
return undefined;
|
|
308
|
+
}
|
|
309
|
+
function extractSharedAgentDefaults(item) {
|
|
310
|
+
const defaults = {};
|
|
311
|
+
for (const key of ["modelRef", "runRoot", "checkpointer", "interruptOn"]) {
|
|
312
|
+
if (key in item) {
|
|
313
|
+
defaults[key] = item[key];
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return defaults;
|
|
317
|
+
}
|
|
318
|
+
function applySharedAgentDefaults(globalDefaults, defaultsByMode, item, current) {
|
|
319
|
+
const executionMode = inferExecutionMode(item, current);
|
|
320
|
+
const defaults = {
|
|
321
|
+
...globalDefaults,
|
|
322
|
+
...(executionMode ? defaultsByMode[executionMode] : {}),
|
|
323
|
+
};
|
|
324
|
+
const merged = { ...item };
|
|
325
|
+
for (const [key, value] of Object.entries(defaults)) {
|
|
326
|
+
if (key in merged) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
if (current && key in current) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
merged[key] = value;
|
|
333
|
+
}
|
|
334
|
+
return merged;
|
|
335
|
+
}
|
|
336
|
+
export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
|
|
337
|
+
const refs = new Map();
|
|
338
|
+
const mergedAgents = new Map();
|
|
339
|
+
const mergedObjects = new Map();
|
|
340
|
+
const roots = [frameworkConfigRoot(), ...(options.overlayRoots ?? []), workspaceRoot];
|
|
341
|
+
let sharedAgentDefaults = {};
|
|
342
|
+
let sharedAgentDefaultsByMode = {};
|
|
343
|
+
for (const root of roots) {
|
|
344
|
+
for (const { item, sourcePath } of await readNamedYamlItems(root, [...ROOT_AGENT_FILENAMES])) {
|
|
345
|
+
const id = typeof item.id === "string" ? item.id : undefined;
|
|
346
|
+
if (!id) {
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const current = mergedAgents.get(id);
|
|
350
|
+
mergedAgents.set(id, {
|
|
351
|
+
item: current ? mergeValues(current.item, item) : item,
|
|
352
|
+
sourcePath,
|
|
353
|
+
});
|
|
354
|
+
const filename = path.basename(sourcePath).toLowerCase();
|
|
355
|
+
if (LEGACY_GLOBAL_AGENT_FILENAMES.includes(filename)) {
|
|
356
|
+
sharedAgentDefaults = mergeValues(sharedAgentDefaults, extractSharedAgentDefaults(item));
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
const executionMode = inferExecutionMode(item, current?.item);
|
|
360
|
+
if (executionMode) {
|
|
361
|
+
sharedAgentDefaultsByMode = {
|
|
362
|
+
...sharedAgentDefaultsByMode,
|
|
363
|
+
[executionMode]: mergeValues(sharedAgentDefaultsByMode[executionMode] ?? {}, extractSharedAgentDefaults(item)),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
for (const { item, sourcePath } of await readYamlItems(root, "agents", { recursive: true })) {
|
|
369
|
+
const id = typeof item.id === "string" ? item.id : undefined;
|
|
370
|
+
if (!id) {
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
const current = mergedAgents.get(id);
|
|
374
|
+
const itemWithDefaults = applySharedAgentDefaults(sharedAgentDefaults, sharedAgentDefaultsByMode, item, current?.item);
|
|
375
|
+
mergedAgents.set(id, {
|
|
376
|
+
item: current ? mergeValues(current.item, itemWithDefaults) : itemWithDefaults,
|
|
377
|
+
sourcePath,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
for (const { item, sourcePath } of (await readYamlItems(root)).filter(({ sourcePath: fullPath }) => !fullPath.includes(`${path.sep}agents${path.sep}`) && !isPrimaryAgentFile(fullPath))) {
|
|
381
|
+
const workspaceObject = parseWorkspaceObject(item, sourcePath);
|
|
382
|
+
if (!workspaceObject) {
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
|
|
386
|
+
const current = mergedObjects.get(ref);
|
|
387
|
+
mergedObjects.set(ref, {
|
|
388
|
+
item: current ? mergeValues(current.item, item) : item,
|
|
389
|
+
sourcePath,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
const agents = Array.from(mergedAgents.values()).map(({ item, sourcePath }) => parseAgentItem(item, sourcePath));
|
|
394
|
+
for (const [ref, { item, sourcePath }] of mergedObjects) {
|
|
395
|
+
const workspaceObject = parseWorkspaceObject(item, sourcePath);
|
|
396
|
+
if (!workspaceObject) {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
refs.set(ref, workspaceObject);
|
|
400
|
+
}
|
|
401
|
+
for (const agent of agents) {
|
|
402
|
+
refs.set(`agent/${agent.id}`, agent);
|
|
403
|
+
}
|
|
404
|
+
return { refs, agents };
|
|
405
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CompiledEmbeddingModel, CompiledModel, CompiledVectorStore, ParsedEmbeddingModelObject, ParsedVectorStoreObject, CompiledTool, ParsedModelObject, ParsedToolObject, WorkspaceObject } from "../contracts/types.js";
|
|
2
|
+
export declare function parseModelObject(object: WorkspaceObject): ParsedModelObject;
|
|
3
|
+
export declare function parseEmbeddingModelObject(object: WorkspaceObject): ParsedEmbeddingModelObject;
|
|
4
|
+
export declare function parseVectorStoreObject(object: WorkspaceObject): ParsedVectorStoreObject;
|
|
5
|
+
export declare function validateModelObject(model: ParsedModelObject, models: Map<string, ParsedModelObject>): void;
|
|
6
|
+
export declare function validateEmbeddingModelObject(model: ParsedEmbeddingModelObject): void;
|
|
7
|
+
export declare function validateVectorStoreObject(vectorStore: ParsedVectorStoreObject): void;
|
|
8
|
+
export declare function compileModel(model: ParsedModelObject): CompiledModel;
|
|
9
|
+
export declare function compileVectorStore(vectorStore: ParsedVectorStoreObject): CompiledVectorStore;
|
|
10
|
+
export declare function compileEmbeddingModel(model: ParsedEmbeddingModelObject): CompiledEmbeddingModel;
|
|
11
|
+
export declare function parseToolObject(object: WorkspaceObject): ParsedToolObject;
|
|
12
|
+
export declare function validateToolObject(tool: ParsedToolObject, tools: Map<string, ParsedToolObject>): void;
|
|
13
|
+
export declare function compileTool(tool: ParsedToolObject, tools: Map<string, ParsedToolObject>): CompiledTool[];
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { compileToolWithRegistry, validateToolWithRegistry } from "../extensions.js";
|
|
2
|
+
function asObject(value) {
|
|
3
|
+
return typeof value === "object" && value ? value : undefined;
|
|
4
|
+
}
|
|
5
|
+
function asStringArray(value) {
|
|
6
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
7
|
+
}
|
|
8
|
+
function asRefArray(value) {
|
|
9
|
+
return toArray(value)
|
|
10
|
+
.map((item) => typeof item === "string" ? item : typeof item === "object" && item && "ref" in item ? String(item.ref) : undefined)
|
|
11
|
+
.filter((item) => Boolean(item));
|
|
12
|
+
}
|
|
13
|
+
function toArray(value) {
|
|
14
|
+
return Array.isArray(value) ? value : [];
|
|
15
|
+
}
|
|
16
|
+
function parseHitlPolicy(value) {
|
|
17
|
+
const record = asObject(value);
|
|
18
|
+
if (!record) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const enabled = record.enabled === true;
|
|
22
|
+
const allow = Array.isArray(record.allow)
|
|
23
|
+
? record.allow.filter((item) => item === "approve" || item === "edit" || item === "reject")
|
|
24
|
+
: undefined;
|
|
25
|
+
return {
|
|
26
|
+
enabled,
|
|
27
|
+
allow: allow && allow.length > 0 ? allow : undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function parseModelObject(object) {
|
|
31
|
+
const value = object.value;
|
|
32
|
+
const provider = String(value.provider ?? "").trim();
|
|
33
|
+
const model = String((value.model ?? value.name) ?? "").trim();
|
|
34
|
+
const init = asObject(value.init) ?? {};
|
|
35
|
+
const fallbacks = Array.isArray(value.fallbacks)
|
|
36
|
+
? value.fallbacks
|
|
37
|
+
.map((item) => (typeof item === "object" && item && "ref" in item ? String(item.ref) : undefined))
|
|
38
|
+
.filter((item) => Boolean(item))
|
|
39
|
+
: [];
|
|
40
|
+
return {
|
|
41
|
+
id: object.id,
|
|
42
|
+
provider,
|
|
43
|
+
model,
|
|
44
|
+
init,
|
|
45
|
+
clientRef: typeof value.clientRef === "string" ? value.clientRef : undefined,
|
|
46
|
+
fallbacks,
|
|
47
|
+
metadata: asObject(value.metadata),
|
|
48
|
+
sourcePath: object.sourcePath,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function parseEmbeddingModelObject(object) {
|
|
52
|
+
const value = object.value;
|
|
53
|
+
const provider = String(value.provider ?? "").trim();
|
|
54
|
+
const model = String((value.model ?? value.name) ?? "").trim();
|
|
55
|
+
const init = asObject(value.init) ?? {};
|
|
56
|
+
return {
|
|
57
|
+
id: object.id,
|
|
58
|
+
provider,
|
|
59
|
+
model,
|
|
60
|
+
init,
|
|
61
|
+
clientRef: typeof value.clientRef === "string" ? value.clientRef : undefined,
|
|
62
|
+
metadata: asObject(value.metadata),
|
|
63
|
+
sourcePath: object.sourcePath,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function parseVectorStoreObject(object) {
|
|
67
|
+
const value = object.value;
|
|
68
|
+
return {
|
|
69
|
+
id: object.id,
|
|
70
|
+
kind: String(value.storeKind ?? value.kind ?? "LibSQLVectorStore").trim(),
|
|
71
|
+
url: typeof value.url === "string" ? value.url : undefined,
|
|
72
|
+
authToken: typeof value.authToken === "string" ? value.authToken : undefined,
|
|
73
|
+
table: typeof value.table === "string" ? value.table : undefined,
|
|
74
|
+
column: typeof value.column === "string" ? value.column : undefined,
|
|
75
|
+
embeddingModelRef: typeof value.embeddingModelRef === "string"
|
|
76
|
+
? value.embeddingModelRef
|
|
77
|
+
: typeof asObject(value.embeddingModel)?.ref === "string"
|
|
78
|
+
? String(asObject(value.embeddingModel)?.ref)
|
|
79
|
+
: undefined,
|
|
80
|
+
metadata: asObject(value.metadata),
|
|
81
|
+
sourcePath: object.sourcePath,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function validateModelObject(model, models) {
|
|
85
|
+
if (!model.provider) {
|
|
86
|
+
throw new Error(`Model ${model.id} provider must not be empty`);
|
|
87
|
+
}
|
|
88
|
+
if (!model.model) {
|
|
89
|
+
throw new Error(`Model ${model.id} model must not be empty`);
|
|
90
|
+
}
|
|
91
|
+
for (const fallback of model.fallbacks) {
|
|
92
|
+
const targetId = fallback.split("/").slice(1).join("/");
|
|
93
|
+
if (!models.has(targetId)) {
|
|
94
|
+
throw new Error(`Model ${model.id} fallback ${fallback} does not exist`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
export function validateEmbeddingModelObject(model) {
|
|
99
|
+
if (!model.provider) {
|
|
100
|
+
throw new Error(`Embedding model ${model.id} provider must not be empty`);
|
|
101
|
+
}
|
|
102
|
+
if (!model.model) {
|
|
103
|
+
throw new Error(`Embedding model ${model.id} model must not be empty`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
export function validateVectorStoreObject(vectorStore) {
|
|
107
|
+
if (!vectorStore.kind) {
|
|
108
|
+
throw new Error(`Vector store ${vectorStore.id} kind must not be empty`);
|
|
109
|
+
}
|
|
110
|
+
if ((vectorStore.kind === "LibSQLVectorStore" || vectorStore.kind === "LlamaIndexSimpleVectorStore") && !vectorStore.url) {
|
|
111
|
+
throw new Error(`Vector store ${vectorStore.id} url must not be empty for ${vectorStore.kind}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export function compileModel(model) {
|
|
115
|
+
return {
|
|
116
|
+
id: model.id,
|
|
117
|
+
provider: model.provider,
|
|
118
|
+
model: model.model,
|
|
119
|
+
init: model.init,
|
|
120
|
+
clientRef: model.clientRef,
|
|
121
|
+
fallbacks: model.fallbacks,
|
|
122
|
+
runtimeValue: `${model.provider}:${model.model}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export function compileVectorStore(vectorStore) {
|
|
126
|
+
return {
|
|
127
|
+
id: vectorStore.id,
|
|
128
|
+
kind: vectorStore.kind,
|
|
129
|
+
url: vectorStore.url,
|
|
130
|
+
authToken: vectorStore.authToken,
|
|
131
|
+
table: vectorStore.table,
|
|
132
|
+
column: vectorStore.column,
|
|
133
|
+
embeddingModelRef: vectorStore.embeddingModelRef,
|
|
134
|
+
runtimeValue: vectorStore.kind,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
export function compileEmbeddingModel(model) {
|
|
138
|
+
return {
|
|
139
|
+
id: model.id,
|
|
140
|
+
provider: model.provider,
|
|
141
|
+
model: model.model,
|
|
142
|
+
init: model.init,
|
|
143
|
+
clientRef: model.clientRef,
|
|
144
|
+
runtimeValue: `${model.provider}:${model.model}`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
export function parseToolObject(object) {
|
|
148
|
+
const value = object.value;
|
|
149
|
+
const backend = asObject(value.backend);
|
|
150
|
+
const mcp = asObject(value.mcp);
|
|
151
|
+
const bundleRefs = asRefArray(value.refs ?? value.bundle);
|
|
152
|
+
const inferredType = typeof value.type === "string"
|
|
153
|
+
? value.type
|
|
154
|
+
: bundleRefs.length > 0
|
|
155
|
+
? "bundle"
|
|
156
|
+
: backend || mcp
|
|
157
|
+
? "backend"
|
|
158
|
+
: "function";
|
|
159
|
+
return {
|
|
160
|
+
id: object.id,
|
|
161
|
+
type: String(inferredType),
|
|
162
|
+
name: String(value.name ?? "").trim(),
|
|
163
|
+
description: String(value.description ?? "").trim(),
|
|
164
|
+
config: asObject(value.config),
|
|
165
|
+
inputSchemaRef: typeof asObject(value.inputSchema)?.ref === "string" ? String(asObject(value.inputSchema)?.ref) : undefined,
|
|
166
|
+
backendOperation: typeof backend?.operation === "string"
|
|
167
|
+
? backend.operation
|
|
168
|
+
: typeof value.operation === "string"
|
|
169
|
+
? value.operation
|
|
170
|
+
: undefined,
|
|
171
|
+
mcpRef: typeof mcp?.ref === "string" ? mcp.ref : undefined,
|
|
172
|
+
bundleRefs,
|
|
173
|
+
hitl: parseHitlPolicy(value.hitl),
|
|
174
|
+
sourcePath: object.sourcePath,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
export function validateToolObject(tool, tools) {
|
|
178
|
+
validateToolWithRegistry(tool, tools);
|
|
179
|
+
}
|
|
180
|
+
export function compileTool(tool, tools) {
|
|
181
|
+
return compileToolWithRegistry(tool, tools);
|
|
182
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ParsedAgentObject } from "../../contracts/types.js";
|
|
2
|
+
export declare function ensureDiscoverySources(locators: string[], workspaceRoot: string): Promise<void>;
|
|
3
|
+
export declare function resolveDiscoveryRoot(ref: string, workspaceRoot: string, kind: "skills" | "subagents"): string;
|
|
4
|
+
export declare function discoverSkillPaths(rootRefs: string[], workspaceRoot: string): string[];
|
|
5
|
+
export declare function discoverSubagents(agents: ParsedAgentObject[], workspaceRoot: string): Promise<ParsedAgentObject[]>;
|