@botbotgo/agent-harness 0.0.475 → 0.0.476

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 (227) hide show
  1. package/README.md +3 -1234
  2. package/README.zh.md +3 -1191
  3. package/dist/acp.js +1 -1
  4. package/dist/api.js +1 -404
  5. package/dist/benchmark/checkpoint-resume-cost-benchmark.js +1 -55
  6. package/dist/benchmark/deepagent-local-model-benchmark.js +2 -35
  7. package/dist/benchmark/upstream-runtime-ab-benchmark.js +1 -179
  8. package/dist/cli/chat-interactive.js +25 -244
  9. package/dist/cli/chat-rendering.js +6 -100
  10. package/dist/cli/chat-stream.js +23 -512
  11. package/dist/cli/chat-ui.js +21 -199
  12. package/dist/cli/chat-workspace.js +2 -210
  13. package/dist/cli/main.js +21 -428
  14. package/dist/cli/managed-service-commands.js +9 -63
  15. package/dist/cli/managed-service.js +2 -137
  16. package/dist/cli/options-init-chat.js +1 -108
  17. package/dist/cli/options-runtime.js +1 -158
  18. package/dist/cli/options-serve.js +1 -282
  19. package/dist/cli/options.js +2 -19
  20. package/dist/cli/process-guards.js +1 -139
  21. package/dist/cli/request-tree.js +7 -296
  22. package/dist/cli/runtime-commands.js +12 -258
  23. package/dist/cli/runtime-output.js +16 -155
  24. package/dist/cli/server-commands.js +16 -270
  25. package/dist/cli/workspace.js +1 -67
  26. package/dist/cli.js +1 -7
  27. package/dist/client/acp.js +1 -1
  28. package/dist/client/in-process.js +1 -67
  29. package/dist/client/index.js +1 -2
  30. package/dist/client/types.js +0 -1
  31. package/dist/client.js +1 -1
  32. package/dist/contracts/core.js +1 -1
  33. package/dist/contracts/runtime-evaluation.js +0 -1
  34. package/dist/contracts/runtime-memory.js +0 -1
  35. package/dist/contracts/runtime-observability.js +0 -1
  36. package/dist/contracts/runtime-requests.js +0 -1
  37. package/dist/contracts/runtime-scheduling.js +0 -1
  38. package/dist/contracts/runtime.js +1 -27
  39. package/dist/contracts/types.js +1 -3
  40. package/dist/contracts/workspace.js +0 -1
  41. package/dist/flow/build-flow-graph.js +1 -50
  42. package/dist/flow/export-mermaid.js +2 -464
  43. package/dist/flow/export-sequence-mermaid.js +2 -325
  44. package/dist/flow/flow-graph-normalization.js +1 -214
  45. package/dist/flow/flow-graph-runtime.js +1 -107
  46. package/dist/flow/flow-graph-upstream.js +1 -494
  47. package/dist/flow/index.js +1 -3
  48. package/dist/flow/types.js +0 -1
  49. package/dist/index.js +1 -5
  50. package/dist/init-project.js +1 -1
  51. package/dist/knowledge/config.js +1 -32
  52. package/dist/knowledge/contracts.js +0 -1
  53. package/dist/knowledge/index.js +1 -2
  54. package/dist/knowledge/module.js +12 -909
  55. package/dist/knowledge/procedural/config.js +1 -125
  56. package/dist/knowledge/procedural/index.js +1 -2
  57. package/dist/knowledge/procedural/manager.js +9 -345
  58. package/dist/mcp.js +1 -2
  59. package/dist/package-version.d.ts +1 -1
  60. package/dist/package-version.js +1 -2
  61. package/dist/persistence/file-store.js +3 -758
  62. package/dist/persistence/sqlite-request-context-store.js +5 -54
  63. package/dist/persistence/sqlite-request-queue-store.js +10 -108
  64. package/dist/persistence/sqlite-runtime.js +1 -86
  65. package/dist/persistence/sqlite-store.js +62 -810
  66. package/dist/persistence/types.js +0 -1
  67. package/dist/projections/presentation.js +37 -206
  68. package/dist/projections/request-events.js +2 -502
  69. package/dist/projections/upstream-events.js +1 -201
  70. package/dist/protocol/a2a/http-discovery.js +1 -178
  71. package/dist/protocol/a2a/http-rpc.js +6 -622
  72. package/dist/protocol/a2a/http.js +1 -138
  73. package/dist/protocol/a2a/task-state.js +3 -317
  74. package/dist/protocol/acp/client.js +8 -294
  75. package/dist/protocol/acp/harness-client.js +1 -218
  76. package/dist/protocol/acp/http.js +5 -130
  77. package/dist/protocol/acp/server.js +1 -310
  78. package/dist/protocol/acp/stdio.js +2 -69
  79. package/dist/protocol/ag-ui/http.js +3 -378
  80. package/dist/protocol/mcp/server.js +1 -428
  81. package/dist/resource/backend/workspace-scoped-backend.js +1 -319
  82. package/dist/resource/isolation.js +1 -237
  83. package/dist/resource/mcp/tool-support.js +3 -296
  84. package/dist/resource/mcp-tool-support.js +1 -2
  85. package/dist/resource/providers/resource-provider.js +1 -215
  86. package/dist/resource/resource-impl.js +1 -3
  87. package/dist/resource/resource-types.js +0 -1
  88. package/dist/resource/resource.js +1 -1
  89. package/dist/resource/sources.js +1 -247
  90. package/dist/resource/tools/function-tool-resolver.js +2 -272
  91. package/dist/runtime/adapter/compat/deepagent-compat.js +1 -29
  92. package/dist/runtime/adapter/compat/openai-compatible.js +1 -55
  93. package/dist/runtime/adapter/direct-builtin-utility.js +2 -90
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -71
  95. package/dist/runtime/adapter/flow/invocation-flow.js +8 -425
  96. package/dist/runtime/adapter/flow/invoke-runtime.js +1 -20
  97. package/dist/runtime/adapter/flow/stream-runtime.js +11 -1395
  98. package/dist/runtime/adapter/invocation-result.js +2 -473
  99. package/dist/runtime/adapter/local-tool-invocation.js +6 -638
  100. package/dist/runtime/adapter/middleware/context-hygiene.js +1 -83
  101. package/dist/runtime/adapter/middleware-assembly.js +5 -477
  102. package/dist/runtime/adapter/model/invocation-request.js +3 -183
  103. package/dist/runtime/adapter/model/message-assembly.js +1 -28
  104. package/dist/runtime/adapter/model/model-providers.js +23 -1115
  105. package/dist/runtime/adapter/model/prompted-json-tool-call-capture.js +1 -40
  106. package/dist/runtime/adapter/model/prompted-json-tool-policy.js +1 -22
  107. package/dist/runtime/adapter/resilience.js +1 -104
  108. package/dist/runtime/adapter/runtime-adapter-support.js +3 -141
  109. package/dist/runtime/adapter/runtime-shell.js +5 -166
  110. package/dist/runtime/adapter/stream-event-projection.js +2 -622
  111. package/dist/runtime/adapter/stream-text-consumption.js +1 -18
  112. package/dist/runtime/adapter/terminal-status.js +2 -67
  113. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +6 -627
  114. package/dist/runtime/adapter/tool/declared-middleware.js +1 -154
  115. package/dist/runtime/adapter/tool/interrupt-policy.js +1 -34
  116. package/dist/runtime/adapter/tool/provider-tool.js +1 -25
  117. package/dist/runtime/adapter/tool/resolved-tool.js +1 -225
  118. package/dist/runtime/adapter/tool/tool-arguments.js +3 -486
  119. package/dist/runtime/adapter/tool/tool-hitl.js +1 -346
  120. package/dist/runtime/adapter/tool/tool-name-mapping.js +1 -128
  121. package/dist/runtime/adapter/tool/tool-output-artifacts.js +2 -88
  122. package/dist/runtime/adapter/tool/tool-replay.js +1 -37
  123. package/dist/runtime/adapter/tool-resolution.js +1 -86
  124. package/dist/runtime/adapter/upstream-configurable-keys.js +1 -2
  125. package/dist/runtime/agent-runtime-adapter.js +60 -2338
  126. package/dist/runtime/agent-runtime-assembly.js +7 -249
  127. package/dist/runtime/env/runtime-env.js +1 -62
  128. package/dist/runtime/harness/background-runtime.js +1 -8
  129. package/dist/runtime/harness/bindings.js +1 -58
  130. package/dist/runtime/harness/events/event-bus.js +1 -16
  131. package/dist/runtime/harness/events/event-sink.js +1 -61
  132. package/dist/runtime/harness/events/events.js +1 -80
  133. package/dist/runtime/harness/events/listener-runtime.js +1 -13
  134. package/dist/runtime/harness/events/runtime-event-operations.js +1 -9
  135. package/dist/runtime/harness/events/streaming.js +1 -100
  136. package/dist/runtime/harness/events/timeline.js +1 -52
  137. package/dist/runtime/harness/public-shapes.js +1 -186
  138. package/dist/runtime/harness/run/artifact-paths.js +1 -15
  139. package/dist/runtime/harness/run/governance.js +1 -295
  140. package/dist/runtime/harness/run/helpers.js +1 -71
  141. package/dist/runtime/harness/run/inspection.js +1 -409
  142. package/dist/runtime/harness/run/operator-overview.js +1 -80
  143. package/dist/runtime/harness/run/queue-diagnostics.js +1 -15
  144. package/dist/runtime/harness/run/recovery.js +1 -162
  145. package/dist/runtime/harness/run/resources.js +1 -60
  146. package/dist/runtime/harness/run/resume.js +1 -56
  147. package/dist/runtime/harness/run/routing.js +1 -48
  148. package/dist/runtime/harness/run/run-lifecycle.js +1 -66
  149. package/dist/runtime/harness/run/run-operations.js +1 -217
  150. package/dist/runtime/harness/run/run-queue.js +1 -43
  151. package/dist/runtime/harness/run/run-slot-acquisition.js +1 -157
  152. package/dist/runtime/harness/run/session-records.js +1 -97
  153. package/dist/runtime/harness/run/start-run.js +1 -120
  154. package/dist/runtime/harness/run/startup-runtime.js +1 -69
  155. package/dist/runtime/harness/run/stream-run.js +8 -1418
  156. package/dist/runtime/harness/run/surface-semantics.js +1 -79
  157. package/dist/runtime/harness/runtime-defaults.js +1 -39
  158. package/dist/runtime/harness/system/boundary-analysis.js +1 -234
  159. package/dist/runtime/harness/system/health-monitor.js +1 -258
  160. package/dist/runtime/harness/system/inventory.js +1 -129
  161. package/dist/runtime/harness/system/mem0-ingestion-sync.js +5 -345
  162. package/dist/runtime/harness/system/policy-engine.js +1 -175
  163. package/dist/runtime/harness/system/runtime-memory-candidates.js +4 -110
  164. package/dist/runtime/harness/system/runtime-memory-consolidation.js +1 -51
  165. package/dist/runtime/harness/system/runtime-memory-manager.js +10 -693
  166. package/dist/runtime/harness/system/runtime-memory-policy.js +1 -155
  167. package/dist/runtime/harness/system/runtime-memory-records.js +11 -577
  168. package/dist/runtime/harness/system/runtime-memory-sync.js +5 -206
  169. package/dist/runtime/harness/system/session-memory-sync.js +3 -113
  170. package/dist/runtime/harness/system/skill-requirements.js +1 -112
  171. package/dist/runtime/harness/system/store.js +9 -365
  172. package/dist/runtime/harness/tool-gateway/index.js +1 -2
  173. package/dist/runtime/harness/tool-gateway/policy.js +1 -45
  174. package/dist/runtime/harness/tool-gateway/validation.js +1 -176
  175. package/dist/runtime/harness/tool-schema.js +1 -3
  176. package/dist/runtime/harness.js +3 -1490
  177. package/dist/runtime/index.js +1 -3
  178. package/dist/runtime/layout/runtime-layout.js +1 -31
  179. package/dist/runtime/maintenance/checkpoint-maintenance.js +2 -178
  180. package/dist/runtime/maintenance/file-checkpoint-saver.js +1 -106
  181. package/dist/runtime/maintenance/runtime-record-maintenance.js +2 -169
  182. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +4 -289
  183. package/dist/runtime/parsing/output-content.js +10 -550
  184. package/dist/runtime/parsing/output-parsing.js +1 -4
  185. package/dist/runtime/parsing/output-recovery.js +3 -213
  186. package/dist/runtime/parsing/output-tool-args.js +7 -663
  187. package/dist/runtime/parsing/stream-event-parsing.js +3 -362
  188. package/dist/runtime/prompts/runtime-prompts.js +4 -73
  189. package/dist/runtime/scheduling/system-schedule-manager.js +11 -532
  190. package/dist/runtime/skills/skill-metadata.js +1 -197
  191. package/dist/runtime/startup-tracing.js +2 -37
  192. package/dist/runtime/support/compiled-binding.js +1 -290
  193. package/dist/runtime/support/embedding-models.js +1 -118
  194. package/dist/runtime/support/harness-support.js +5 -137
  195. package/dist/runtime/support/llamaindex.js +1 -108
  196. package/dist/runtime/support/runtime-adapter-options.js +1 -29
  197. package/dist/runtime/support/runtime-factories.js +1 -51
  198. package/dist/runtime/support/vector-stores.js +9 -270
  199. package/dist/scaffold/init-project.js +54 -233
  200. package/dist/tooling/extensions.js +1 -311
  201. package/dist/tooling/module-loader.js +1 -55
  202. package/dist/tools.js +1 -176
  203. package/dist/utils/agent-display.js +1 -18
  204. package/dist/utils/bundled-text.js +4 -39
  205. package/dist/utils/compiled-binding.js +1 -33
  206. package/dist/utils/fs.js +2 -45
  207. package/dist/utils/id.js +1 -9
  208. package/dist/utils/message-content.js +1 -30
  209. package/dist/utils/object.js +1 -6
  210. package/dist/workspace/agent-binding-compiler.js +3 -613
  211. package/dist/workspace/compile.js +1 -472
  212. package/dist/workspace/framework-contract-validation.js +2 -322
  213. package/dist/workspace/index.js +1 -1
  214. package/dist/workspace/object-loader-paths.js +1 -71
  215. package/dist/workspace/object-loader-readers.js +1 -187
  216. package/dist/workspace/object-loader.js +1 -754
  217. package/dist/workspace/resource-compilers.js +1 -374
  218. package/dist/workspace/support/agent-capabilities.js +1 -37
  219. package/dist/workspace/support/agent-execution-config.js +1 -44
  220. package/dist/workspace/support/discovery.js +1 -147
  221. package/dist/workspace/support/source-collectors.js +1 -30
  222. package/dist/workspace/support/source-protocols.js +2 -192
  223. package/dist/workspace/support/workspace-ref-utils.js +1 -362
  224. package/dist/workspace/tool-hydration.js +1 -280
  225. package/dist/workspace/validate.js +1 -99
  226. package/dist/workspace/yaml-object-reader.js +1 -285
  227. package/package.json +7 -3
@@ -1,754 +1 @@
1
- import path from "node:path";
2
- import { existsSync } from "node:fs";
3
- import { readdir, readFile, stat } from "node:fs/promises";
4
- import { pathToFileURL } from "node:url";
5
- import { resolveIsolatedResourceModulePath } from "../resource/isolation.js";
6
- import { discoverToolModuleDefinitions, isSupportedToolModulePath, loadToolModuleDefinition } from "../tooling/module-loader.js";
7
- import { fileExists, shouldSkipScanDirectory } from "../utils/fs.js";
8
- import { isFileSourceUri, readRuntimeSources, resolveFileSourcePath } from "./support/source-protocols.js";
9
- import { readNamedYamlItems, readYamlItems, } from "./yaml-object-reader.js";
10
- import { CONVENTIONAL_OBJECT_DIRECTORIES, MODULE_AGENT_FILENAMES, MODULE_TOOL_ENTRY_FILENAMES, MODULE_TOOL_FILENAMES, conventionalConfigRoot, conventionalObjectRoots, frameworkWorkspaceRoot, moduleCollectionRoot, moduleRootForSourcePath, resolveModuleRelativePath, } from "./object-loader-paths.js";
11
- import { asMutableObject, asObject, cloneConfigValue, readAsyncSubAgentArray, readCapabilities, readMcpServerArray, readMiddlewareArray, readPathArray, readPrefixedRefArray, readRefArray, readSingleRef, readToolBindingArray, } from "./object-loader-readers.js";
12
- export { normalizeYamlItem, readYamlItems } from "./yaml-object-reader.js";
13
- const CONSUMED_AGENT_CONFIG_KEYS = [
14
- "systemPrompt",
15
- "checkpointer",
16
- "interruptOn",
17
- "stateSchema",
18
- "responseFormat",
19
- "responseFormatRef",
20
- "contextSchema",
21
- "includeAgentName",
22
- "version",
23
- "middleware",
24
- "backend",
25
- "store",
26
- "runtimeMemory",
27
- "proceduralMemory",
28
- "taskDescription",
29
- "generalPurposeAgent",
30
- "filesystem",
31
- "builtinTools",
32
- "interactionMode",
33
- "executionContract",
34
- ];
35
- const NON_AGENT_CONFIG_ITEM_KEYS = [
36
- "id",
37
- "kind",
38
- "description",
39
- "capabilities",
40
- "runtime",
41
- "executionMode",
42
- "sourcePath",
43
- ];
44
- const RESERVED_AGENT_KEYS = [
45
- "backend",
46
- "modelRef",
47
- "tools",
48
- "skills",
49
- "memory",
50
- "subagents",
51
- "mcpServers",
52
- "config",
53
- ];
54
- const MIGRATED_AGENT_CONFIG_KEYS = [
55
- "systemPrompt",
56
- "checkpointer",
57
- "interruptOn",
58
- "stateSchema",
59
- "responseFormat",
60
- "responseFormatRef",
61
- "contextSchema",
62
- "includeAgentName",
63
- "version",
64
- "middleware",
65
- "store",
66
- "taskDescription",
67
- "generalPurposeAgent",
68
- "filesystem",
69
- "builtinTools",
70
- "interactionMode",
71
- "executionContract",
72
- ];
73
- function normalizeAgentItemForMerge(item) {
74
- const normalized = { ...item };
75
- if (normalized.execution !== undefined) {
76
- throw new Error("Agent spec.execution is no longer supported; move backend, modelRef, tools, skills, memory, subagents, mcpServers, and config directly under spec");
77
- }
78
- const config = asMutableObject(normalized.config);
79
- const runtime = readRuntimeConfig(normalized);
80
- if (config) {
81
- for (const key of MIGRATED_AGENT_CONFIG_KEYS) {
82
- if (!(key in config) || normalized[key] !== undefined) {
83
- continue;
84
- }
85
- normalized[key] = cloneConfigValue(config[key]);
86
- delete config[key];
87
- }
88
- if (config.runtimeMemory !== undefined && runtime?.runtimeMemory === undefined) {
89
- const nextRuntime = runtime ?? {};
90
- nextRuntime.runtimeMemory = cloneConfigValue(config.runtimeMemory);
91
- normalized.runtime = nextRuntime;
92
- delete config.runtimeMemory;
93
- }
94
- if (config.proceduralMemory !== undefined && runtime?.proceduralMemory === undefined) {
95
- const nextRuntime = asMutableObject(normalized.runtime) ?? runtime ?? {};
96
- nextRuntime.proceduralMemory = cloneConfigValue(config.proceduralMemory);
97
- normalized.runtime = nextRuntime;
98
- delete config.proceduralMemory;
99
- }
100
- }
101
- if (config && Object.keys(config).length > 0) {
102
- normalized.config = config;
103
- }
104
- else {
105
- delete normalized.config;
106
- }
107
- return normalized;
108
- }
109
- function readExecutionAgentConfig(item) {
110
- const config = asMutableObject(item.config) ?? {};
111
- const directExecutionConfig = Object.fromEntries(Object.entries(item).filter(([key]) => !RESERVED_AGENT_KEYS.includes(key) &&
112
- !NON_AGENT_CONFIG_ITEM_KEYS.includes(key)));
113
- return {
114
- ...config,
115
- ...directExecutionConfig,
116
- };
117
- }
118
- function readExecutionValue(item, key, reader) {
119
- return reader(item[key]);
120
- }
121
- function readRuntimeConfig(item) {
122
- return asMutableObject(item.runtime);
123
- }
124
- function readRuntimeMemoryConfig(item, runtime) {
125
- if (typeof runtime?.runtimeMemory === "string" && runtime.runtimeMemory.trim()) {
126
- return {
127
- ref: runtime.runtimeMemory.startsWith("runtime-memory/")
128
- ? runtime.runtimeMemory
129
- : `runtime-memory/${runtime.runtimeMemory.trim()}`,
130
- };
131
- }
132
- if (typeof runtime?.runtimeMemory === "object" && runtime.runtimeMemory && !Array.isArray(runtime.runtimeMemory)) {
133
- return cloneConfigValue(runtime.runtimeMemory);
134
- }
135
- const legacyExecutionConfig = readExecutionAgentConfig(item);
136
- if (typeof legacyExecutionConfig.runtimeMemory === "string" && legacyExecutionConfig.runtimeMemory.trim()) {
137
- return {
138
- ref: legacyExecutionConfig.runtimeMemory.startsWith("runtime-memory/")
139
- ? legacyExecutionConfig.runtimeMemory
140
- : `runtime-memory/${legacyExecutionConfig.runtimeMemory.trim()}`,
141
- };
142
- }
143
- if (typeof legacyExecutionConfig.runtimeMemory === "object" &&
144
- legacyExecutionConfig.runtimeMemory &&
145
- !Array.isArray(legacyExecutionConfig.runtimeMemory)) {
146
- return cloneConfigValue(legacyExecutionConfig.runtimeMemory);
147
- }
148
- return undefined;
149
- }
150
- function readProceduralMemoryConfig(item, runtime) {
151
- if (typeof runtime?.proceduralMemory === "string" && runtime.proceduralMemory.trim()) {
152
- return {
153
- ref: runtime.proceduralMemory.startsWith("procedural-memory/")
154
- ? runtime.proceduralMemory
155
- : `procedural-memory/${runtime.proceduralMemory.trim()}`,
156
- };
157
- }
158
- if (typeof runtime?.proceduralMemory === "object" && runtime.proceduralMemory && !Array.isArray(runtime.proceduralMemory)) {
159
- return cloneConfigValue(runtime.proceduralMemory);
160
- }
161
- const legacyExecutionConfig = readExecutionAgentConfig(item);
162
- if (typeof legacyExecutionConfig.proceduralMemory === "string" && legacyExecutionConfig.proceduralMemory.trim()) {
163
- return {
164
- ref: legacyExecutionConfig.proceduralMemory.startsWith("procedural-memory/")
165
- ? legacyExecutionConfig.proceduralMemory
166
- : `procedural-memory/${legacyExecutionConfig.proceduralMemory.trim()}`,
167
- };
168
- }
169
- if (typeof legacyExecutionConfig.proceduralMemory === "object" &&
170
- legacyExecutionConfig.proceduralMemory &&
171
- !Array.isArray(legacyExecutionConfig.proceduralMemory)) {
172
- return cloneConfigValue(legacyExecutionConfig.proceduralMemory);
173
- }
174
- return undefined;
175
- }
176
- function normalizeModulePromptConfig(value, moduleRoot) {
177
- if (!moduleRoot || typeof value !== "object" || value === null || Array.isArray(value)) {
178
- return value;
179
- }
180
- const typed = { ...value };
181
- if (typeof typed.path === "string") {
182
- typed.path = resolveModuleRelativePath(typed.path, moduleRoot);
183
- }
184
- return typed;
185
- }
186
- function normalizeModuleAgentConfig(config, moduleRoot) {
187
- if (!moduleRoot) {
188
- return config;
189
- }
190
- return {
191
- ...config,
192
- ...(config.systemPrompt !== undefined
193
- ? { systemPrompt: normalizeModulePromptConfig(config.systemPrompt, moduleRoot) }
194
- : {}),
195
- };
196
- }
197
- function readPassthroughConfig(item, consumedKeys) {
198
- const passthrough = Object.fromEntries(Object.entries(item)
199
- .filter(([key]) => !consumedKeys.includes(key))
200
- .map(([key, value]) => [key, cloneConfigValue(value)]));
201
- return Object.keys(passthrough).length > 0 ? passthrough : undefined;
202
- }
203
- function resolveExecutionBackend(item, current) {
204
- if (item.execution !== undefined || current?.execution !== undefined) {
205
- throw new Error("Agent spec.execution is no longer supported; move backend, modelRef, tools, skills, memory, subagents, mcpServers, and config directly under spec");
206
- }
207
- const mode = typeof item.mode === "string"
208
- ? item.mode
209
- : typeof current?.mode === "string"
210
- ? current.mode
211
- : undefined;
212
- if (typeof mode === "string" && mode.trim().length > 0) {
213
- throw new Error("Agent mode is no longer supported; use backend");
214
- }
215
- const backend = typeof item.backend === "string"
216
- ? item.backend.trim().toLowerCase()
217
- : typeof current?.backend === "string"
218
- ? current.backend.trim().toLowerCase()
219
- : undefined;
220
- if (backend === "langchain-v1") {
221
- return "langchain-v1";
222
- }
223
- if (backend === "deepagent") {
224
- return "deepagent";
225
- }
226
- if (backend === "langgraph") {
227
- throw new Error("Agent backend=langgraph is no longer supported; use backend=langchain-v1 or backend=deepagent");
228
- }
229
- return undefined;
230
- }
231
- function readSharedAgentConfigFields(config, options = {}) {
232
- return {
233
- ...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
234
- ...(typeof config.builtinTools === "object" && config.builtinTools ? { builtinTools: cloneConfigValue(config.builtinTools) } : {}),
235
- ...(options.includeDelegationControls && typeof config.taskDescription === "string" && config.taskDescription.trim()
236
- ? { taskDescription: config.taskDescription }
237
- : {}),
238
- ...(options.includeDelegationControls && typeof config.generalPurposeAgent === "boolean"
239
- ? { generalPurposeAgent: config.generalPurposeAgent }
240
- : {}),
241
- };
242
- }
243
- function readSharedAgentConfig(config) {
244
- const middleware = readMiddlewareArray(config.middleware);
245
- const backend = typeof config.backend === "string" && config.backend.trim()
246
- ? { ref: config.backend.startsWith("backend/") ? config.backend : `backend/${config.backend.trim()}` }
247
- : typeof config.backend === "object" && config.backend
248
- ? config.backend
249
- : undefined;
250
- const checkpointer = typeof config.checkpointer === "string" && config.checkpointer.trim()
251
- ? { ref: config.checkpointer.startsWith("checkpointer/") ? config.checkpointer : `checkpointer/${config.checkpointer.trim()}` }
252
- : (typeof config.checkpointer === "object" && config.checkpointer) || typeof config.checkpointer === "boolean"
253
- ? config.checkpointer
254
- : undefined;
255
- const store = typeof config.store === "string" && config.store.trim()
256
- ? { ref: config.store.startsWith("store/") ? config.store : `store/${config.store.trim()}` }
257
- : typeof config.store === "object" && config.store
258
- ? config.store
259
- : undefined;
260
- return {
261
- ...((typeof config.systemPrompt === "string" && config.systemPrompt)
262
- || (typeof config.systemPrompt === "object" && config.systemPrompt && !Array.isArray(config.systemPrompt))
263
- ? { systemPrompt: cloneConfigValue(config.systemPrompt) }
264
- : {}),
265
- ...(checkpointer !== undefined ? { checkpointer } : {}),
266
- ...(typeof config.interruptOn === "object" && config.interruptOn ? { interruptOn: config.interruptOn } : {}),
267
- ...(config.stateSchema !== undefined ? { stateSchema: config.stateSchema } : {}),
268
- ...(config.responseFormat !== undefined ? { responseFormat: config.responseFormat } : {}),
269
- ...(typeof config.responseFormatRef === "string" && config.responseFormatRef.trim()
270
- ? {
271
- responseFormatRef: config.responseFormatRef.startsWith("response-format/")
272
- ? config.responseFormatRef
273
- : `response-format/${config.responseFormatRef.trim()}`,
274
- }
275
- : {}),
276
- ...(config.contextSchema !== undefined ? { contextSchema: config.contextSchema } : {}),
277
- ...(config.interactionMode === "stream" || config.interactionMode === "invoke" ? { interactionMode: config.interactionMode } : {}),
278
- ...(config.includeAgentName === "inline" ? { includeAgentName: "inline" } : {}),
279
- ...(config.version === "v1" || config.version === "v2" ? { version: config.version } : {}),
280
- ...(typeof config.filesystem === "object" && config.filesystem ? { filesystem: config.filesystem } : {}),
281
- ...(typeof config.executionContract === "object" && config.executionContract ? { executionContract: config.executionContract } : {}),
282
- ...(backend ? { backend } : {}),
283
- ...(store ? { store } : {}),
284
- ...(middleware ? { middleware } : {}),
285
- };
286
- }
287
- function readAgentConfig(item, options = {}) {
288
- const config = readExecutionAgentConfig(item);
289
- const passthrough = readPassthroughConfig(config, [...CONSUMED_AGENT_CONFIG_KEYS]);
290
- return {
291
- ...readSharedAgentConfig(config),
292
- ...readSharedAgentConfigFields(config, { includeDelegationControls: options.includeDelegationControls }),
293
- ...(passthrough ? { passthrough } : {}),
294
- };
295
- }
296
- export function parseAgentItem(item, sourcePath) {
297
- const normalizedItem = normalizeAgentItemForMerge(item);
298
- const moduleRoot = moduleRootForSourcePath(sourcePath, "agents");
299
- const subagentRefs = readExecutionValue(normalizedItem, "subagents", readRefArray);
300
- const toolBindings = readExecutionValue(normalizedItem, "tools", readToolBindingArray);
301
- const subagentPathRefs = readExecutionValue(normalizedItem, "subagents", readPathArray)
302
- .filter((entry) => path.isAbsolute(entry) || entry.startsWith("./") || entry.startsWith("../"))
303
- .map((entry) => resolveModuleRelativePath(entry, moduleRoot));
304
- const asyncSubagents = readExecutionValue(normalizedItem, "subagents", readAsyncSubAgentArray);
305
- const executionMode = String(resolveExecutionBackend(normalizedItem) ?? "deepagent");
306
- const runtime = readRuntimeConfig(normalizedItem);
307
- return {
308
- id: String(normalizedItem.id),
309
- executionMode: executionMode,
310
- runtimeMemory: readRuntimeMemoryConfig(normalizedItem, runtime),
311
- proceduralMemory: readProceduralMemoryConfig(normalizedItem, runtime),
312
- capabilities: readCapabilities(normalizedItem.capabilities) ?? (executionMode === "deepagent"
313
- ? { delegation: true, memory: true }
314
- : { delegation: true, memory: true }),
315
- description: String(normalizedItem.description ?? ""),
316
- modelRef: readExecutionValue(normalizedItem, "modelRef", readSingleRef) ?? "",
317
- runtimeRoot: typeof runtime?.runtimeRoot === "string" ? runtime.runtimeRoot : undefined,
318
- applicationRoot: typeof runtime?.applicationRoot === "string" ? runtime.applicationRoot : undefined,
319
- dataRoot: typeof runtime?.dataRoot === "string" ? runtime.dataRoot : undefined,
320
- runtimeProfile: typeof runtime?.profile === "string" ? runtime.profile : undefined,
321
- toolRefs: toolBindings.map((binding) => binding.ref),
322
- toolBindings,
323
- inlineTools: undefined,
324
- mcpServers: readExecutionValue(normalizedItem, "mcpServers", readMcpServerArray),
325
- skillPathRefs: readExecutionValue(normalizedItem, "skills", (value) => readPrefixedRefArray(value, "skill")),
326
- memorySources: readExecutionValue(normalizedItem, "memory", readPathArray).map((entry) => resolveModuleRelativePath(entry, moduleRoot)),
327
- subagentRefs,
328
- subagentPathRefs,
329
- asyncSubagents,
330
- langchainAgentConfig: normalizeModuleAgentConfig(readAgentConfig(normalizedItem, {
331
- includeDelegationControls: executionMode === "langchain-v1",
332
- }), moduleRoot),
333
- deepAgentConfig: normalizeModuleAgentConfig(readAgentConfig(normalizedItem, {
334
- includeObjectBackend: true,
335
- includeDelegationControls: false,
336
- }), moduleRoot),
337
- sourcePath,
338
- };
339
- }
340
- function parseWorkspaceObject(item, sourcePath) {
341
- if (typeof item.id !== "string") {
342
- return null;
343
- }
344
- const inferredKind = typeof item.kind === "string"
345
- ? item.kind
346
- : path.basename(sourcePath).replace(/\.(yaml|yml|json)$/i, "");
347
- if (!inferredKind) {
348
- return null;
349
- }
350
- return {
351
- id: item.id,
352
- kind: inferredKind,
353
- sourcePath,
354
- value: item,
355
- };
356
- }
357
- function mergeValues(base, override) {
358
- if (override === undefined) {
359
- return base;
360
- }
361
- if (Array.isArray(base) && Array.isArray(override)) {
362
- return override;
363
- }
364
- if (typeof base === "object" && base && typeof override === "object" && override && !Array.isArray(base) && !Array.isArray(override)) {
365
- const merged = { ...base };
366
- for (const [key, value] of Object.entries(override)) {
367
- merged[key] = key in merged ? mergeValues(merged[key], value) : value;
368
- }
369
- return merged;
370
- }
371
- return override;
372
- }
373
- function mergeRawItemRecord(records, key, item, sourcePath) {
374
- const current = records.get(key);
375
- const mergedItem = current ? mergeValues(current.item, item) : item;
376
- const kind = typeof mergedItem.kind === "string" ? mergedItem.kind : undefined;
377
- const type = typeof mergedItem.type === "string" ? mergedItem.type : undefined;
378
- const resolvedSourcePath = current &&
379
- kind === "tool" &&
380
- type === "function" &&
381
- isSupportedToolModulePath(current.sourcePath) &&
382
- !isSupportedToolModulePath(sourcePath)
383
- ? current.sourcePath
384
- : sourcePath;
385
- const mergedRecord = {
386
- item: mergedItem,
387
- sourcePath: resolvedSourcePath,
388
- };
389
- records.set(key, mergedRecord);
390
- return mergedRecord;
391
- }
392
- function mergeAgentRecord(records, item, sourcePath) {
393
- const normalizedItem = normalizeAgentItemForMerge(item);
394
- const id = typeof normalizedItem.id === "string" ? normalizedItem.id : undefined;
395
- if (!id) {
396
- return null;
397
- }
398
- const current = records.get(id);
399
- const incomingHasSystemPrompt = normalizedItem.systemPrompt !== undefined;
400
- const currentSystemPrompt = current?.item.systemPrompt;
401
- const currentCarriesRelativePromptPath = typeof currentSystemPrompt === "object"
402
- && currentSystemPrompt !== null
403
- && !Array.isArray(currentSystemPrompt)
404
- && typeof currentSystemPrompt.path === "string"
405
- && !!currentSystemPrompt.path.trim()
406
- && !path.isAbsolute(currentSystemPrompt.path);
407
- if (current && currentCarriesRelativePromptPath && !incomingHasSystemPrompt) {
408
- const currentPromptConfig = currentSystemPrompt;
409
- const absolutizedCurrent = {
410
- ...current.item,
411
- systemPrompt: {
412
- ...currentPromptConfig,
413
- path: path.resolve(path.dirname(current.sourcePath), currentPromptConfig.path),
414
- },
415
- };
416
- const mergedRecord = {
417
- item: mergeValues(absolutizedCurrent, normalizedItem),
418
- sourcePath,
419
- };
420
- records.set(id, mergedRecord);
421
- return mergedRecord;
422
- }
423
- return mergeRawItemRecord(records, id, normalizedItem, sourcePath);
424
- }
425
- function mergeWorkspaceObjectRecord(records, workspaceObject, item, sourcePath) {
426
- mergeRawItemRecord(records, `${workspaceObject.kind}/${workspaceObject.id}`, item, sourcePath);
427
- }
428
- async function loadModuleAgentsForRoot(root, mergedAgents) {
429
- const modulesRoot = moduleCollectionRoot(root, "agents");
430
- if (!(await fileExists(modulesRoot))) {
431
- return;
432
- }
433
- const entries = await readdir(modulesRoot, { withFileTypes: true });
434
- for (const entry of entries.filter((candidate) => candidate.isDirectory()).sort((left, right) => left.name.localeCompare(right.name))) {
435
- const moduleRoot = path.join(modulesRoot, entry.name);
436
- for (const { item, sourcePath } of await readNamedYamlItems(moduleRoot, [...MODULE_AGENT_FILENAMES])) {
437
- const normalizedItem = typeof item.id === "string" && item.id.trim() ? item : { ...item, id: entry.name };
438
- if (!isAgentKind(normalizedItem.kind)) {
439
- continue;
440
- }
441
- mergeAgentRecord(mergedAgents, normalizedItem, sourcePath);
442
- }
443
- }
444
- }
445
- function getMergedToolModuleDiscoveryScope(mergedObjects) {
446
- const runtimeDefaults = mergedObjects.get("runtime/default")?.item;
447
- const toolModuleDiscovery = typeof runtimeDefaults?.toolModuleDiscovery === "object" && runtimeDefaults.toolModuleDiscovery
448
- ? runtimeDefaults.toolModuleDiscovery
449
- : {};
450
- return toolModuleDiscovery.scope === "top-level" ? "top-level" : "recursive";
451
- }
452
- async function loadConventionalObjectsForRoot(root, runtimeRoot, mergedObjects, toolModuleDiscoveryScope) {
453
- const runtimeDefaults = mergedObjects.get("runtime/default")?.item;
454
- const configuredToolRoots = readRuntimeSources(runtimeDefaults).tools
455
- .filter((source) => isFileSourceUri(source))
456
- .map((source) => resolveFileSourcePath(source, runtimeRoot));
457
- const conventionalToolRoots = conventionalObjectRoots(root);
458
- const objectRoots = root === runtimeRoot
459
- ? Array.from(new Set([
460
- ...conventionalToolRoots,
461
- ...configuredToolRoots,
462
- ]))
463
- : conventionalToolRoots;
464
- for (const objectRoot of objectRoots) {
465
- for (const { item, sourcePath } of await readYamlItemsIgnoringNodeModules(objectRoot)) {
466
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
467
- if (!workspaceObject) {
468
- continue;
469
- }
470
- mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
471
- }
472
- for (const { item, sourcePath } of await readToolModuleItems(objectRoot, { scope: toolModuleDiscoveryScope })) {
473
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
474
- if (!workspaceObject) {
475
- continue;
476
- }
477
- mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
478
- }
479
- }
480
- }
481
- async function readYamlItemsIgnoringNodeModules(root) {
482
- if (!(await fileExists(root))) {
483
- return [];
484
- }
485
- const records = [];
486
- const pending = [root];
487
- while (pending.length > 0) {
488
- const current = pending.shift();
489
- const entries = await readdir(current, { withFileTypes: true });
490
- for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
491
- const entryPath = path.join(current, entry.name);
492
- const entryType = await resolveScanEntryType(entryPath, entry);
493
- if (entryType === "directory") {
494
- if (shouldSkipScanDirectory(entry.name)) {
495
- continue;
496
- }
497
- pending.push(entryPath);
498
- continue;
499
- }
500
- if (entryType !== "file" || (!entry.name.endsWith(".yaml") && !entry.name.endsWith(".yml"))) {
501
- continue;
502
- }
503
- records.push(...(await readNamedYamlItems(current, [entry.name])));
504
- }
505
- }
506
- return records;
507
- }
508
- async function readModuleToolItems(root) {
509
- const modulesRoot = moduleCollectionRoot(root, "tools");
510
- if (!(await fileExists(modulesRoot))) {
511
- return [];
512
- }
513
- const entries = await readdir(modulesRoot, { withFileTypes: true });
514
- const records = [];
515
- for (const entry of entries.filter((candidate) => candidate.isDirectory()).sort((left, right) => left.name.localeCompare(right.name))) {
516
- const moduleRoot = path.join(modulesRoot, entry.name);
517
- for (const { item, sourcePath } of await readNamedYamlItems(moduleRoot, [...MODULE_TOOL_FILENAMES])) {
518
- const normalizedItem = typeof item.id === "string" && item.id.trim() ? item : { ...item, id: entry.name };
519
- const workspaceObject = parseWorkspaceObject(normalizedItem, sourcePath);
520
- if (!workspaceObject || workspaceObject.kind !== "tool") {
521
- continue;
522
- }
523
- const implementation = asObject(normalizedItem.implementation);
524
- const explicitPath = typeof implementation?.path === "string" ? path.resolve(moduleRoot, implementation.path) : undefined;
525
- const discoveredPath = explicitPath ??
526
- MODULE_TOOL_ENTRY_FILENAMES.map((filename) => path.join(moduleRoot, filename)).find((candidate) => existsSync(candidate));
527
- const inferredType = typeof normalizedItem.type === "string"
528
- ? normalizedItem.type
529
- : normalizedItem.refs !== undefined || normalizedItem.bundle !== undefined
530
- ? "bundle"
531
- : normalizedItem.providerTool !== undefined || normalizedItem.provider !== undefined
532
- ? "provider"
533
- : normalizedItem.backend !== undefined || normalizedItem.operation !== undefined
534
- ? "backend"
535
- : normalizedItem.mcp !== undefined
536
- ? "mcp"
537
- : "function";
538
- if (inferredType === "function" && !discoveredPath) {
539
- throw new Error(`Module tool ${workspaceObject.id} must define implementation.path or provide index.mjs|index.js|index.cjs`);
540
- }
541
- const implementationName = typeof normalizedItem.implementationName === "string" && normalizedItem.implementationName.trim().length > 0
542
- ? normalizedItem.implementationName.trim()
543
- : typeof implementation?.export === "string" && implementation.export.trim().length > 0
544
- ? implementation.export.trim()
545
- : workspaceObject.id;
546
- const schemaMetadata = inferredType === "function" && discoveredPath
547
- ? await readModuleToolSchemaMetadata({
548
- sourcePath: discoveredPath,
549
- implementationName,
550
- })
551
- : { hasModuleSchema: false };
552
- records.push({
553
- item: {
554
- ...normalizedItem,
555
- ...(typeof implementation?.export === "string" && !normalizedItem.implementationName ? { implementationName } : {}),
556
- ...(schemaMetadata.hasModuleSchema ? { hasModuleSchema: true } : {}),
557
- },
558
- sourcePath: discoveredPath ?? sourcePath,
559
- });
560
- }
561
- }
562
- return records;
563
- }
564
- function findToolPackageRoot(startPath) {
565
- let current = path.dirname(startPath);
566
- for (;;) {
567
- const packageJsonPath = path.join(current, "package.json");
568
- if (existsSync(packageJsonPath)) {
569
- return current;
570
- }
571
- const parent = path.dirname(current);
572
- if (parent === current) {
573
- return path.dirname(startPath);
574
- }
575
- current = parent;
576
- }
577
- }
578
- async function readModuleToolSchemaMetadata(input) {
579
- if (!isSupportedToolModulePath(input.sourcePath)) {
580
- return { hasModuleSchema: false };
581
- }
582
- const packageRoot = findToolPackageRoot(input.sourcePath);
583
- const isolatedSourcePath = await resolveIsolatedResourceModulePath(packageRoot, input.sourcePath);
584
- const imported = await import(pathToFileURL(isolatedSourcePath).href);
585
- const definition = loadToolModuleDefinition(imported, input.implementationName);
586
- return {
587
- hasModuleSchema: definition.hasModuleSchema,
588
- };
589
- }
590
- async function loadModuleObjectsForRoot(root, mergedObjects) {
591
- for (const { item, sourcePath } of await readModuleToolItems(root)) {
592
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
593
- if (!workspaceObject) {
594
- continue;
595
- }
596
- mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
597
- }
598
- }
599
- async function loadConfigYamlForRoot(root, configRoot, mergedAgents, mergedObjects) {
600
- if (!conventionalConfigRoot(root)) {
601
- return;
602
- }
603
- for (const { item, sourcePath } of await readYamlItems(configRoot, undefined, { recursive: true })) {
604
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
605
- if (!workspaceObject) {
606
- continue;
607
- }
608
- if (isAgentKind(workspaceObject.kind)) {
609
- mergeAgentRecord(mergedAgents, item, sourcePath);
610
- continue;
611
- }
612
- mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
613
- }
614
- }
615
- async function loadRootObjects(root, mergedObjects) {
616
- for (const { item, sourcePath } of (await readYamlItems(root)).filter(({ sourcePath: fullPath }) => !fullPath.includes(`${path.sep}config${path.sep}`) &&
617
- !fullPath.includes(`${path.sep}resources${path.sep}`) &&
618
- !fullPath.includes(`${path.sep}agents${path.sep}`) &&
619
- !CONVENTIONAL_OBJECT_DIRECTORIES.some((directory) => fullPath.includes(`${path.sep}${directory}${path.sep}`)))) {
620
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
621
- if (!workspaceObject) {
622
- continue;
623
- }
624
- if (workspaceObject.kind === "tool" || workspaceObject.kind === "mcp" || workspaceObject.kind === "model") {
625
- continue;
626
- }
627
- mergeWorkspaceObjectRecord(mergedObjects, workspaceObject, item, sourcePath);
628
- }
629
- }
630
- function isAgentKind(kind) {
631
- return kind === "agent";
632
- }
633
- export async function readToolModuleItems(root, options = {}) {
634
- if (!(await fileExists(root))) {
635
- return [];
636
- }
637
- const scope = options.scope === "top-level" ? "top-level" : "recursive";
638
- const files = [];
639
- const pending = [root];
640
- while (pending.length > 0) {
641
- const current = pending.shift();
642
- const entries = await readdir(current, { withFileTypes: true });
643
- for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
644
- const entryPath = path.join(current, entry.name);
645
- const entryType = await resolveScanEntryType(entryPath, entry);
646
- if (entryType === "directory") {
647
- if (shouldSkipScanDirectory(entry.name) || scope === "top-level") {
648
- continue;
649
- }
650
- pending.push(entryPath);
651
- continue;
652
- }
653
- if (entryType === "file" && isSupportedToolModulePath(entry.name)) {
654
- files.push(entryPath);
655
- }
656
- }
657
- }
658
- const records = [];
659
- for (const filePath of files) {
660
- const sourceText = await readFile(filePath, "utf8");
661
- const packageRoot = findToolPackageRoot(filePath);
662
- const isolatedSourcePath = await resolveIsolatedResourceModulePath(packageRoot, filePath);
663
- const imported = await import(pathToFileURL(isolatedSourcePath).href);
664
- const definitions = discoverToolModuleDefinitions(sourceText, imported);
665
- if (definitions.length === 0) {
666
- continue;
667
- }
668
- for (const definition of definitions) {
669
- records.push({
670
- item: {
671
- kind: "tool",
672
- id: definition.implementationName,
673
- type: "function",
674
- name: definition.implementationName,
675
- description: definition.description,
676
- implementationName: definition.implementationName,
677
- hasModuleSchema: definition.hasModuleSchema,
678
- ...(definition.modelSchema ? { modelSchema: definition.modelSchema } : {}),
679
- ...(definition.retryable !== undefined ? { retryable: definition.retryable } : {}),
680
- ...(definition.memory ? { config: { memory: definition.memory } } : {}),
681
- },
682
- sourcePath: filePath,
683
- });
684
- }
685
- }
686
- return records;
687
- }
688
- async function resolveScanEntryType(entryPath, entry) {
689
- if (entry.isDirectory()) {
690
- return "directory";
691
- }
692
- if (entry.isFile()) {
693
- return "file";
694
- }
695
- if (entry.isSymbolicLink?.()) {
696
- try {
697
- const resolved = await stat(entryPath);
698
- if (resolved.isDirectory()) {
699
- return "directory";
700
- }
701
- if (resolved.isFile()) {
702
- return "file";
703
- }
704
- }
705
- catch {
706
- return "other";
707
- }
708
- }
709
- return "other";
710
- }
711
- function inferExecutionMode(item, current) {
712
- return resolveExecutionBackend(item, current);
713
- }
714
- /**
715
- * Load and merge workspace objects in deterministic order:
716
- * 1) framework workspace defaults
717
- * 2) overlay roots in order
718
- * 3) workspaceRoot
719
- *
720
- * Merge semantics:
721
- * - later sources override earlier sources
722
- * - arrays are replaced, not concatenated
723
- * - plain objects are merged recursively
724
- * - scalars and non-plain objects are replaced
725
- */
726
- export async function loadWorkspaceObjects(workspaceRoot, options = {}) {
727
- const refs = new Map();
728
- const mergedAgents = new Map();
729
- const mergedObjects = new Map();
730
- const defaultRoot = frameworkWorkspaceRoot();
731
- const roots = [defaultRoot, ...(options.overlayRoots ?? []), workspaceRoot];
732
- for (const root of roots) {
733
- const configRoot = conventionalConfigRoot(root) ?? root;
734
- await loadConfigYamlForRoot(root, configRoot, mergedAgents, mergedObjects);
735
- await loadModuleAgentsForRoot(root, mergedAgents);
736
- if (root !== defaultRoot) {
737
- await loadConventionalObjectsForRoot(root, workspaceRoot, mergedObjects, getMergedToolModuleDiscoveryScope(mergedObjects));
738
- }
739
- await loadModuleObjectsForRoot(root, mergedObjects);
740
- await loadRootObjects(root, mergedObjects);
741
- }
742
- const agents = Array.from(mergedAgents.values()).map(({ item, sourcePath }) => parseAgentItem(item, sourcePath));
743
- for (const [ref, { item, sourcePath }] of mergedObjects) {
744
- const workspaceObject = parseWorkspaceObject(item, sourcePath);
745
- if (!workspaceObject) {
746
- continue;
747
- }
748
- refs.set(ref, workspaceObject);
749
- }
750
- for (const agent of agents) {
751
- refs.set(`agent/${agent.id}`, agent);
752
- }
753
- return { refs, agents };
754
- }
1
+ import u from"node:path";import{existsSync as x}from"node:fs";import{readdir as M,readFile as J,stat as H}from"node:fs/promises";import{pathToFileURL as E}from"node:url";import{resolveIsolatedResourceModulePath as O}from"../resource/isolation.js";import{discoverToolModuleDefinitions as q,isSupportedToolModulePath as b,loadToolModuleDefinition as Q}from"../tooling/module-loader.js";import{fileExists as k,shouldSkipScanDirectory as T}from"../utils/fs.js";import{isFileSourceUri as X,readRuntimeSources as Z,resolveFileSourcePath as ee}from"./support/source-protocols.js";import{readNamedYamlItems as w,readYamlItems as F}from"./yaml-object-reader.js";import{CONVENTIONAL_OBJECT_DIRECTORIES as te,MODULE_AGENT_FILENAMES as oe,MODULE_TOOL_ENTRY_FILENAMES as re,MODULE_TOOL_FILENAMES as ne,conventionalConfigRoot as D,conventionalObjectRoots as ie,frameworkWorkspaceRoot as se,moduleCollectionRoot as N,moduleRootForSourcePath as ae,resolveModuleRelativePath as S}from"./object-loader-paths.js";import{asMutableObject as A,asObject as ce,cloneConfigValue as f,readAsyncSubAgentArray as me,readCapabilities as de,readMcpServerArray as ue,readMiddlewareArray as le,readPathArray as I,readPrefixedRefArray as pe,readRefArray as fe,readSingleRef as ye,readToolBindingArray as he}from"./object-loader-readers.js";import{normalizeYamlItem as Ze,readYamlItems as et}from"./yaml-object-reader.js";const ge=["systemPrompt","checkpointer","interruptOn","stateSchema","responseFormat","responseFormatRef","contextSchema","includeAgentName","version","middleware","backend","store","runtimeMemory","proceduralMemory","taskDescription","generalPurposeAgent","filesystem","builtinTools","interactionMode","executionContract"],Me=["id","kind","description","capabilities","runtime","executionMode","sourcePath"],be=["backend","modelRef","tools","skills","memory","subagents","mcpServers","config"],ke=["systemPrompt","checkpointer","interruptOn","stateSchema","responseFormat","responseFormatRef","contextSchema","includeAgentName","version","middleware","store","taskDescription","generalPurposeAgent","filesystem","builtinTools","interactionMode","executionContract"];function $(e){const o={...e};if(o.execution!==void 0)throw new Error("Agent spec.execution is no longer supported; move backend, modelRef, tools, skills, memory, subagents, mcpServers, and config directly under spec");const t=A(o.config),r=_(o);if(t){for(const n of ke)!(n in t)||o[n]!==void 0||(o[n]=f(t[n]),delete t[n]);if(t.runtimeMemory!==void 0&&r?.runtimeMemory===void 0){const n=r??{};n.runtimeMemory=f(t.runtimeMemory),o.runtime=n,delete t.runtimeMemory}if(t.proceduralMemory!==void 0&&r?.proceduralMemory===void 0){const n=A(o.runtime)??r??{};n.proceduralMemory=f(t.proceduralMemory),o.runtime=n,delete t.proceduralMemory}}return t&&Object.keys(t).length>0?o.config=t:delete o.config,o}function P(e){const o=A(e.config)??{},t=Object.fromEntries(Object.entries(e).filter(([r])=>!be.includes(r)&&!Me.includes(r)));return{...o,...t}}function y(e,o,t){return t(e[o])}function _(e){return A(e.runtime)}function Ae(e,o){if(typeof o?.runtimeMemory=="string"&&o.runtimeMemory.trim())return{ref:o.runtimeMemory.startsWith("runtime-memory/")?o.runtimeMemory:`runtime-memory/${o.runtimeMemory.trim()}`};if(typeof o?.runtimeMemory=="object"&&o.runtimeMemory&&!Array.isArray(o.runtimeMemory))return f(o.runtimeMemory);const t=P(e);if(typeof t.runtimeMemory=="string"&&t.runtimeMemory.trim())return{ref:t.runtimeMemory.startsWith("runtime-memory/")?t.runtimeMemory:`runtime-memory/${t.runtimeMemory.trim()}`};if(typeof t.runtimeMemory=="object"&&t.runtimeMemory&&!Array.isArray(t.runtimeMemory))return f(t.runtimeMemory)}function Re(e,o){if(typeof o?.proceduralMemory=="string"&&o.proceduralMemory.trim())return{ref:o.proceduralMemory.startsWith("procedural-memory/")?o.proceduralMemory:`procedural-memory/${o.proceduralMemory.trim()}`};if(typeof o?.proceduralMemory=="object"&&o.proceduralMemory&&!Array.isArray(o.proceduralMemory))return f(o.proceduralMemory);const t=P(e);if(typeof t.proceduralMemory=="string"&&t.proceduralMemory.trim())return{ref:t.proceduralMemory.startsWith("procedural-memory/")?t.proceduralMemory:`procedural-memory/${t.proceduralMemory.trim()}`};if(typeof t.proceduralMemory=="object"&&t.proceduralMemory&&!Array.isArray(t.proceduralMemory))return f(t.proceduralMemory)}function we(e,o){if(!o||typeof e!="object"||e===null||Array.isArray(e))return e;const t={...e};return typeof t.path=="string"&&(t.path=S(t.path,o)),t}function W(e,o){return o?{...e,...e.systemPrompt!==void 0?{systemPrompt:we(e.systemPrompt,o)}:{}}:e}function Se(e,o){const t=Object.fromEntries(Object.entries(e).filter(([r])=>!o.includes(r)).map(([r,n])=>[r,f(n)]));return Object.keys(t).length>0?t:void 0}function L(e,o){if(e.execution!==void 0||o?.execution!==void 0)throw new Error("Agent spec.execution is no longer supported; move backend, modelRef, tools, skills, memory, subagents, mcpServers, and config directly under spec");const t=typeof e.mode=="string"?e.mode:typeof o?.mode=="string"?o.mode:void 0;if(typeof t=="string"&&t.trim().length>0)throw new Error("Agent mode is no longer supported; use backend");const r=typeof e.backend=="string"?e.backend.trim().toLowerCase():typeof o?.backend=="string"?o.backend.trim().toLowerCase():void 0;if(r==="langchain-v1")return"langchain-v1";if(r==="deepagent")return"deepagent";if(r==="langgraph")throw new Error("Agent backend=langgraph is no longer supported; use backend=langchain-v1 or backend=deepagent")}function Pe(e,o={}){return{...typeof e.store=="object"&&e.store?{store:e.store}:{},...typeof e.builtinTools=="object"&&e.builtinTools?{builtinTools:f(e.builtinTools)}:{},...o.includeDelegationControls&&typeof e.taskDescription=="string"&&e.taskDescription.trim()?{taskDescription:e.taskDescription}:{},...o.includeDelegationControls&&typeof e.generalPurposeAgent=="boolean"?{generalPurposeAgent:e.generalPurposeAgent}:{}}}function je(e){const o=le(e.middleware),t=typeof e.backend=="string"&&e.backend.trim()?{ref:e.backend.startsWith("backend/")?e.backend:`backend/${e.backend.trim()}`}:typeof e.backend=="object"&&e.backend?e.backend:void 0,r=typeof e.checkpointer=="string"&&e.checkpointer.trim()?{ref:e.checkpointer.startsWith("checkpointer/")?e.checkpointer:`checkpointer/${e.checkpointer.trim()}`}:typeof e.checkpointer=="object"&&e.checkpointer||typeof e.checkpointer=="boolean"?e.checkpointer:void 0,n=typeof e.store=="string"&&e.store.trim()?{ref:e.store.startsWith("store/")?e.store:`store/${e.store.trim()}`}:typeof e.store=="object"&&e.store?e.store:void 0;return{...typeof e.systemPrompt=="string"&&e.systemPrompt||typeof e.systemPrompt=="object"&&e.systemPrompt&&!Array.isArray(e.systemPrompt)?{systemPrompt:f(e.systemPrompt)}:{},...r!==void 0?{checkpointer:r}:{},...typeof e.interruptOn=="object"&&e.interruptOn?{interruptOn:e.interruptOn}:{},...e.stateSchema!==void 0?{stateSchema:e.stateSchema}:{},...e.responseFormat!==void 0?{responseFormat:e.responseFormat}:{},...typeof e.responseFormatRef=="string"&&e.responseFormatRef.trim()?{responseFormatRef:e.responseFormatRef.startsWith("response-format/")?e.responseFormatRef:`response-format/${e.responseFormatRef.trim()}`}:{},...e.contextSchema!==void 0?{contextSchema:e.contextSchema}:{},...e.interactionMode==="stream"||e.interactionMode==="invoke"?{interactionMode:e.interactionMode}:{},...e.includeAgentName==="inline"?{includeAgentName:"inline"}:{},...e.version==="v1"||e.version==="v2"?{version:e.version}:{},...typeof e.filesystem=="object"&&e.filesystem?{filesystem:e.filesystem}:{},...typeof e.executionContract=="object"&&e.executionContract?{executionContract:e.executionContract}:{},...t?{backend:t}:{},...n?{store:n}:{},...o?{middleware:o}:{}}}function Y(e,o={}){const t=P(e),r=Se(t,[...ge]);return{...je(t),...Pe(t,{includeDelegationControls:o.includeDelegationControls}),...r?{passthrough:r}:{}}}function ve(e,o){const t=$(e),r=ae(o,"agents"),n=y(t,"subagents",fe),s=y(t,"tools",he),a=y(t,"subagents",I).filter(m=>u.isAbsolute(m)||m.startsWith("./")||m.startsWith("../")).map(m=>S(m,r)),d=y(t,"subagents",me),i=String(L(t)??"deepagent"),c=_(t);return{id:String(t.id),executionMode:i,runtimeMemory:Ae(t,c),proceduralMemory:Re(t,c),capabilities:de(t.capabilities)??(i==="deepagent"?{delegation:!0,memory:!0}:{delegation:!0,memory:!0}),description:String(t.description??""),modelRef:y(t,"modelRef",ye)??"",runtimeRoot:typeof c?.runtimeRoot=="string"?c.runtimeRoot:void 0,applicationRoot:typeof c?.applicationRoot=="string"?c.applicationRoot:void 0,dataRoot:typeof c?.dataRoot=="string"?c.dataRoot:void 0,runtimeProfile:typeof c?.profile=="string"?c.profile:void 0,toolRefs:s.map(m=>m.ref),toolBindings:s,inlineTools:void 0,mcpServers:y(t,"mcpServers",ue),skillPathRefs:y(t,"skills",m=>pe(m,"skill")),memorySources:y(t,"memory",I).map(m=>S(m,r)),subagentRefs:n,subagentPathRefs:a,asyncSubagents:d,langchainAgentConfig:W(Y(t,{includeDelegationControls:i==="langchain-v1"}),r),deepAgentConfig:W(Y(t,{includeObjectBackend:!0,includeDelegationControls:!1}),r),sourcePath:o}}function h(e,o){if(typeof e.id!="string")return null;const t=typeof e.kind=="string"?e.kind:u.basename(o).replace(/\.(yaml|yml|json)$/i,"");return t?{id:e.id,kind:t,sourcePath:o,value:e}:null}function j(e,o){if(o===void 0)return e;if(Array.isArray(e)&&Array.isArray(o))return o;if(typeof e=="object"&&e&&typeof o=="object"&&o&&!Array.isArray(e)&&!Array.isArray(o)){const t={...e};for(const[r,n]of Object.entries(o))t[r]=r in t?j(t[r],n):n;return t}return o}function z(e,o,t,r){const n=e.get(o),s=n?j(n.item,t):t,a=typeof s.kind=="string"?s.kind:void 0,d=typeof s.type=="string"?s.type:void 0,i=n&&a==="tool"&&d==="function"&&b(n.sourcePath)&&!b(r)?n.sourcePath:r,c={item:s,sourcePath:i};return e.set(o,c),c}function G(e,o,t){const r=$(o),n=typeof r.id=="string"?r.id:void 0;if(!n)return null;const s=e.get(n),a=r.systemPrompt!==void 0,d=s?.item.systemPrompt,i=typeof d=="object"&&d!==null&&!Array.isArray(d)&&typeof d.path=="string"&&!!d.path.trim()&&!u.isAbsolute(d.path);if(s&&i&&!a){const c=d,m={...s.item,systemPrompt:{...c,path:u.resolve(u.dirname(s.sourcePath),c.path)}},p={item:j(m,r),sourcePath:t};return e.set(n,p),p}return z(e,n,r,t)}function g(e,o,t,r){z(e,`${o.kind}/${o.id}`,t,r)}async function Ce(e,o){const t=N(e,"agents");if(!await k(t))return;const r=await M(t,{withFileTypes:!0});for(const n of r.filter(s=>s.isDirectory()).sort((s,a)=>s.name.localeCompare(a.name))){const s=u.join(t,n.name);for(const{item:a,sourcePath:d}of await w(s,[...oe])){const i=typeof a.id=="string"&&a.id.trim()?a:{...a,id:n.name};U(i.kind)&&G(o,i,d)}}}function xe(e){const o=e.get("runtime/default")?.item;return(typeof o?.toolModuleDiscovery=="object"&&o.toolModuleDiscovery?o.toolModuleDiscovery:{}).scope==="top-level"?"top-level":"recursive"}async function Ee(e,o,t,r){const n=t.get("runtime/default")?.item,s=Z(n).tools.filter(i=>X(i)).map(i=>ee(i,o)),a=ie(e),d=e===o?Array.from(new Set([...a,...s])):a;for(const i of d){for(const{item:c,sourcePath:m}of await Oe(i)){const p=h(c,m);p&&g(t,p,c,m)}for(const{item:c,sourcePath:m}of await $e(i,{scope:r})){const p=h(c,m);p&&g(t,p,c,m)}}}async function Oe(e){if(!await k(e))return[];const o=[],t=[e];for(;t.length>0;){const r=t.shift(),n=await M(r,{withFileTypes:!0});for(const s of n.sort((a,d)=>a.name.localeCompare(d.name))){const a=u.join(r,s.name),d=await B(a,s);if(d==="directory"){if(T(s.name))continue;t.push(a);continue}d!=="file"||!s.name.endsWith(".yaml")&&!s.name.endsWith(".yml")||o.push(...await w(r,[s.name]))}}return o}async function Te(e){const o=N(e,"tools");if(!await k(o))return[];const t=await M(o,{withFileTypes:!0}),r=[];for(const n of t.filter(s=>s.isDirectory()).sort((s,a)=>s.name.localeCompare(a.name))){const s=u.join(o,n.name);for(const{item:a,sourcePath:d}of await w(s,[...ne])){const i=typeof a.id=="string"&&a.id.trim()?a:{...a,id:n.name},c=h(i,d);if(!c||c.kind!=="tool")continue;const m=ce(i.implementation),l=(typeof m?.path=="string"?u.resolve(s,m.path):void 0)??re.map(R=>u.join(s,R)).find(R=>x(R)),v=typeof i.type=="string"?i.type:i.refs!==void 0||i.bundle!==void 0?"bundle":i.providerTool!==void 0||i.provider!==void 0?"provider":i.backend!==void 0||i.operation!==void 0?"backend":i.mcp!==void 0?"mcp":"function";if(v==="function"&&!l)throw new Error(`Module tool ${c.id} must define implementation.path or provide index.mjs|index.js|index.cjs`);const C=typeof i.implementationName=="string"&&i.implementationName.trim().length>0?i.implementationName.trim():typeof m?.export=="string"&&m.export.trim().length>0?m.export.trim():c.id,V=v==="function"&&l?await Fe({sourcePath:l,implementationName:C}):{hasModuleSchema:!1};r.push({item:{...i,...typeof m?.export=="string"&&!i.implementationName?{implementationName:C}:{},...V.hasModuleSchema?{hasModuleSchema:!0}:{}},sourcePath:l??d})}}return r}function K(e){let o=u.dirname(e);for(;;){const t=u.join(o,"package.json");if(x(t))return o;const r=u.dirname(o);if(r===o)return u.dirname(e);o=r}}async function Fe(e){if(!b(e.sourcePath))return{hasModuleSchema:!1};const o=K(e.sourcePath),t=await O(o,e.sourcePath),r=await import(E(t).href);return{hasModuleSchema:Q(r,e.implementationName).hasModuleSchema}}async function De(e,o){for(const{item:t,sourcePath:r}of await Te(e)){const n=h(t,r);n&&g(o,n,t,r)}}async function Ne(e,o,t,r){if(D(e))for(const{item:n,sourcePath:s}of await F(o,void 0,{recursive:!0})){const a=h(n,s);if(a){if(U(a.kind)){G(t,n,s);continue}g(r,a,n,s)}}}async function Ie(e,o){for(const{item:t,sourcePath:r}of(await F(e)).filter(({sourcePath:n})=>!n.includes(`${u.sep}config${u.sep}`)&&!n.includes(`${u.sep}resources${u.sep}`)&&!n.includes(`${u.sep}agents${u.sep}`)&&!te.some(s=>n.includes(`${u.sep}${s}${u.sep}`)))){const n=h(t,r);n&&(n.kind==="tool"||n.kind==="mcp"||n.kind==="model"||g(o,n,t,r))}}function U(e){return e==="agent"}async function $e(e,o={}){if(!await k(e))return[];const t=o.scope==="top-level"?"top-level":"recursive",r=[],n=[e];for(;n.length>0;){const a=n.shift(),d=await M(a,{withFileTypes:!0});for(const i of d.sort((c,m)=>c.name.localeCompare(m.name))){const c=u.join(a,i.name),m=await B(c,i);if(m==="directory"){if(T(i.name)||t==="top-level")continue;n.push(c);continue}m==="file"&&b(i.name)&&r.push(c)}}const s=[];for(const a of r){const d=await J(a,"utf8"),i=K(a),c=await O(i,a),m=await import(E(c).href),p=q(d,m);if(p.length!==0)for(const l of p)s.push({item:{kind:"tool",id:l.implementationName,type:"function",name:l.implementationName,description:l.description,implementationName:l.implementationName,hasModuleSchema:l.hasModuleSchema,...l.modelSchema?{modelSchema:l.modelSchema}:{},...l.retryable!==void 0?{retryable:l.retryable}:{},...l.memory?{config:{memory:l.memory}}:{}},sourcePath:a})}return s}async function B(e,o){if(o.isDirectory())return"directory";if(o.isFile())return"file";if(o.isSymbolicLink?.())try{const t=await H(e);if(t.isDirectory())return"directory";if(t.isFile())return"file"}catch{return"other"}return"other"}function He(e,o){return L(e,o)}async function qe(e,o={}){const t=new Map,r=new Map,n=new Map,s=se(),a=[s,...o.overlayRoots??[],e];for(const i of a){const c=D(i)??i;await Ne(i,c,r,n),await Ce(i,r),i!==s&&await Ee(i,e,n,xe(n)),await De(i,n),await Ie(i,n)}const d=Array.from(r.values()).map(({item:i,sourcePath:c})=>ve(i,c));for(const[i,{item:c,sourcePath:m}]of n){const p=h(c,m);p&&t.set(i,p)}for(const i of d)t.set(`agent/${i.id}`,i);return{refs:t,agents:d}}export{qe as loadWorkspaceObjects,Ze as normalizeYamlItem,ve as parseAgentItem,$e as readToolModuleItems,et as readYamlItems};