@botbotgo/agent-harness 0.0.22 → 0.0.24

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.
@@ -1,15 +1,12 @@
1
- import path from "node:path";
2
- import { createHash } from "node:crypto";
3
- import { ensureResourceSources, listResourceTools, listResourceToolsForSource } from "../resource/resource.js";
4
- import { listRemoteMcpTools } from "../resource/resource-impl.js";
5
- import { ensureExternalResourceSource, isExternalSourceLocator } from "../resource/sources.js";
6
- import { loadWorkspaceObjects, readToolModuleItems } from "./object-loader.js";
1
+ import { ensureResourceSources } from "../resource/resource.js";
2
+ import { loadWorkspaceObjects } from "./object-loader.js";
7
3
  import { parseEmbeddingModelObject, parseMcpServerObject, parseModelObject, parseToolObject, parseVectorStoreObject, validateEmbeddingModelObject, validateMcpServerObject, validateModelObject, validateToolObject, validateVectorStoreObject, } from "./resource-compilers.js";
8
4
  import { validateAgent, validateTopology } from "./validate.js";
9
5
  import { compileBinding } from "./agent-binding-compiler.js";
10
6
  import { discoverSubagents, ensureDiscoverySources } from "./support/discovery.js";
11
7
  import { collectAgentDiscoverySourceRefs, collectToolSourceRefs } from "./support/source-collectors.js";
12
8
  import { resolveRefId } from "./support/workspace-ref-utils.js";
9
+ import { hydrateAgentMcpTools, hydrateResourceAndExternalTools } from "./tool-hydration.js";
13
10
  function collectParsedResources(refs) {
14
11
  const embeddings = new Map();
15
12
  const mcpServers = new Map();
@@ -39,154 +36,6 @@ function collectParsedResources(refs) {
39
36
  }
40
37
  return { embeddings, mcpServers, models, vectorStores, tools };
41
38
  }
42
- async function hydrateResourceAndExternalTools(tools, toolSourceRefs, workspaceRoot) {
43
- for (const source of toolSourceRefs) {
44
- if (isExternalSourceLocator(source)) {
45
- const externalRoot = await ensureExternalResourceSource(source, workspaceRoot);
46
- const discoveredToolRefs = [];
47
- const sourcePrefix = `external.${createHash("sha256").update(source).digest("hex").slice(0, 12)}`;
48
- for (const { item, sourcePath } of await readToolModuleItems(path.join(externalRoot, "tools"))) {
49
- const toolId = typeof item.id === "string" ? item.id : undefined;
50
- if (!toolId) {
51
- continue;
52
- }
53
- const namespacedId = `${sourcePrefix}.${toolId}`;
54
- const parsed = parseToolObject({
55
- id: namespacedId,
56
- kind: "tool",
57
- sourcePath,
58
- value: {
59
- ...item,
60
- id: namespacedId,
61
- },
62
- });
63
- tools.set(parsed.id, parsed);
64
- discoveredToolRefs.push(`tool/${parsed.id}`);
65
- }
66
- const sourceTools = await listResourceToolsForSource(source, workspaceRoot);
67
- const bundleRefs = [...sourceTools.map((tool) => tool.toolPath), ...discoveredToolRefs];
68
- if (bundleRefs.length > 0) {
69
- tools.set(source, {
70
- id: source,
71
- type: "bundle",
72
- name: source,
73
- description: `External tool resource loaded from ${source}`,
74
- bundleRefs,
75
- sourcePath: source,
76
- });
77
- }
78
- }
79
- }
80
- for (const resourceTool of await listResourceTools(toolSourceRefs, workspaceRoot)) {
81
- const existing = tools.get(resourceTool.toolPath);
82
- tools.set(resourceTool.toolPath, {
83
- id: resourceTool.toolPath,
84
- type: existing?.type ?? "backend",
85
- name: existing?.name || resourceTool.name,
86
- description: existing?.description || resourceTool.description,
87
- config: existing?.config,
88
- backendOperation: existing?.backendOperation ?? resourceTool.backendOperation,
89
- bundleRefs: existing?.bundleRefs ?? [],
90
- hitl: existing?.hitl ?? resourceTool.hitl,
91
- sourcePath: existing?.sourcePath ?? resourceTool.toolPath,
92
- });
93
- }
94
- }
95
- function toMcpServerConfig(server) {
96
- return {
97
- transport: server.transport,
98
- command: server.command,
99
- args: server.args,
100
- env: server.env,
101
- cwd: server.cwd,
102
- url: server.url,
103
- token: server.token,
104
- headers: server.headers,
105
- };
106
- }
107
- function readStringArray(value) {
108
- return Array.isArray(value) ? value.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
109
- }
110
- function compileRegexList(value, label) {
111
- return readStringArray(value).map((pattern) => {
112
- try {
113
- return new RegExp(pattern);
114
- }
115
- catch (error) {
116
- throw new Error(`${label} contains invalid regex ${JSON.stringify(pattern)}: ${error instanceof Error ? error.message : String(error)}`);
117
- }
118
- });
119
- }
120
- function compileMcpToolFilter(serverItem) {
121
- return {
122
- includeNames: new Set(readStringArray(serverItem.tools)),
123
- excludeNames: new Set(readStringArray(serverItem.excludeTools)),
124
- includePatterns: compileRegexList(serverItem.toolFilters ?? serverItem.toolFilter, "toolFilter"),
125
- excludePatterns: compileRegexList(serverItem.excludeToolFilters ?? serverItem.excludeToolFilter, "excludeToolFilter"),
126
- };
127
- }
128
- function shouldIncludeRemoteMcpTool(filter, toolName) {
129
- const { includeNames, excludeNames, includePatterns, excludePatterns } = filter;
130
- const includedByName = includeNames.size === 0 || includeNames.has(toolName);
131
- const includedByPattern = includePatterns.length === 0 || includePatterns.some((pattern) => pattern.test(toolName));
132
- if (!includedByName || !includedByPattern) {
133
- return false;
134
- }
135
- if (excludeNames.has(toolName)) {
136
- return false;
137
- }
138
- if (excludePatterns.some((pattern) => pattern.test(toolName))) {
139
- return false;
140
- }
141
- return true;
142
- }
143
- async function hydrateAgentMcpTools(agents, mcpServers, tools) {
144
- for (const agent of agents) {
145
- const discoveredRefs = new Set(agent.toolRefs);
146
- for (const item of agent.mcpServers ?? []) {
147
- const name = typeof item.name === "string" && item.name.trim()
148
- ? item.name.trim()
149
- : typeof item.id === "string" && item.id.trim()
150
- ? item.id.trim()
151
- : "";
152
- if (!name) {
153
- throw new Error(`Agent ${agent.id} has an MCP server entry without a name`);
154
- }
155
- const serverId = `${agent.id}.${name}`;
156
- const parsedServer = parseMcpServerObject({
157
- id: serverId,
158
- kind: "mcp",
159
- sourcePath: agent.sourcePath,
160
- value: item,
161
- });
162
- const filter = compileMcpToolFilter(item);
163
- mcpServers.set(serverId, parsedServer);
164
- const remoteTools = await listRemoteMcpTools(toMcpServerConfig(parsedServer));
165
- for (const remoteTool of remoteTools) {
166
- if (!shouldIncludeRemoteMcpTool(filter, remoteTool.name)) {
167
- continue;
168
- }
169
- const toolId = `mcp.${agent.id}.${name}.${remoteTool.name}`;
170
- tools.set(toolId, {
171
- id: toolId,
172
- type: "mcp",
173
- name: remoteTool.name,
174
- description: remoteTool.description ?? remoteTool.name,
175
- config: {
176
- mcp: {
177
- serverRef: `mcp/${serverId}`,
178
- },
179
- },
180
- mcpRef: remoteTool.name,
181
- bundleRefs: [],
182
- sourcePath: agent.sourcePath,
183
- });
184
- discoveredRefs.add(`tool/${toolId}`);
185
- }
186
- }
187
- agent.toolRefs = Array.from(discoveredRefs);
188
- }
189
- }
190
39
  function validateWorkspaceResources(embeddings, mcpServers, models, vectorStores, tools, agents) {
191
40
  embeddings.forEach((embedding) => validateEmbeddingModelObject(embedding));
192
41
  mcpServers.forEach((server) => validateMcpServerObject(server));
@@ -7,18 +7,7 @@ import { resolveIsolatedResourceModulePath } from "../resource/isolation.js";
7
7
  import { resolveResourcePackageRoot } from "../resource/sources.js";
8
8
  import { discoverToolModuleDefinitions, isSupportedToolModulePath } from "../tool-modules.js";
9
9
  import { fileExists, listFilesRecursive, readYamlOrJson } from "../utils/fs.js";
10
- const ROOT_AGENT_FILENAMES = [
11
- "agent.yaml",
12
- "agent.yml",
13
- "orchestra.yaml",
14
- "orchestra.yml",
15
- "direct.yaml",
16
- "direct.yml",
17
- "research.yaml",
18
- "research.yml",
19
- ];
20
10
  const MODEL_FILENAMES = ["models.yaml", "models.yml"];
21
- const LEGACY_GLOBAL_AGENT_FILENAMES = ["agent.yaml", "agent.yml"];
22
11
  const CONVENTIONAL_OBJECT_DIRECTORIES = ["tools"];
23
12
  function conventionalConfigRoot(root) {
24
13
  if (path.basename(root) === "config" && existsSync(root) && statSync(root).isDirectory()) {
@@ -220,6 +209,27 @@ function readObjectArray(items) {
220
209
  .map((item) => ({ ...item }));
221
210
  return records.length > 0 ? records : undefined;
222
211
  }
212
+ function readSharedAgentConfig(item) {
213
+ const middleware = readMiddlewareArray(item.middleware);
214
+ return {
215
+ ...(typeof item.systemPrompt === "string" ? { systemPrompt: item.systemPrompt } : {}),
216
+ ...(typeof item.checkpointer === "object" && item.checkpointer ? { checkpointer: item.checkpointer } : {}),
217
+ ...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
218
+ ...(item.responseFormat !== undefined ? { responseFormat: item.responseFormat } : {}),
219
+ ...(item.contextSchema !== undefined ? { contextSchema: item.contextSchema } : {}),
220
+ ...(middleware ? { middleware } : {}),
221
+ };
222
+ }
223
+ function readLangchainAgentConfig(item) {
224
+ return readSharedAgentConfig(item);
225
+ }
226
+ function readDeepAgentConfig(item) {
227
+ return {
228
+ ...readSharedAgentConfig(item),
229
+ ...(typeof item.backend === "object" && item.backend ? { backend: item.backend } : {}),
230
+ ...(typeof item.store === "object" && item.store ? { store: item.store } : {}),
231
+ };
232
+ }
223
233
  export function parseAgentItem(item, sourcePath) {
224
234
  const subagentRefs = readRefArray(item.subagents);
225
235
  const subagentPathRefs = readPathArray(item.subagents);
@@ -239,44 +249,8 @@ export function parseAgentItem(item, sourcePath) {
239
249
  memorySources: readPathArray(item.memory),
240
250
  subagentRefs,
241
251
  subagentPathRefs,
242
- langchainAgentConfig: {
243
- ...(typeof item.systemPrompt === "string" ||
244
- typeof item.interruptOn === "object" ||
245
- typeof item.checkpointer === "object" ||
246
- item.responseFormat !== undefined ||
247
- item.contextSchema !== undefined ||
248
- item.middleware !== undefined
249
- ? {
250
- ...(typeof item.systemPrompt === "string" ? { systemPrompt: item.systemPrompt } : {}),
251
- ...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
252
- ...(typeof item.checkpointer === "object" && item.checkpointer ? { checkpointer: item.checkpointer } : {}),
253
- ...(item.responseFormat !== undefined ? { responseFormat: item.responseFormat } : {}),
254
- ...(item.contextSchema !== undefined ? { contextSchema: item.contextSchema } : {}),
255
- ...(readMiddlewareArray(item.middleware) ? { middleware: readMiddlewareArray(item.middleware) } : {}),
256
- }
257
- : {}),
258
- },
259
- deepAgentConfig: {
260
- ...(typeof item.systemPrompt === "string" ||
261
- typeof item.backend === "object" ||
262
- typeof item.store === "object" ||
263
- typeof item.checkpointer === "object" ||
264
- typeof item.interruptOn === "object" ||
265
- item.responseFormat !== undefined ||
266
- item.contextSchema !== undefined ||
267
- item.middleware !== undefined
268
- ? {
269
- ...(typeof item.systemPrompt === "string" ? { systemPrompt: item.systemPrompt } : {}),
270
- ...(typeof item.backend === "object" && item.backend ? { backend: item.backend } : {}),
271
- ...(typeof item.store === "object" && item.store ? { store: item.store } : {}),
272
- ...(typeof item.checkpointer === "object" && item.checkpointer ? { checkpointer: item.checkpointer } : {}),
273
- ...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
274
- ...(item.responseFormat !== undefined ? { responseFormat: item.responseFormat } : {}),
275
- ...(item.contextSchema !== undefined ? { contextSchema: item.contextSchema } : {}),
276
- ...(readMiddlewareArray(item.middleware) ? { middleware: readMiddlewareArray(item.middleware) } : {}),
277
- }
278
- : {}),
279
- },
252
+ langchainAgentConfig: readLangchainAgentConfig(item),
253
+ deepAgentConfig: readDeepAgentConfig(item),
280
254
  sourcePath,
281
255
  };
282
256
  }
@@ -346,6 +320,89 @@ function mergeValues(base, override) {
346
320
  }
347
321
  return override;
348
322
  }
323
+ function mergeRawItemRecord(records, key, item, sourcePath) {
324
+ const current = records.get(key);
325
+ const mergedRecord = {
326
+ item: current ? mergeValues(current.item, item) : item,
327
+ sourcePath,
328
+ };
329
+ records.set(key, mergedRecord);
330
+ return mergedRecord;
331
+ }
332
+ function mergeAgentRecord(records, item, sourcePath) {
333
+ const id = typeof item.id === "string" ? item.id : undefined;
334
+ if (!id) {
335
+ return null;
336
+ }
337
+ return mergeRawItemRecord(records, id, item, sourcePath);
338
+ }
339
+ function mergeWorkspaceObjectRecord(records, workspaceObject, item, sourcePath) {
340
+ mergeRawItemRecord(records, `${workspaceObject.kind}/${workspaceObject.id}`, item, sourcePath);
341
+ }
342
+ async function loadNamedModelsForRoot(configRoot, mergedObjects) {
343
+ for (const { item, sourcePath } of await readNamedModelItems(configRoot)) {
344
+ const workspaceObject = parseWorkspaceObject(item, sourcePath);
345
+ if (!workspaceObject || workspaceObject.kind !== "model") {
346
+ continue;
347
+ }
348
+ mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
349
+ }
350
+ }
351
+ async function loadConfigAgentsForRoot(configRoot, mergedAgents) {
352
+ for (const { item, sourcePath } of await readConfigAgentItems(configRoot)) {
353
+ mergeAgentRecord(mergedAgents, item, sourcePath);
354
+ }
355
+ }
356
+ async function loadConventionalObjectsForRoot(root, mergedObjects) {
357
+ for (const directory of CONVENTIONAL_OBJECT_DIRECTORIES) {
358
+ for (const objectRoot of conventionalDirectoryRoots(root, directory)) {
359
+ for (const { item, sourcePath } of await readYamlItems(objectRoot, undefined, { recursive: true })) {
360
+ const workspaceObject = parseWorkspaceObject(item, sourcePath);
361
+ if (!workspaceObject || workspaceObject.kind === "tool") {
362
+ continue;
363
+ }
364
+ mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
365
+ }
366
+ for (const { item, sourcePath } of await readToolModuleItems(objectRoot)) {
367
+ const workspaceObject = parseWorkspaceObject(item, sourcePath);
368
+ if (!workspaceObject) {
369
+ continue;
370
+ }
371
+ mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
372
+ }
373
+ }
374
+ }
375
+ }
376
+ async function loadConfigObjectsForRoot(root, configRoot, mergedObjects) {
377
+ if (!conventionalConfigRoot(root)) {
378
+ return;
379
+ }
380
+ for (const { item, sourcePath } of await readYamlItems(configRoot, undefined, { recursive: true })) {
381
+ const workspaceObject = parseWorkspaceObject(item, sourcePath);
382
+ if (!workspaceObject) {
383
+ continue;
384
+ }
385
+ if (isAgentKind(workspaceObject.kind) || workspaceObject.kind === "model") {
386
+ continue;
387
+ }
388
+ mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
389
+ }
390
+ }
391
+ async function loadRootObjects(root, mergedObjects) {
392
+ for (const { item, sourcePath } of (await readYamlItems(root)).filter(({ sourcePath: fullPath }) => !fullPath.includes(`${path.sep}config${path.sep}`) &&
393
+ !fullPath.includes(`${path.sep}resources${path.sep}`) &&
394
+ !fullPath.includes(`${path.sep}agents${path.sep}`) &&
395
+ !CONVENTIONAL_OBJECT_DIRECTORIES.some((directory) => fullPath.includes(`${path.sep}${directory}${path.sep}`)))) {
396
+ const workspaceObject = parseWorkspaceObject(item, sourcePath);
397
+ if (!workspaceObject) {
398
+ continue;
399
+ }
400
+ if (workspaceObject.kind === "tool" || workspaceObject.kind === "mcp" || workspaceObject.kind === "model") {
401
+ continue;
402
+ }
403
+ mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
404
+ }
405
+ }
349
406
  export async function readYamlItems(root, relativeDir, options = {}) {
350
407
  const targetRoot = relativeDir ? path.join(root, relativeDir) : root;
351
408
  if (!(await fileExists(targetRoot))) {
@@ -405,15 +462,13 @@ function isAgentKind(kind) {
405
462
  return kind === "deepagent" || kind === "langchain-agent";
406
463
  }
407
464
  async function readConfigAgentItems(configRoot) {
408
- const records = await readYamlItems(configRoot, undefined, { recursive: true });
465
+ const records = await readYamlItems(configRoot, "agents", { recursive: true });
409
466
  return records.filter(({ item, sourcePath }) => {
410
467
  const kind = typeof item.kind === "string" ? item.kind : undefined;
411
468
  if (!isAgentKind(kind)) {
412
469
  return false;
413
470
  }
414
- const parentDir = path.dirname(sourcePath);
415
- const filename = path.basename(sourcePath).toLowerCase();
416
- return !(parentDir === configRoot && ROOT_AGENT_FILENAMES.includes(filename));
471
+ return sourcePath.includes(`${path.sep}agents${path.sep}`);
417
472
  });
418
473
  }
419
474
  export async function readToolModuleItems(root) {
@@ -451,10 +506,6 @@ export async function readToolModuleItems(root) {
451
506
  }
452
507
  return records;
453
508
  }
454
- function isPrimaryAgentFile(sourcePath) {
455
- const base = path.basename(sourcePath).toLowerCase();
456
- return ROOT_AGENT_FILENAMES.includes(base);
457
- }
458
509
  function inferExecutionMode(item, current) {
459
510
  const kind = typeof item.kind === "string" ? item.kind : typeof current?.kind === "string" ? current.kind : undefined;
460
511
  if (kind === "langchain-agent") {
@@ -465,160 +516,18 @@ function inferExecutionMode(item, current) {
465
516
  }
466
517
  return undefined;
467
518
  }
468
- function extractSharedAgentDefaults(item) {
469
- const defaults = {};
470
- for (const key of ["modelRef", "runRoot", "checkpointer", "interruptOn"]) {
471
- if (key in item) {
472
- defaults[key] = item[key];
473
- }
474
- }
475
- return defaults;
476
- }
477
- function applySharedAgentDefaults(globalDefaults, defaultsByMode, item, current) {
478
- const executionMode = inferExecutionMode(item, current);
479
- const defaults = {
480
- ...globalDefaults,
481
- ...(executionMode ? defaultsByMode[executionMode] : {}),
482
- };
483
- const merged = { ...item };
484
- for (const [key, value] of Object.entries(defaults)) {
485
- if (key in merged) {
486
- continue;
487
- }
488
- if (current && key in current) {
489
- continue;
490
- }
491
- merged[key] = value;
492
- }
493
- return merged;
494
- }
495
519
  export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
496
520
  const refs = new Map();
497
521
  const mergedAgents = new Map();
498
522
  const mergedObjects = new Map();
499
523
  const roots = [frameworkWorkspaceRoot(), ...(options.overlayRoots ?? []), workspaceRoot];
500
- let sharedAgentDefaults = {};
501
- let sharedAgentDefaultsByMode = {};
502
524
  for (const root of roots) {
503
525
  const configRoot = conventionalConfigRoot(root) ?? root;
504
- const namedAgentRoots = Array.from(new Set([root, configRoot]));
505
- for (const namedAgentRoot of namedAgentRoots) {
506
- for (const { item, sourcePath } of await readNamedYamlItems(namedAgentRoot, [...ROOT_AGENT_FILENAMES])) {
507
- const id = typeof item.id === "string" ? item.id : undefined;
508
- if (!id) {
509
- continue;
510
- }
511
- const current = mergedAgents.get(id);
512
- mergedAgents.set(id, {
513
- item: current ? mergeValues(current.item, item) : item,
514
- sourcePath,
515
- });
516
- const filename = path.basename(sourcePath).toLowerCase();
517
- if (LEGACY_GLOBAL_AGENT_FILENAMES.includes(filename)) {
518
- sharedAgentDefaults = mergeValues(sharedAgentDefaults, extractSharedAgentDefaults(item));
519
- }
520
- else {
521
- const executionMode = inferExecutionMode(item, current?.item);
522
- if (executionMode) {
523
- sharedAgentDefaultsByMode = {
524
- ...sharedAgentDefaultsByMode,
525
- [executionMode]: mergeValues(sharedAgentDefaultsByMode[executionMode] ?? {}, extractSharedAgentDefaults(item)),
526
- };
527
- }
528
- }
529
- }
530
- }
531
- for (const modelRoot of Array.from(new Set([configRoot]))) {
532
- for (const { item, sourcePath } of await readNamedModelItems(modelRoot)) {
533
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
534
- if (!workspaceObject || workspaceObject.kind !== "model") {
535
- continue;
536
- }
537
- const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
538
- const current = mergedObjects.get(ref);
539
- mergedObjects.set(ref, {
540
- item: current ? mergeValues(current.item, item) : item,
541
- sourcePath,
542
- });
543
- }
544
- }
545
- for (const { item, sourcePath } of await readConfigAgentItems(configRoot)) {
546
- const id = typeof item.id === "string" ? item.id : undefined;
547
- if (!id) {
548
- continue;
549
- }
550
- const current = mergedAgents.get(id);
551
- const itemWithDefaults = applySharedAgentDefaults(sharedAgentDefaults, sharedAgentDefaultsByMode, item, current?.item);
552
- mergedAgents.set(id, {
553
- item: current ? mergeValues(current.item, itemWithDefaults) : itemWithDefaults,
554
- sourcePath,
555
- });
556
- }
557
- for (const directory of CONVENTIONAL_OBJECT_DIRECTORIES) {
558
- for (const objectRoot of conventionalDirectoryRoots(root, directory)) {
559
- for (const { item, sourcePath } of await readYamlItems(objectRoot, undefined, { recursive: true })) {
560
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
561
- if (!workspaceObject || workspaceObject.kind === "tool") {
562
- continue;
563
- }
564
- const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
565
- const current = mergedObjects.get(ref);
566
- mergedObjects.set(ref, {
567
- item: current ? mergeValues(current.item, item) : item,
568
- sourcePath,
569
- });
570
- }
571
- for (const { item, sourcePath } of await readToolModuleItems(objectRoot)) {
572
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
573
- if (!workspaceObject) {
574
- continue;
575
- }
576
- const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
577
- const current = mergedObjects.get(ref);
578
- mergedObjects.set(ref, {
579
- item: current ? mergeValues(current.item, item) : item,
580
- sourcePath,
581
- });
582
- }
583
- }
584
- }
585
- if (conventionalConfigRoot(root)) {
586
- for (const { item, sourcePath } of await readYamlItems(configRoot, undefined, { recursive: true })) {
587
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
588
- if (!workspaceObject) {
589
- continue;
590
- }
591
- if (isAgentKind(workspaceObject.kind) ||
592
- workspaceObject.kind === "model") {
593
- continue;
594
- }
595
- const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
596
- const current = mergedObjects.get(ref);
597
- mergedObjects.set(ref, {
598
- item: current ? mergeValues(current.item, item) : item,
599
- sourcePath,
600
- });
601
- }
602
- }
603
- for (const { item, sourcePath } of (await readYamlItems(root)).filter(({ sourcePath: fullPath }) => !fullPath.includes(`${path.sep}config${path.sep}`) &&
604
- !fullPath.includes(`${path.sep}resources${path.sep}`) &&
605
- !fullPath.includes(`${path.sep}agents${path.sep}`) &&
606
- !CONVENTIONAL_OBJECT_DIRECTORIES.some((directory) => fullPath.includes(`${path.sep}${directory}${path.sep}`)) &&
607
- !isPrimaryAgentFile(fullPath))) {
608
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
609
- if (!workspaceObject) {
610
- continue;
611
- }
612
- if (workspaceObject.kind === "tool" || workspaceObject.kind === "mcp" || workspaceObject.kind === "model") {
613
- continue;
614
- }
615
- const ref = `${workspaceObject.kind}/${workspaceObject.id}`;
616
- const current = mergedObjects.get(ref);
617
- mergedObjects.set(ref, {
618
- item: current ? mergeValues(current.item, item) : item,
619
- sourcePath,
620
- });
621
- }
526
+ await loadNamedModelsForRoot(configRoot, mergedObjects);
527
+ await loadConfigAgentsForRoot(configRoot, mergedAgents);
528
+ await loadConventionalObjectsForRoot(root, mergedObjects);
529
+ await loadConfigObjectsForRoot(root, configRoot, mergedObjects);
530
+ await loadRootObjects(root, mergedObjects);
622
531
  }
623
532
  const agents = Array.from(mergedAgents.values()).map(({ item, sourcePath }) => parseAgentItem(item, sourcePath));
624
533
  for (const [ref, { item, sourcePath }] of mergedObjects) {
@@ -0,0 +1,3 @@
1
+ import type { ParsedAgentObject, ParsedMcpServerObject, ParsedToolObject } from "../contracts/types.js";
2
+ export declare function hydrateResourceAndExternalTools(tools: Map<string, ParsedToolObject>, toolSourceRefs: string[], workspaceRoot: string): Promise<void>;
3
+ export declare function hydrateAgentMcpTools(agents: ParsedAgentObject[], mcpServers: Map<string, ParsedMcpServerObject>, tools: Map<string, ParsedToolObject>): Promise<void>;