@botbotgo/agent-harness 0.0.100 → 0.0.102

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.
Files changed (40) hide show
  1. package/dist/package-version.d.ts +1 -1
  2. package/dist/package-version.js +1 -1
  3. package/dist/persistence/sqlite-run-context-store.d.ts +22 -0
  4. package/dist/persistence/sqlite-run-context-store.js +64 -0
  5. package/dist/persistence/sqlite-run-queue-store.d.ts +41 -0
  6. package/dist/persistence/sqlite-run-queue-store.js +120 -0
  7. package/dist/persistence/sqlite-store.d.ts +2 -2
  8. package/dist/persistence/sqlite-store.js +31 -117
  9. package/dist/resource/mcp-tool-support.d.ts +21 -0
  10. package/dist/resource/mcp-tool-support.js +173 -0
  11. package/dist/resource/resource-impl.d.ts +1 -18
  12. package/dist/resource/resource-impl.js +79 -240
  13. package/dist/runtime/adapter/invoke-runtime.d.ts +22 -0
  14. package/dist/runtime/adapter/invoke-runtime.js +18 -0
  15. package/dist/runtime/adapter/stream-runtime.d.ts +46 -0
  16. package/dist/runtime/adapter/stream-runtime.js +93 -0
  17. package/dist/runtime/agent-runtime-adapter.d.ts +1 -12
  18. package/dist/runtime/agent-runtime-adapter.js +122 -312
  19. package/dist/runtime/harness/run/recovery.d.ts +42 -0
  20. package/dist/runtime/harness/run/recovery.js +139 -0
  21. package/dist/runtime/harness/run/run-operations.d.ts +50 -0
  22. package/dist/runtime/harness/run/run-operations.js +113 -0
  23. package/dist/runtime/harness/run/run-slot-acquisition.d.ts +64 -0
  24. package/dist/runtime/harness/run/run-slot-acquisition.js +157 -0
  25. package/dist/runtime/harness/run/stream-run.d.ts +53 -0
  26. package/dist/runtime/harness/run/stream-run.js +304 -0
  27. package/dist/runtime/harness.d.ts +2 -17
  28. package/dist/runtime/harness.js +157 -773
  29. package/dist/runtime/support/runtime-factories.js +2 -2
  30. package/dist/workspace/object-loader.d.ts +1 -8
  31. package/dist/workspace/object-loader.js +43 -275
  32. package/dist/workspace/yaml-object-reader.d.ts +15 -0
  33. package/dist/workspace/yaml-object-reader.js +202 -0
  34. package/package.json +1 -1
  35. package/dist/runtime/checkpoint-maintenance.d.ts +0 -1
  36. package/dist/runtime/checkpoint-maintenance.js +0 -1
  37. package/dist/runtime/file-checkpoint-saver.d.ts +0 -1
  38. package/dist/runtime/file-checkpoint-saver.js +0 -1
  39. package/dist/runtime/sqlite-maintained-checkpoint-saver.d.ts +0 -1
  40. package/dist/runtime/sqlite-maintained-checkpoint-saver.js +0 -1
@@ -1,8 +1,8 @@
1
1
  import path from "node:path";
2
2
  import { MemorySaver } from "@langchain/langgraph";
3
3
  import { SqliteSaver } from "@langchain/langgraph-checkpoint-sqlite";
4
- import { FileCheckpointSaver } from "../file-checkpoint-saver.js";
5
- import { ManagedSqliteSaver } from "../sqlite-maintained-checkpoint-saver.js";
4
+ import { FileCheckpointSaver } from "../maintenance/file-checkpoint-saver.js";
5
+ import { ManagedSqliteSaver } from "../maintenance/sqlite-maintained-checkpoint-saver.js";
6
6
  import { createInMemoryStore, FileBackedStore } from "../harness/system/store.js";
7
7
  export function createStoreForConfig(storeConfig, runRoot) {
8
8
  const kind = typeof storeConfig.kind === "string" ? storeConfig.kind : "FileStore";
@@ -1,18 +1,12 @@
1
1
  import type { ParsedAgentObject, WorkspaceLoadOptions, WorkspaceObject } from "../contracts/types.js";
2
+ export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
2
3
  type RefMap = Map<string, WorkspaceObject | ParsedAgentObject>;
3
4
  export type WorkspaceObjects = {
4
5
  refs: RefMap;
5
6
  agents: ParsedAgentObject[];
6
7
  };
7
8
  export declare function conventionalPackageRoots(root: string, relativeDir: "tools" | "skills"): string[];
8
- export declare function normalizeYamlItem(item: Record<string, unknown>): Record<string, unknown>;
9
9
  export declare function parseAgentItem(item: Record<string, unknown>, sourcePath: string): ParsedAgentObject;
10
- export declare function readYamlItems(root: string, relativeDir?: string, options?: {
11
- recursive?: boolean;
12
- }): Promise<Array<{
13
- item: Record<string, unknown>;
14
- sourcePath: string;
15
- }>>;
16
10
  export declare function readToolModuleItems(root: string): Promise<Array<{
17
11
  item: Record<string, unknown>;
18
12
  sourcePath: string;
@@ -30,4 +24,3 @@ export declare function readToolModuleItems(root: string): Promise<Array<{
30
24
  * - scalars and non-plain objects are replaced
31
25
  */
32
26
  export declare function loadWorkspaceObjects(workspaceRoot: string, options?: WorkspaceLoadOptions): Promise<WorkspaceObjects>;
33
- export {};
@@ -2,12 +2,12 @@ import path from "node:path";
2
2
  import { existsSync, statSync } from "node:fs";
3
3
  import { readdir, readFile } from "node:fs/promises";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
- import { parseAllDocuments } from "yaml";
6
5
  import { resolveIsolatedResourceModulePath } from "../resource/isolation.js";
7
6
  import { isExternalSourceLocator, resolveResourcePackageRoot } from "../resource/sources.js";
8
7
  import { discoverToolModuleDefinitions, isSupportedToolModulePath } from "../tool-modules.js";
9
- import { fileExists, listFilesRecursive, readYamlOrJson } from "../utils/fs.js";
10
- const MODEL_FILENAMES = ["models.yaml", "models.yml"];
8
+ import { fileExists } from "../utils/fs.js";
9
+ import { readNamedModelItems, readNamedYamlItems, readYamlItems, } from "./yaml-object-reader.js";
10
+ export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
11
11
  const CONVENTIONAL_OBJECT_DIRECTORIES = ["tools"];
12
12
  const MODULE_AGENT_FILENAMES = ["agent.yaml", "agent.yml"];
13
13
  const MODULE_TOOL_FILENAMES = ["tool.yaml", "tool.yml"];
@@ -84,107 +84,6 @@ function asMutableObject(value) {
84
84
  ? { ...value }
85
85
  : undefined;
86
86
  }
87
- function normalizeCatalogSpec(document, options = {}) {
88
- const typed = asObject(document);
89
- const spec = typed?.spec;
90
- if (!Array.isArray(spec)) {
91
- return [];
92
- }
93
- const normalized = spec
94
- .filter((item) => typeof item === "object" && item !== null && !Array.isArray(item))
95
- .map((item) => {
96
- const id = typeof item.id === "string" && item.id.trim()
97
- ? item.id
98
- : typeof item.name === "string" && item.name.trim()
99
- ? item.name
100
- : undefined;
101
- const itemKind = typeof item.kind === "string" && item.kind.trim()
102
- ? item.kind
103
- : options.defaultKind;
104
- if (!id || !itemKind) {
105
- return null;
106
- }
107
- return {
108
- ...item,
109
- kind: itemKind,
110
- id,
111
- };
112
- });
113
- return normalized.filter((item) => item !== null);
114
- }
115
- function normalizeKind(kind) {
116
- switch (kind) {
117
- case "Agent":
118
- return "agent";
119
- case "FileStore":
120
- return "file-store";
121
- case "InMemoryStore":
122
- return "in-memory-store";
123
- case "RedisStore":
124
- return "redis-store";
125
- case "PostgresStore":
126
- return "postgres-store";
127
- case "SqliteSaver":
128
- return "sqlite-saver";
129
- case "FileCheckpointer":
130
- return "file-checkpointer";
131
- case "Checkpointer":
132
- return "checkpointer";
133
- case "Model":
134
- return "model";
135
- case "EmbeddingModel":
136
- return "embedding-model";
137
- case "VectorStore":
138
- return "vector-store";
139
- case "Backend":
140
- return "backend";
141
- case "Store":
142
- return "store";
143
- case "Memory":
144
- return "memory";
145
- case "Tool":
146
- return "tool";
147
- case "Skill":
148
- return "skill";
149
- case "Runtime":
150
- return "runtime";
151
- case "RuntimeMemory":
152
- return "runtime-memory";
153
- case "Prompt":
154
- return "prompt";
155
- case "McpServer":
156
- return "mcp";
157
- default:
158
- return kind;
159
- }
160
- }
161
- export function normalizeYamlItem(item) {
162
- if (item.kind === "DeepAgent" || item.kind === "LangChainAgent") {
163
- throw new Error(`YAML object kind ${String(item.kind)} is no longer supported; use kind: Agent with spec.execution.backend instead`);
164
- }
165
- const metadata = asObject(item.metadata);
166
- const spec = asObject(item.spec);
167
- const kind = typeof item.kind === "string" ? normalizeKind(item.kind) : undefined;
168
- const name = typeof metadata?.name === "string" ? metadata.name : undefined;
169
- const description = typeof metadata?.description === "string" ? metadata.description : undefined;
170
- if (!spec && !metadata) {
171
- return kind ? { ...item, kind } : item;
172
- }
173
- if (!spec && metadata) {
174
- return {
175
- ...item,
176
- ...(description ? { description } : {}),
177
- ...(name ? { id: name } : {}),
178
- ...(kind ? { kind } : {}),
179
- };
180
- }
181
- return {
182
- ...(spec ?? {}),
183
- ...(description ? { description } : {}),
184
- ...(name ? { id: name } : {}),
185
- ...(kind ? { kind } : {}),
186
- };
187
- }
188
87
  function readRefArray(items) {
189
88
  return toArray(items)
190
89
  .map((item) => typeof item === "string"
@@ -235,12 +134,29 @@ function readCapabilities(value) {
235
134
  };
236
135
  return Object.keys(capabilities).length > 0 ? capabilities : undefined;
237
136
  }
137
+ const CONSUMED_AGENT_CONFIG_KEYS = [
138
+ "systemPrompt",
139
+ "checkpointer",
140
+ "interruptOn",
141
+ "stateSchema",
142
+ "responseFormat",
143
+ "contextSchema",
144
+ "includeAgentName",
145
+ "version",
146
+ "middleware",
147
+ "backend",
148
+ "store",
149
+ "runtimeMemory",
150
+ "taskDescription",
151
+ "generalPurposeAgent",
152
+ "filesystem",
153
+ ];
238
154
  function readExecutionConfig(value) {
239
155
  return asMutableObject(value);
240
156
  }
241
- function readExecutionAgentConfig(item) {
157
+ function readExecutionValue(item, key, reader) {
242
158
  const execution = readExecutionConfig(item.execution);
243
- return asMutableObject(execution?.config) ?? {};
159
+ return reader(execution?.[key]);
244
160
  }
245
161
  function readRuntimeConfig(item) {
246
162
  return asMutableObject(item.runtime);
@@ -323,21 +239,13 @@ function resolveExecutionBackend(item, current) {
323
239
  }
324
240
  return undefined;
325
241
  }
326
- function readExecutionSingleRef(item, key) {
327
- const execution = readExecutionConfig(item.execution);
328
- return readSingleRef(execution?.[key]);
329
- }
330
- function readExecutionRefArray(item, key) {
331
- const execution = readExecutionConfig(item.execution);
332
- return readRefArray(execution?.[key]);
333
- }
334
- function readExecutionPathArray(item, key) {
335
- const execution = readExecutionConfig(item.execution);
336
- return readPathArray(execution?.[key]);
337
- }
338
- function readExecutionObjectArray(item, key) {
339
- const execution = readExecutionConfig(item.execution);
340
- return readObjectArray(execution?.[key]);
242
+ function readSharedAgentConfigFields(config) {
243
+ return {
244
+ ...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
245
+ ...(typeof config.runtimeMemory === "object" && config.runtimeMemory ? { runtimeMemory: config.runtimeMemory } : {}),
246
+ ...(typeof config.taskDescription === "string" && config.taskDescription.trim() ? { taskDescription: config.taskDescription } : {}),
247
+ ...(typeof config.generalPurposeAgent === "boolean" ? { generalPurposeAgent: config.generalPurposeAgent } : {}),
248
+ };
341
249
  }
342
250
  function readSharedAgentConfig(config) {
343
251
  const middleware = readMiddlewareArray(config.middleware);
@@ -359,67 +267,20 @@ function readSharedAgentConfig(config) {
359
267
  ...(middleware ? { middleware } : {}),
360
268
  };
361
269
  }
362
- function readLangchainAgentConfig(item) {
363
- const config = readExecutionAgentConfig(item);
364
- const passthrough = readPassthroughConfig(config, [
365
- "systemPrompt",
366
- "checkpointer",
367
- "interruptOn",
368
- "stateSchema",
369
- "responseFormat",
370
- "contextSchema",
371
- "includeAgentName",
372
- "version",
373
- "middleware",
374
- "backend",
375
- "store",
376
- "runtimeMemory",
377
- "taskDescription",
378
- "generalPurposeAgent",
379
- "filesystem",
380
- ]);
270
+ function readAgentConfig(item, options = {}) {
271
+ const config = readExecutionValue(item, "config", asMutableObject) ?? {};
272
+ const passthrough = readPassthroughConfig(config, [...CONSUMED_AGENT_CONFIG_KEYS]);
381
273
  return {
382
274
  ...readSharedAgentConfig(config),
383
- ...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
384
- ...(typeof config.runtimeMemory === "object" && config.runtimeMemory ? { runtimeMemory: config.runtimeMemory } : {}),
385
- ...(typeof config.taskDescription === "string" && config.taskDescription.trim() ? { taskDescription: config.taskDescription } : {}),
386
- ...(typeof config.generalPurposeAgent === "boolean" ? { generalPurposeAgent: config.generalPurposeAgent } : {}),
387
- ...(passthrough ? { passthrough } : {}),
388
- };
389
- }
390
- function readDeepAgentConfig(item) {
391
- const config = readExecutionAgentConfig(item);
392
- const passthrough = readPassthroughConfig(config, [
393
- "systemPrompt",
394
- "checkpointer",
395
- "interruptOn",
396
- "stateSchema",
397
- "responseFormat",
398
- "contextSchema",
399
- "includeAgentName",
400
- "version",
401
- "middleware",
402
- "backend",
403
- "store",
404
- "runtimeMemory",
405
- "taskDescription",
406
- "generalPurposeAgent",
407
- "filesystem",
408
- ]);
409
- return {
410
- ...readSharedAgentConfig(config),
411
- ...(typeof config.backend === "object" && config.backend ? { backend: config.backend } : {}),
412
- ...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
413
- ...(typeof config.runtimeMemory === "object" && config.runtimeMemory ? { runtimeMemory: config.runtimeMemory } : {}),
414
- ...(typeof config.taskDescription === "string" && config.taskDescription.trim() ? { taskDescription: config.taskDescription } : {}),
415
- ...(typeof config.generalPurposeAgent === "boolean" ? { generalPurposeAgent: config.generalPurposeAgent } : {}),
275
+ ...readSharedAgentConfigFields(config),
276
+ ...(options.includeObjectBackend && typeof config.backend === "object" && config.backend ? { backend: config.backend } : {}),
416
277
  ...(passthrough ? { passthrough } : {}),
417
278
  };
418
279
  }
419
280
  export function parseAgentItem(item, sourcePath) {
420
281
  const moduleRoot = moduleRootForSourcePath(sourcePath, "agents");
421
- const subagentRefs = readExecutionRefArray(item, "subagents");
422
- const subagentPathRefs = readExecutionPathArray(item, "subagents").map((entry) => resolveModuleRelativePath(entry, moduleRoot));
282
+ const subagentRefs = readExecutionValue(item, "subagents", readRefArray);
283
+ const subagentPathRefs = readExecutionValue(item, "subagents", readPathArray).map((entry) => resolveModuleRelativePath(entry, moduleRoot));
423
284
  const executionMode = String(resolveExecutionBackend(item) ?? "deepagent");
424
285
  const runtime = readRuntimeConfig(item);
425
286
  return {
@@ -430,45 +291,19 @@ export function parseAgentItem(item, sourcePath) {
430
291
  ? { delegation: true, memory: true }
431
292
  : { delegation: true, memory: true }),
432
293
  description: String(item.description ?? ""),
433
- modelRef: readExecutionSingleRef(item, "modelRef") ?? "",
294
+ modelRef: readExecutionValue(item, "modelRef", readSingleRef) ?? "",
434
295
  runRoot: typeof runtime?.runRoot === "string" ? runtime.runRoot : undefined,
435
- toolRefs: readExecutionRefArray(item, "tools"),
436
- mcpServers: readExecutionObjectArray(item, "mcpServers"),
437
- skillPathRefs: readExecutionPathArray(item, "skills").map((entry) => resolveModuleRelativePath(entry, moduleRoot)),
438
- memorySources: readExecutionPathArray(item, "memory").map((entry) => resolveModuleRelativePath(entry, moduleRoot)),
296
+ toolRefs: readExecutionValue(item, "tools", readRefArray),
297
+ mcpServers: readExecutionValue(item, "mcpServers", readObjectArray),
298
+ skillPathRefs: readExecutionValue(item, "skills", readPathArray).map((entry) => resolveModuleRelativePath(entry, moduleRoot)),
299
+ memorySources: readExecutionValue(item, "memory", readPathArray).map((entry) => resolveModuleRelativePath(entry, moduleRoot)),
439
300
  subagentRefs,
440
301
  subagentPathRefs,
441
- langchainAgentConfig: normalizeModuleAgentConfig(readLangchainAgentConfig(item), moduleRoot),
442
- deepAgentConfig: normalizeModuleAgentConfig(readDeepAgentConfig(item), moduleRoot),
302
+ langchainAgentConfig: normalizeModuleAgentConfig(readAgentConfig(item), moduleRoot),
303
+ deepAgentConfig: normalizeModuleAgentConfig(readAgentConfig(item, { includeObjectBackend: true }), moduleRoot),
443
304
  sourcePath,
444
305
  };
445
306
  }
446
- async function objectItemsFromDocument(document, sourcePath) {
447
- if (typeof document !== "object" || !document) {
448
- return [];
449
- }
450
- const catalogKind = typeof document.kind === "string"
451
- ? String(document.kind)
452
- : undefined;
453
- const catalogItems = catalogKind === "Models"
454
- ? normalizeCatalogSpec(document, { defaultKind: "Model" })
455
- : catalogKind === "Stores"
456
- ? normalizeCatalogSpec(document)
457
- : catalogKind === "Backends"
458
- ? normalizeCatalogSpec(document, { defaultKind: "Backend" })
459
- : catalogKind === "Tools"
460
- ? normalizeCatalogSpec(document, { defaultKind: "Tool" })
461
- : catalogKind === "McpServers"
462
- ? normalizeCatalogSpec(document, { defaultKind: "McpServer" })
463
- : [];
464
- if (catalogItems.length > 0) {
465
- return catalogItems;
466
- }
467
- if ("items" in document) {
468
- throw new Error(`YAML document ${sourcePath} uses unsupported legacy items wrapper; use kind/spec catalog documents or metadata/spec objects instead`);
469
- }
470
- return [document];
471
- }
472
307
  function parseWorkspaceObject(item, sourcePath) {
473
308
  if (typeof item.id !== "string") {
474
309
  return null;
@@ -657,73 +492,6 @@ async function loadRootObjects(root, mergedObjects) {
657
492
  mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
658
493
  }
659
494
  }
660
- export async function readYamlItems(root, relativeDir, options = {}) {
661
- const targetRoot = relativeDir ? path.join(root, relativeDir) : root;
662
- if (!(await fileExists(targetRoot))) {
663
- return [];
664
- }
665
- const files = options.recursive
666
- ? await listFilesRecursive(targetRoot, ".yaml")
667
- : (await readdir(targetRoot, { withFileTypes: true }))
668
- .filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name))
669
- .map((entry) => path.join(targetRoot, entry.name))
670
- .sort();
671
- const records = [];
672
- for (const filePath of files) {
673
- const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
674
- for (const parsedDocument of parsedDocuments) {
675
- for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
676
- records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
677
- }
678
- }
679
- }
680
- return records;
681
- }
682
- async function readNamedYamlItems(root, filenames) {
683
- const records = [];
684
- for (const filename of filenames) {
685
- const filePath = path.join(root, filename);
686
- if (!(await fileExists(filePath))) {
687
- continue;
688
- }
689
- const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
690
- for (const parsedDocument of parsedDocuments) {
691
- for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
692
- records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
693
- }
694
- }
695
- }
696
- return records;
697
- }
698
- async function readNamedModelItems(root) {
699
- const filePaths = new Set();
700
- for (const filename of MODEL_FILENAMES) {
701
- const directPath = path.join(root, filename);
702
- if (await fileExists(directPath)) {
703
- filePaths.add(directPath);
704
- }
705
- }
706
- for (const extension of [".yaml", ".yml"]) {
707
- for (const filePath of await listFilesRecursive(root, extension)) {
708
- if (MODEL_FILENAMES.includes(path.basename(filePath))) {
709
- filePaths.add(filePath);
710
- }
711
- }
712
- }
713
- const records = [];
714
- for (const filePath of [...filePaths].sort()) {
715
- const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
716
- for (const parsedDocument of parsedDocuments) {
717
- for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
718
- const normalized = normalizeYamlItem(item);
719
- if (normalized.kind === "model" && typeof normalized.id === "string" && normalized.id.trim()) {
720
- records.push({ item: normalized, sourcePath: filePath });
721
- }
722
- }
723
- }
724
- }
725
- return records;
726
- }
727
495
  function isAgentKind(kind) {
728
496
  return kind === "agent";
729
497
  }
@@ -0,0 +1,15 @@
1
+ export declare function normalizeYamlItem(item: Record<string, unknown>): Record<string, unknown>;
2
+ export declare function readYamlItems(root: string, relativeDir?: string, options?: {
3
+ recursive?: boolean;
4
+ }): Promise<Array<{
5
+ item: Record<string, unknown>;
6
+ sourcePath: string;
7
+ }>>;
8
+ export declare function readNamedYamlItems(root: string, filenames: string[]): Promise<Array<{
9
+ item: Record<string, unknown>;
10
+ sourcePath: string;
11
+ }>>;
12
+ export declare function readNamedModelItems(root: string): Promise<Array<{
13
+ item: Record<string, unknown>;
14
+ sourcePath: string;
15
+ }>>;
@@ -0,0 +1,202 @@
1
+ import path from "node:path";
2
+ import { readdir } from "node:fs/promises";
3
+ import { parseAllDocuments } from "yaml";
4
+ import { fileExists, listFilesRecursive, readYamlOrJson } from "../utils/fs.js";
5
+ const MODEL_FILENAMES = ["models.yaml", "models.yml"];
6
+ function asObject(value) {
7
+ return typeof value === "object" && value ? value : undefined;
8
+ }
9
+ function normalizeCatalogSpec(document, options = {}) {
10
+ const typed = asObject(document);
11
+ const spec = typed?.spec;
12
+ if (!Array.isArray(spec)) {
13
+ return [];
14
+ }
15
+ const normalized = spec
16
+ .filter((item) => typeof item === "object" && item !== null && !Array.isArray(item))
17
+ .map((item) => {
18
+ const id = typeof item.id === "string" && item.id.trim()
19
+ ? item.id
20
+ : typeof item.name === "string" && item.name.trim()
21
+ ? item.name
22
+ : undefined;
23
+ const itemKind = typeof item.kind === "string" && item.kind.trim()
24
+ ? item.kind
25
+ : options.defaultKind;
26
+ if (!id || !itemKind) {
27
+ return null;
28
+ }
29
+ return {
30
+ ...item,
31
+ kind: itemKind,
32
+ id,
33
+ };
34
+ });
35
+ return normalized.filter((item) => item !== null);
36
+ }
37
+ function normalizeKind(kind) {
38
+ switch (kind) {
39
+ case "Agent":
40
+ return "agent";
41
+ case "FileStore":
42
+ return "file-store";
43
+ case "InMemoryStore":
44
+ return "in-memory-store";
45
+ case "RedisStore":
46
+ return "redis-store";
47
+ case "PostgresStore":
48
+ return "postgres-store";
49
+ case "SqliteSaver":
50
+ return "sqlite-saver";
51
+ case "FileCheckpointer":
52
+ return "file-checkpointer";
53
+ case "Checkpointer":
54
+ return "checkpointer";
55
+ case "Model":
56
+ return "model";
57
+ case "EmbeddingModel":
58
+ return "embedding-model";
59
+ case "VectorStore":
60
+ return "vector-store";
61
+ case "Backend":
62
+ return "backend";
63
+ case "Store":
64
+ return "store";
65
+ case "Memory":
66
+ return "memory";
67
+ case "Tool":
68
+ return "tool";
69
+ case "Skill":
70
+ return "skill";
71
+ case "Runtime":
72
+ return "runtime";
73
+ case "RuntimeMemory":
74
+ return "runtime-memory";
75
+ case "Prompt":
76
+ return "prompt";
77
+ case "McpServer":
78
+ return "mcp";
79
+ default:
80
+ return kind;
81
+ }
82
+ }
83
+ export function normalizeYamlItem(item) {
84
+ if (item.kind === "DeepAgent" || item.kind === "LangChainAgent") {
85
+ throw new Error(`YAML object kind ${String(item.kind)} is no longer supported; use kind: Agent with spec.execution.backend instead`);
86
+ }
87
+ const metadata = asObject(item.metadata);
88
+ const spec = asObject(item.spec);
89
+ const kind = typeof item.kind === "string" ? normalizeKind(item.kind) : undefined;
90
+ const name = typeof metadata?.name === "string" ? metadata.name : undefined;
91
+ const description = typeof metadata?.description === "string" ? metadata.description : undefined;
92
+ if (!spec && !metadata) {
93
+ return kind ? { ...item, kind } : item;
94
+ }
95
+ if (!spec && metadata) {
96
+ return {
97
+ ...item,
98
+ ...(description ? { description } : {}),
99
+ ...(name ? { id: name } : {}),
100
+ ...(kind ? { kind } : {}),
101
+ };
102
+ }
103
+ return {
104
+ ...(spec ?? {}),
105
+ ...(description ? { description } : {}),
106
+ ...(name ? { id: name } : {}),
107
+ ...(kind ? { kind } : {}),
108
+ };
109
+ }
110
+ async function objectItemsFromDocument(document, sourcePath) {
111
+ if (typeof document !== "object" || !document) {
112
+ return [];
113
+ }
114
+ const catalogKind = typeof document.kind === "string"
115
+ ? String(document.kind)
116
+ : undefined;
117
+ const catalogItems = catalogKind === "Models"
118
+ ? normalizeCatalogSpec(document, { defaultKind: "Model" })
119
+ : catalogKind === "Stores"
120
+ ? normalizeCatalogSpec(document)
121
+ : catalogKind === "Backends"
122
+ ? normalizeCatalogSpec(document, { defaultKind: "Backend" })
123
+ : catalogKind === "Tools"
124
+ ? normalizeCatalogSpec(document, { defaultKind: "Tool" })
125
+ : catalogKind === "McpServers"
126
+ ? normalizeCatalogSpec(document, { defaultKind: "McpServer" })
127
+ : [];
128
+ if (catalogItems.length > 0) {
129
+ return catalogItems;
130
+ }
131
+ if ("items" in document) {
132
+ throw new Error(`YAML document ${sourcePath} uses unsupported legacy items wrapper; use kind/spec catalog documents or metadata/spec objects instead`);
133
+ }
134
+ return [document];
135
+ }
136
+ export async function readYamlItems(root, relativeDir, options = {}) {
137
+ const targetRoot = relativeDir ? path.join(root, relativeDir) : root;
138
+ if (!(await fileExists(targetRoot))) {
139
+ return [];
140
+ }
141
+ const files = options.recursive
142
+ ? await listFilesRecursive(targetRoot, ".yaml")
143
+ : (await readdir(targetRoot, { withFileTypes: true }))
144
+ .filter((entry) => entry.isFile() && /\.ya?ml$/i.test(entry.name))
145
+ .map((entry) => path.join(targetRoot, entry.name))
146
+ .sort();
147
+ const records = [];
148
+ for (const filePath of files) {
149
+ const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
150
+ for (const parsedDocument of parsedDocuments) {
151
+ for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
152
+ records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
153
+ }
154
+ }
155
+ }
156
+ return records;
157
+ }
158
+ export async function readNamedYamlItems(root, filenames) {
159
+ const records = [];
160
+ for (const filename of filenames) {
161
+ const filePath = path.join(root, filename);
162
+ if (!(await fileExists(filePath))) {
163
+ continue;
164
+ }
165
+ const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
166
+ for (const parsedDocument of parsedDocuments) {
167
+ for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
168
+ records.push({ item: normalizeYamlItem(item), sourcePath: filePath });
169
+ }
170
+ }
171
+ }
172
+ return records;
173
+ }
174
+ export async function readNamedModelItems(root) {
175
+ const filePaths = new Set();
176
+ for (const filename of MODEL_FILENAMES) {
177
+ const directPath = path.join(root, filename);
178
+ if (await fileExists(directPath)) {
179
+ filePaths.add(directPath);
180
+ }
181
+ }
182
+ for (const extension of [".yaml", ".yml"]) {
183
+ for (const filePath of await listFilesRecursive(root, extension)) {
184
+ if (MODEL_FILENAMES.includes(path.basename(filePath))) {
185
+ filePaths.add(filePath);
186
+ }
187
+ }
188
+ }
189
+ const records = [];
190
+ for (const filePath of [...filePaths].sort()) {
191
+ const parsedDocuments = parseAllDocuments(await readYamlOrJson(filePath));
192
+ for (const parsedDocument of parsedDocuments) {
193
+ for (const item of await objectItemsFromDocument(parsedDocument.toJSON(), filePath)) {
194
+ const normalized = normalizeYamlItem(item);
195
+ if (normalized.kind === "model" && typeof normalized.id === "string" && normalized.id.trim()) {
196
+ records.push({ item: normalized, sourcePath: filePath });
197
+ }
198
+ }
199
+ }
200
+ }
201
+ return records;
202
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.100",
3
+ "version": "0.0.102",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",
@@ -1 +0,0 @@
1
- export * from "./maintenance/checkpoint-maintenance.js";
@@ -1 +0,0 @@
1
- export * from "./maintenance/checkpoint-maintenance.js";
@@ -1 +0,0 @@
1
- export * from "./maintenance/file-checkpoint-saver.js";
@@ -1 +0,0 @@
1
- export * from "./maintenance/file-checkpoint-saver.js";
@@ -1 +0,0 @@
1
- export * from "./maintenance/sqlite-maintained-checkpoint-saver.js";
@@ -1 +0,0 @@
1
- export * from "./maintenance/sqlite-maintained-checkpoint-saver.js";