veryfront 0.1.759 → 0.1.762

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 (211) hide show
  1. package/esm/cli/commands/init/catalog.d.ts.map +1 -1
  2. package/esm/cli/commands/init/catalog.js +116 -1
  3. package/esm/cli/shared/config.d.ts +0 -6
  4. package/esm/cli/shared/config.d.ts.map +1 -1
  5. package/esm/cli/shared/config.js +64 -8
  6. package/esm/cli/templates/integration-loader.d.ts.map +1 -1
  7. package/esm/cli/templates/integration-loader.js +2 -52
  8. package/esm/deno.d.ts +5 -16
  9. package/esm/deno.js +6 -17
  10. package/esm/src/agent/ag-ui/tool-shared.d.ts.map +1 -1
  11. package/esm/src/agent/ag-ui/tool-shared.js +7 -1
  12. package/esm/src/agent/child-run/invoke-agent-child-runs.d.ts +0 -1
  13. package/esm/src/agent/child-run/invoke-agent-child-runs.d.ts.map +1 -1
  14. package/esm/src/agent/child-run/invoke-agent-child-runs.js +0 -1
  15. package/esm/src/agent/conversation/bootstrap.d.ts +0 -1
  16. package/esm/src/agent/conversation/bootstrap.d.ts.map +1 -1
  17. package/esm/src/agent/conversation/bootstrap.js +0 -1
  18. package/esm/src/agent/conversation/durable.d.ts +0 -1
  19. package/esm/src/agent/conversation/durable.d.ts.map +1 -1
  20. package/esm/src/agent/conversation/durable.js +0 -1
  21. package/esm/src/agent/factory.d.ts.map +1 -1
  22. package/esm/src/agent/factory.js +7 -1
  23. package/esm/src/agent/hosted/chat-preparation.d.ts +1 -1
  24. package/esm/src/agent/hosted/chat-preparation.d.ts.map +1 -1
  25. package/esm/src/agent/hosted/chat-preparation.js +17 -3
  26. package/esm/src/agent/hosted/chat-runtime-contract.d.ts +2 -0
  27. package/esm/src/agent/hosted/chat-runtime-contract.d.ts.map +1 -1
  28. package/esm/src/agent/hosted/default-chat-runtime.d.ts +2 -0
  29. package/esm/src/agent/hosted/default-chat-runtime.d.ts.map +1 -1
  30. package/esm/src/agent/hosted/default-chat-runtime.js +1 -0
  31. package/esm/src/agent/hosted/default-project-steering-refresh.js +1 -1
  32. package/esm/src/agent/hosted/project-steering-adapter.d.ts +7 -0
  33. package/esm/src/agent/hosted/project-steering-adapter.d.ts.map +1 -1
  34. package/esm/src/agent/hosted/project-steering-adapter.js +12 -1
  35. package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts +4 -0
  36. package/esm/src/agent/hosted/veryfront-cloud-agent-service.d.ts.map +1 -1
  37. package/esm/src/agent/hosted/veryfront-cloud-agent-service.js +14 -12
  38. package/esm/src/agent/index.d.ts +1 -0
  39. package/esm/src/agent/index.d.ts.map +1 -1
  40. package/esm/src/agent/index.js +1 -0
  41. package/esm/src/agent/project/context.d.ts +2 -0
  42. package/esm/src/agent/project/context.d.ts.map +1 -1
  43. package/esm/src/agent/project/context.js +1 -0
  44. package/esm/src/agent/project/steering-mutation.d.ts.map +1 -1
  45. package/esm/src/agent/project/steering-mutation.js +7 -1
  46. package/esm/src/agent/runtime/agent-definition.d.ts +6 -0
  47. package/esm/src/agent/runtime/agent-definition.d.ts.map +1 -1
  48. package/esm/src/agent/runtime/agent-definition.js +46 -0
  49. package/esm/src/agent/runtime/agent-delegation-names.d.ts +5 -0
  50. package/esm/src/agent/runtime/agent-delegation-names.d.ts.map +1 -0
  51. package/esm/src/agent/runtime/agent-delegation-names.js +8 -0
  52. package/esm/src/agent/runtime/agent-delegation.d.ts +32 -0
  53. package/esm/src/agent/runtime/agent-delegation.d.ts.map +1 -0
  54. package/esm/src/agent/runtime/agent-delegation.js +57 -0
  55. package/esm/src/agent/runtime/agent-markdown-adapter.d.ts.map +1 -1
  56. package/esm/src/agent/runtime/agent-markdown-adapter.js +24 -0
  57. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  58. package/esm/src/agent/runtime/index.js +8 -0
  59. package/esm/src/agent/runtime/local-tool.d.ts +6 -0
  60. package/esm/src/agent/runtime/local-tool.d.ts.map +1 -0
  61. package/esm/src/agent/runtime/local-tool.js +15 -0
  62. package/esm/src/agent/runtime/project-skill-catalog.d.ts.map +1 -1
  63. package/esm/src/agent/runtime/project-skill-catalog.js +67 -0
  64. package/esm/src/agent/runtime/project-skill-loader.d.ts +9 -0
  65. package/esm/src/agent/runtime/project-skill-loader.d.ts.map +1 -1
  66. package/esm/src/agent/runtime/project-skill-loader.js +44 -6
  67. package/esm/src/agent/runtime/skill-metadata.d.ts +23 -0
  68. package/esm/src/agent/runtime/skill-metadata.d.ts.map +1 -1
  69. package/esm/src/agent/runtime/skill-metadata.js +11 -0
  70. package/esm/src/agent/runtime/tool-helpers.d.ts +3 -1
  71. package/esm/src/agent/runtime/tool-helpers.d.ts.map +1 -1
  72. package/esm/src/agent/runtime/tool-helpers.js +45 -11
  73. package/esm/src/agent/service/request-auth-cache.d.ts +0 -1
  74. package/esm/src/agent/service/request-auth-cache.d.ts.map +1 -1
  75. package/esm/src/agent/service/request-auth-cache.js +0 -1
  76. package/esm/src/channels/control-plane.d.ts +1 -0
  77. package/esm/src/channels/control-plane.d.ts.map +1 -1
  78. package/esm/src/channels/control-plane.js +4 -2
  79. package/esm/src/chat/ag-ui.d.ts.map +1 -1
  80. package/esm/src/chat/conversation.d.ts.map +1 -1
  81. package/esm/src/chat/final-step-fallback.d.ts.map +1 -1
  82. package/esm/src/chat/protocol.d.ts.map +1 -1
  83. package/esm/src/chat/protocol.js +1 -0
  84. package/esm/src/chat/provider-errors.d.ts.map +1 -1
  85. package/esm/src/chat/provider-errors.js +0 -1
  86. package/esm/src/chat/stream-watchdog.d.ts +0 -1
  87. package/esm/src/chat/stream-watchdog.d.ts.map +1 -1
  88. package/esm/src/chat/stream-watchdog.js +0 -1
  89. package/esm/src/config/environment-config.d.ts +1 -0
  90. package/esm/src/config/environment-config.d.ts.map +1 -1
  91. package/esm/src/config/environment-config.js +4 -0
  92. package/esm/src/discovery/agent-scoped-capabilities.d.ts +54 -0
  93. package/esm/src/discovery/agent-scoped-capabilities.d.ts.map +1 -0
  94. package/esm/src/discovery/agent-scoped-capabilities.js +228 -0
  95. package/esm/src/discovery/discovery-engine.d.ts.map +1 -1
  96. package/esm/src/discovery/discovery-engine.js +19 -15
  97. package/esm/src/discovery/file-discovery.d.ts +10 -0
  98. package/esm/src/discovery/file-discovery.d.ts.map +1 -1
  99. package/esm/src/discovery/file-discovery.js +46 -0
  100. package/esm/src/discovery/handlers/runtime-agent-markdown-handler.d.ts +12 -0
  101. package/esm/src/discovery/handlers/runtime-agent-markdown-handler.d.ts.map +1 -1
  102. package/esm/src/discovery/handlers/runtime-agent-markdown-handler.js +99 -22
  103. package/esm/src/errors/error-registry/agent.d.ts +2 -0
  104. package/esm/src/errors/error-registry/agent.d.ts.map +1 -1
  105. package/esm/src/errors/error-registry/agent.js +8 -0
  106. package/esm/src/errors/error-registry.d.ts +1 -0
  107. package/esm/src/errors/error-registry.d.ts.map +1 -1
  108. package/esm/src/extensions/errors.d.ts +2 -0
  109. package/esm/src/extensions/errors.d.ts.map +1 -1
  110. package/esm/src/extensions/errors.js +8 -0
  111. package/esm/src/extensions/loader.d.ts +9 -6
  112. package/esm/src/extensions/loader.d.ts.map +1 -1
  113. package/esm/src/extensions/loader.js +39 -4
  114. package/esm/src/extensions/orchestrate.d.ts +3 -0
  115. package/esm/src/extensions/orchestrate.d.ts.map +1 -1
  116. package/esm/src/extensions/orchestrate.js +3 -1
  117. package/esm/src/integrations/_data.d.ts.map +1 -1
  118. package/esm/src/integrations/_data.js +31348 -7873
  119. package/esm/src/integrations/_tool_summaries.d.ts.map +1 -1
  120. package/esm/src/integrations/_tool_summaries.js +1737 -11
  121. package/esm/src/integrations/feature-flags.d.ts +1 -1
  122. package/esm/src/integrations/feature-flags.d.ts.map +1 -1
  123. package/esm/src/integrations/feature-flags.js +83 -0
  124. package/esm/src/integrations/schema.d.ts +129 -4
  125. package/esm/src/integrations/schema.d.ts.map +1 -1
  126. package/esm/src/integrations/schema.js +126 -1
  127. package/esm/src/internal-agents/run-stream.d.ts +4 -0
  128. package/esm/src/internal-agents/run-stream.d.ts.map +1 -1
  129. package/esm/src/internal-agents/run-stream.js +18 -5
  130. package/esm/src/mcp/server.d.ts.map +1 -1
  131. package/esm/src/mcp/server.js +5 -0
  132. package/esm/src/platform/adapters/base.d.ts +7 -0
  133. package/esm/src/platform/adapters/base.d.ts.map +1 -1
  134. package/esm/src/platform/adapters/runtime/deno/adapter.d.ts.map +1 -1
  135. package/esm/src/platform/adapters/runtime/deno/adapter.js +7 -2
  136. package/esm/src/registry/project-scoped-registry-manager.d.ts +7 -0
  137. package/esm/src/registry/project-scoped-registry-manager.d.ts.map +1 -1
  138. package/esm/src/registry/project-scoped-registry-manager.js +10 -0
  139. package/esm/src/registry/scoped-registry-facade.d.ts +2 -0
  140. package/esm/src/registry/scoped-registry-facade.d.ts.map +1 -1
  141. package/esm/src/registry/scoped-registry-facade.js +4 -0
  142. package/esm/src/rendering/layouts/utils/component-loader.d.ts +1 -1
  143. package/esm/src/rendering/layouts/utils/component-loader.d.ts.map +1 -1
  144. package/esm/src/rendering/layouts/utils/component-loader.js +82 -3
  145. package/esm/src/rendering/orchestrator/css-cache.d.ts +3 -0
  146. package/esm/src/rendering/orchestrator/css-cache.d.ts.map +1 -1
  147. package/esm/src/rendering/orchestrator/css-cache.js +16 -8
  148. package/esm/src/rendering/orchestrator/mdx.d.ts.map +1 -1
  149. package/esm/src/rendering/orchestrator/mdx.js +12 -1
  150. package/esm/src/server/bootstrap.d.ts.map +1 -1
  151. package/esm/src/server/bootstrap.js +3 -0
  152. package/esm/src/server/handlers/dev/dashboard/api.js +6 -3
  153. package/esm/src/server/handlers/request/agent-stream.handler.d.ts.map +1 -1
  154. package/esm/src/server/handlers/request/agent-stream.handler.js +10 -0
  155. package/esm/src/server/handlers/request/channel-invoke.handler.d.ts.map +1 -1
  156. package/esm/src/server/handlers/request/channel-invoke.handler.js +8 -0
  157. package/esm/src/server/handlers/request/runtime-shutdown-response.d.ts +13 -0
  158. package/esm/src/server/handlers/request/runtime-shutdown-response.d.ts.map +1 -0
  159. package/esm/src/server/handlers/request/runtime-shutdown-response.js +16 -0
  160. package/esm/src/server/production-server.d.ts.map +1 -1
  161. package/esm/src/server/production-server.js +7 -1
  162. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
  163. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +2 -2
  164. package/esm/src/server/shutdown-state.d.ts +16 -0
  165. package/esm/src/server/shutdown-state.d.ts.map +1 -0
  166. package/esm/src/server/shutdown-state.js +22 -0
  167. package/esm/src/skill/index.d.ts +1 -1
  168. package/esm/src/skill/index.d.ts.map +1 -1
  169. package/esm/src/skill/index.js +1 -1
  170. package/esm/src/skill/registry.d.ts +29 -3
  171. package/esm/src/skill/registry.d.ts.map +1 -1
  172. package/esm/src/skill/registry.js +57 -8
  173. package/esm/src/skill/tools.d.ts.map +1 -1
  174. package/esm/src/skill/tools.js +27 -25
  175. package/esm/src/skill/types.d.ts +8 -0
  176. package/esm/src/skill/types.d.ts.map +1 -1
  177. package/esm/src/tool/executor.d.ts +7 -1
  178. package/esm/src/tool/executor.d.ts.map +1 -1
  179. package/esm/src/tool/executor.js +12 -1
  180. package/esm/src/tool/index.d.ts +1 -1
  181. package/esm/src/tool/index.d.ts.map +1 -1
  182. package/esm/src/tool/index.js +1 -1
  183. package/esm/src/tool/registry.d.ts +1 -0
  184. package/esm/src/tool/registry.d.ts.map +1 -1
  185. package/esm/src/tool/registry.js +25 -0
  186. package/esm/src/tool/types.d.ts +9 -0
  187. package/esm/src/tool/types.d.ts.map +1 -1
  188. package/esm/src/transforms/import-rewriter/strategies/bare-strategy.js +1 -1
  189. package/esm/src/transforms/import-rewriter/strategies/url-strategy.d.ts +1 -1
  190. package/esm/src/transforms/import-rewriter/strategies/url-strategy.d.ts.map +1 -1
  191. package/esm/src/transforms/import-rewriter/strategies/url-strategy.js +1 -1
  192. package/esm/src/transforms/import-rewriter/url-builder.d.ts.map +1 -1
  193. package/esm/src/transforms/import-rewriter/url-builder.js +36 -2
  194. package/esm/src/utils/constants/cache.d.ts +8 -0
  195. package/esm/src/utils/constants/cache.d.ts.map +1 -1
  196. package/esm/src/utils/constants/cache.js +8 -0
  197. package/esm/src/utils/constants/index.d.ts +1 -1
  198. package/esm/src/utils/constants/index.d.ts.map +1 -1
  199. package/esm/src/utils/constants/index.js +1 -1
  200. package/esm/src/utils/index.d.ts +1 -1
  201. package/esm/src/utils/index.d.ts.map +1 -1
  202. package/esm/src/utils/index.js +1 -1
  203. package/esm/src/utils/lru-wrapper.d.ts +2 -0
  204. package/esm/src/utils/lru-wrapper.d.ts.map +1 -1
  205. package/esm/src/utils/lru-wrapper.js +1 -0
  206. package/esm/src/utils/version-constant.d.ts +1 -1
  207. package/esm/src/utils/version-constant.js +1 -1
  208. package/package.json +1 -45
  209. package/esm/src/chat/compat.d.ts +0 -782
  210. package/esm/src/chat/compat.d.ts.map +0 -1
  211. package/esm/src/chat/compat.js +0 -113
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Per-agent colocated capability registration.
3
+ *
4
+ * Directory-layout agents (`agents/{id}/`) may ship their own tools and
5
+ * skills:
6
+ * - Tools: `agents/{id}/tools/*.ts` → registered into the global tool
7
+ * registry under `{agentId}--{shortName}` with `ownerAgentId` metadata.
8
+ * - Skills: `agents/{id}/SKILL.md` (the agent's own skill, registered under
9
+ * the agent id) and `agents/{id}/skills/<sub>/SKILL.md` (registered under
10
+ * `{agentId}--{sub}`), both with `ownerAgentId` metadata.
11
+ *
12
+ * Discovery here is PURE REGISTRATION: no binding decisions. Visibility and
13
+ * selector resolution (`skills:` / `tools:`, `true` or lists, own short names
14
+ * first) happen at invocation time through the owner-aware resolvers, so flat
15
+ * and directory agents share identical binding semantics.
16
+ *
17
+ * The namespace separator is `--` (decided platform-wide): provider-safe and
18
+ * never confusable with `<provider>__<tool>` integration tool naming.
19
+ */
20
+ import { toolRegistry } from "../tool/index.js";
21
+ import { parseSkillFrontmatter, validateSkillMetadata } from "../skill/parser.js";
22
+ import { getSkill, registerSkill } from "../skill/registry.js";
23
+ import { SKILL_MD_FILENAME } from "../skill/types.js";
24
+ import { registerTool } from "../mcp/index.js";
25
+ import { ensureError } from "../errors/veryfront-error.js";
26
+ import { filenameToId } from "./discovery-utils.js";
27
+ import { discoveryFileExists, findTypeScriptFiles, listDiscoveryDirectoryEntries, readDiscoveryTextFile, } from "./file-discovery.js";
28
+ import { importModule } from "./transpiler.js";
29
+ const AGENT_TOOLS_SUBDIR = "tools";
30
+ const AGENT_SKILLS_SUBDIR = "skills";
31
+ /** Separator between the agent namespace and the capability short name. */
32
+ export const AGENT_CAPABILITY_NAMESPACE_SEPARATOR = "--";
33
+ /** Provider tool-call names allow only this charset, max 64 chars. */
34
+ const PROVIDER_TOOL_NAME_REGEX = /^[A-Za-z0-9_-]{1,64}$/;
35
+ /** Whether a namespaced tool name is valid for provider tool calls. */
36
+ export function isProviderSafeToolName(name) {
37
+ return PROVIDER_TOOL_NAME_REGEX.test(name);
38
+ }
39
+ const SAFE_PATH_SEGMENT_REGEX = /^[A-Za-z0-9._-]+$/;
40
+ /**
41
+ * Whether a directory/file entry name is a safe single path segment — used
42
+ * before joining it into a filesystem path. Rejects `.` and `..` (which match
43
+ * the permissive name regex) as defense-in-depth against path traversal.
44
+ */
45
+ export function isSafePathSegment(name) {
46
+ return name !== "." && name !== ".." && SAFE_PATH_SEGMENT_REGEX.test(name);
47
+ }
48
+ /** Sanitizes an agent id into a provider-safe namespace segment. */
49
+ export function sanitizeCapabilityNamespace(agentId) {
50
+ return agentId.replace(/[^A-Za-z0-9_-]/g, "_");
51
+ }
52
+ /** Namespaces a capability short name under its owning agent. */
53
+ export function namespaceAgentCapability(agentId, shortName) {
54
+ return `${sanitizeCapabilityNamespace(agentId)}${AGENT_CAPABILITY_NAMESPACE_SEPARATOR}${shortName}`;
55
+ }
56
+ function isTool(value) {
57
+ return value !== null && typeof value === "object" &&
58
+ typeof value.execute === "function";
59
+ }
60
+ function hasExplicitToolId(tool) {
61
+ const generated = tool.__veryfrontGeneratedId;
62
+ if (typeof tool.id !== "string" || tool.id.trim().length === 0) {
63
+ return false;
64
+ }
65
+ return generated === undefined || tool.id !== generated;
66
+ }
67
+ function toolShortName(tool, file) {
68
+ return hasExplicitToolId(tool) ? tool.id : filenameToId(file);
69
+ }
70
+ function collectModuleTools(module, file) {
71
+ const tools = new Map();
72
+ const record = module;
73
+ for (const value of Object.values(record ?? {})) {
74
+ if (isTool(value)) {
75
+ tools.set(toolShortName(value, file), value);
76
+ }
77
+ }
78
+ return tools;
79
+ }
80
+ function reportShadowedGlobalCapability(input) {
81
+ const global = input.kind === "tool"
82
+ ? toolRegistry.get(input.shortName)
83
+ : getSkill(input.shortName);
84
+ if (global && global.ownerAgentId === undefined) {
85
+ input.result?.errors.push({
86
+ file: input.file,
87
+ error: ensureError(`Colocated ${input.kind} "${input.shortName}" of agent "${input.agentId}" shadows the ` +
88
+ `global ${input.kind} id "${input.shortName}": the agent's selector resolves its own ` +
89
+ `${input.kind} first. Rename one to make the reference unambiguous.`),
90
+ });
91
+ }
92
+ }
93
+ /**
94
+ * Registers an agent's colocated `tools/*.ts` into the global tool registry
95
+ * under `{agentId}--{shortName}` with owner metadata. Returns registered ids.
96
+ */
97
+ export async function registerAgentColocatedTools(input) {
98
+ const toolsDir = `${input.rootPath}/${AGENT_TOOLS_SUBDIR}`;
99
+ if (!(await discoveryFileExists(toolsDir, input.context))) {
100
+ return [];
101
+ }
102
+ const files = (await findTypeScriptFiles(toolsDir, input.context)).sort((left, right) => left.localeCompare(right));
103
+ const registeredIds = [];
104
+ const seenThisPass = new Set();
105
+ for (const file of files) {
106
+ try {
107
+ const module = await importModule(file, input.context);
108
+ for (const [shortName, moduleTool] of collectModuleTools(module, file)) {
109
+ const namespaced = namespaceAgentCapability(input.agentId, shortName);
110
+ if (!isProviderSafeToolName(namespaced)) {
111
+ input.result?.errors.push({
112
+ file,
113
+ error: ensureError(`Colocated tool "${shortName}" for agent "${input.agentId}" produces an ` +
114
+ `invalid tool name "${namespaced}" (must match [A-Za-z0-9_-], max 64 chars).`),
115
+ });
116
+ continue;
117
+ }
118
+ // Two colocated tools resolving to the same short name within one
119
+ // discovery pass is a user error — report it instead of silently
120
+ // keeping the first (a later "unknown tool" with no breadcrumb).
121
+ // A pre-existing registry entry from a previous pass is a normal
122
+ // re-discovery refresh and is overwritten.
123
+ if (seenThisPass.has(namespaced)) {
124
+ input.result?.errors.push({
125
+ file,
126
+ error: ensureError(`Duplicate colocated tool "${shortName}" for agent "${input.agentId}": ` +
127
+ `another tools/ module already registered "${namespaced}"; keeping the first.`),
128
+ });
129
+ continue;
130
+ }
131
+ seenThisPass.add(namespaced);
132
+ reportShadowedGlobalCapability({
133
+ kind: "tool",
134
+ agentId: input.agentId,
135
+ shortName,
136
+ file,
137
+ result: input.result,
138
+ });
139
+ registerTool(namespaced, {
140
+ ...moduleTool,
141
+ id: namespaced,
142
+ ownerAgentId: input.agentId,
143
+ shortName,
144
+ });
145
+ registeredIds.push(namespaced);
146
+ }
147
+ }
148
+ catch (error) {
149
+ input.result?.errors.push({ file, error: ensureError(error) });
150
+ }
151
+ }
152
+ return registeredIds;
153
+ }
154
+ async function buildSkillFromDir(input) {
155
+ const skillMdPath = `${input.skillDir}/${SKILL_MD_FILENAME}`;
156
+ if (!(await discoveryFileExists(skillMdPath, input.context))) {
157
+ return null;
158
+ }
159
+ const content = await readDiscoveryTextFile(skillMdPath, input.context);
160
+ const parsed = await parseSkillFrontmatter(content);
161
+ const metadata = validateSkillMetadata(parsed.frontmatter, input.id);
162
+ return {
163
+ id: input.id,
164
+ metadata,
165
+ rootPath: input.skillDir.replace(/^file:\/\//, ""),
166
+ ownerAgentId: input.ownerAgentId,
167
+ shortName: input.shortName,
168
+ ...(input.context.fsAdapter ? { fsAdapter: input.context.fsAdapter } : {}),
169
+ };
170
+ }
171
+ /**
172
+ * Registers an agent's colocated skills into the skill registry with owner
173
+ * metadata. The agent's own `SKILL.md` registers under the agent id; nested
174
+ * `skills/<sub>/SKILL.md` skills register under `{agentId}--{sub}`. Returns
175
+ * registered ids.
176
+ */
177
+ export async function registerAgentColocatedSkills(input) {
178
+ const candidates = [];
179
+ if (await discoveryFileExists(`${input.rootPath}/${SKILL_MD_FILENAME}`, input.context)) {
180
+ candidates.push({ id: input.agentId, shortName: input.agentId, skillDir: input.rootPath });
181
+ }
182
+ const skillsDir = `${input.rootPath}/${AGENT_SKILLS_SUBDIR}`;
183
+ const entries = (await listDiscoveryDirectoryEntries(skillsDir, input.context)).sort((a, b) => a.name.localeCompare(b.name));
184
+ for (const entry of entries) {
185
+ if (!entry.isDirectory || !isSafePathSegment(entry.name)) {
186
+ continue;
187
+ }
188
+ candidates.push({
189
+ id: namespaceAgentCapability(input.agentId, entry.name),
190
+ shortName: entry.name,
191
+ skillDir: `${skillsDir}/${entry.name}`,
192
+ });
193
+ }
194
+ const registeredIds = [];
195
+ for (const candidate of candidates) {
196
+ try {
197
+ const skill = await buildSkillFromDir({
198
+ id: candidate.id,
199
+ skillDir: candidate.skillDir,
200
+ ownerAgentId: input.agentId,
201
+ shortName: candidate.shortName,
202
+ context: input.context,
203
+ });
204
+ if (!skill) {
205
+ continue;
206
+ }
207
+ if (candidate.shortName !== input.agentId) {
208
+ reportShadowedGlobalCapability({
209
+ kind: "skill",
210
+ agentId: input.agentId,
211
+ shortName: candidate.shortName,
212
+ file: `${candidate.skillDir}/${SKILL_MD_FILENAME}`,
213
+ result: input.result,
214
+ });
215
+ }
216
+ registerSkill(skill.id, skill);
217
+ input.result?.skills.set(skill.id, skill);
218
+ registeredIds.push(skill.id);
219
+ }
220
+ catch (error) {
221
+ input.result?.errors.push({
222
+ file: `${candidate.skillDir}/${SKILL_MD_FILENAME}`,
223
+ error: ensureError(error),
224
+ });
225
+ }
226
+ }
227
+ return registeredIds;
228
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"discovery-engine.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/discovery-engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEhB,MAAM,YAAY,CAAC;AAsIpB;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA2EnF"}
1
+ {"version":3,"file":"discovery-engine.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/discovery-engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEhB,MAAM,YAAY,CAAC;AAsIpB;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA+EnF"}
@@ -120,6 +120,25 @@ export async function discoverAll(config) {
120
120
  for (const dir of config.toolDirs ?? ["tools"]) {
121
121
  await discoverItems(`${baseDir}/${dir}`, result, context, toolHandler, config.verbose);
122
122
  }
123
+ // Clear stale skills before any skill registration so deleted/renamed
124
+ // skills are removed. Global skills are discovered BEFORE agents so that
125
+ // directory-agent colocated skills (registered during agent discovery)
126
+ // survive the clear and owned-short-name shadow diagnostics can see the
127
+ // global ids they shadow.
128
+ skillRegistry.clear();
129
+ // Discover skills (parallel path — markdown-based, not TypeScript import)
130
+ for (const dir of config.skillDirs ?? ["skills"]) {
131
+ const skillResult = await discoverSkills(join(baseDir, dir), context, config.verbose);
132
+ for (const [id, skill] of skillResult.skills) {
133
+ if (result.skills.has(id)) {
134
+ logger.warn(`Duplicate skill "${id}" across discovery roots; keeping first registration`);
135
+ continue;
136
+ }
137
+ registerSkill(id, skill);
138
+ result.skills.set(id, skill);
139
+ }
140
+ result.errors.push(...skillResult.errors.map((e) => ({ file: e.file, error: e.error })));
141
+ }
123
142
  // Discover agents
124
143
  for (const dir of config.agentDirs ?? ["agents"]) {
125
144
  await discoverItems(`${baseDir}/${dir}`, result, context, agentHandler, config.verbose);
@@ -141,20 +160,5 @@ export async function discoverAll(config) {
141
160
  for (const dir of config.taskDirs ?? ["tasks"]) {
142
161
  await discoverItems(`${baseDir}/${dir}`, result, context, taskHandler, config.verbose);
143
162
  }
144
- // Clear stale skills before rediscovery so deleted/renamed skills are removed.
145
- skillRegistry.clear();
146
- // Discover skills (parallel path — markdown-based, not TypeScript import)
147
- for (const dir of config.skillDirs ?? ["skills"]) {
148
- const skillResult = await discoverSkills(join(baseDir, dir), context, config.verbose);
149
- for (const [id, skill] of skillResult.skills) {
150
- if (result.skills.has(id)) {
151
- logger.warn(`Duplicate skill "${id}" across discovery roots; keeping first registration`);
152
- continue;
153
- }
154
- registerSkill(id, skill);
155
- result.skills.set(id, skill);
156
- }
157
- result.errors.push(...skillResult.errors.map((e) => ({ file: e.file, error: e.error })));
158
- }
159
163
  return result;
160
164
  }
@@ -13,4 +13,14 @@ export declare function findTypeScriptFiles(dir: string, context: FileDiscoveryC
13
13
  */
14
14
  export declare function findMarkdownFiles(dir: string, context: FileDiscoveryContext): Promise<string[]>;
15
15
  export declare function readDiscoveryTextFile(fileUrl: string, context: FileDiscoveryContext): Promise<string>;
16
+ /** A single top-level entry inside a discovery directory. */
17
+ export type DiscoveryDirectoryEntry = {
18
+ name: string;
19
+ isFile: boolean;
20
+ isDirectory: boolean;
21
+ };
22
+ /** Lists the immediate (non-recursive) entries of a discovery directory. */
23
+ export declare function listDiscoveryDirectoryEntries(dir: string, context: FileDiscoveryContext): Promise<DiscoveryDirectoryEntry[]>;
24
+ /** Returns true when a discovery file exists (fsAdapter-aware). */
25
+ export declare function discoveryFileExists(path: string, context: FileDiscoveryContext): Promise<boolean>;
16
26
  //# sourceMappingURL=file-discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-discovery.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/file-discovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsEvD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CASjB"}
1
+ {"version":3,"file":"file-discovery.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/file-discovery.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsEvD;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAEnB;AAED,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,6DAA6D;AAC7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,4EAA4E;AAC5E,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAkCpC;AAED,mEAAmE;AACnE,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,OAAO,CAAC,CAUlB"}
@@ -76,3 +76,49 @@ export async function readDiscoveryTextFile(fileUrl, context) {
76
76
  const { fs } = await getNodeDeps(context);
77
77
  return fs.readFileSync(path, "utf-8");
78
78
  }
79
+ /** Lists the immediate (non-recursive) entries of a discovery directory. */
80
+ export async function listDiscoveryDirectoryEntries(dir, context) {
81
+ const entries = [];
82
+ try {
83
+ if (context.fsAdapter) {
84
+ if (!(await context.fsAdapter.exists(dir)))
85
+ return entries;
86
+ for await (const entry of context.fsAdapter.readDir(dir)) {
87
+ entries.push({
88
+ name: entry.name,
89
+ isFile: entry.isFile,
90
+ isDirectory: entry.isDirectory,
91
+ });
92
+ }
93
+ return entries;
94
+ }
95
+ const { fs } = await getNodeDeps(context);
96
+ if (!fs.existsSync(dir))
97
+ return entries;
98
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
99
+ entries.push({
100
+ name: entry.name,
101
+ isFile: entry.isFile(),
102
+ isDirectory: entry.isDirectory(),
103
+ });
104
+ }
105
+ }
106
+ catch (_) {
107
+ /* expected: directory may not exist or be unreadable */
108
+ return entries;
109
+ }
110
+ return entries;
111
+ }
112
+ /** Returns true when a discovery file exists (fsAdapter-aware). */
113
+ export async function discoveryFileExists(path, context) {
114
+ try {
115
+ if (context.fsAdapter) {
116
+ return await context.fsAdapter.exists(path);
117
+ }
118
+ const { fs } = await getNodeDeps(context);
119
+ return fs.existsSync(path);
120
+ }
121
+ catch (_) {
122
+ return false;
123
+ }
124
+ }
@@ -1,3 +1,15 @@
1
1
  import type { DiscoveryResult, FileDiscoveryContext } from "../types.js";
2
+ /**
3
+ * Discovers markdown agents from a directory.
4
+ *
5
+ * Supports two layouts side by side:
6
+ * - Flat: `agents/{id}.md`
7
+ * - Directory: `agents/{id}/AGENT.md` (+ colocated `SKILL.md` / `skills/` /
8
+ * `tools/`, registered with owner metadata)
9
+ *
10
+ * Binding is NOT decided here: both layouts pass their parsed definition to
11
+ * the same adapter, and the owner-aware resolvers apply one rule for every
12
+ * agent kind at invocation time.
13
+ */
2
14
  export declare function discoverRuntimeAgentMarkdownDefinitions(dir: string, result: DiscoveryResult, context: FileDiscoveryContext): Promise<void>;
3
15
  //# sourceMappingURL=runtime-agent-markdown-handler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-agent-markdown-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/discovery/handlers/runtime-agent-markdown-handler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AA6CzE,wBAAsB,uCAAuC,CAC3D,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAqBf"}
1
+ {"version":3,"file":"runtime-agent-markdown-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/discovery/handlers/runtime-agent-markdown-handler.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAkKzE;;;;;;;;;;;GAWG;AACH,wBAAsB,uCAAuC,CAC3D,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -3,25 +3,82 @@ import { parseRuntimeAgentMarkdownDefinition, } from "../../agent/runtime/agent-
3
3
  import { agentRegistry, registerAgent } from "../../agent/composition/index.js";
4
4
  import { ensureError } from "../../errors/veryfront-error.js";
5
5
  import { trackAgentPath } from "../discovery-utils.js";
6
- import { findMarkdownFiles, readDiscoveryTextFile } from "../file-discovery.js";
6
+ import { discoveryFileExists, listDiscoveryDirectoryEntries, readDiscoveryTextFile, } from "../file-discovery.js";
7
+ import { isSafePathSegment, registerAgentColocatedSkills, registerAgentColocatedTools, sanitizeCapabilityNamespace, } from "../agent-scoped-capabilities.js";
7
8
  const MARKDOWN_AGENT_FILE_PATTERN = /^[A-Za-z0-9._-]+\.md$/;
8
- function getFileName(file) {
9
- return file.split("/").pop() ?? "";
10
- }
11
- function getMarkdownAgentCandidate(file) {
12
- const fileName = getFileName(file);
9
+ const DIRECTORY_AGENT_FILENAME = "AGENT.md";
10
+ const RESERVED_TOP_LEVEL_FILENAMES = new Set(["AGENT.md", "SKILL.md"]);
11
+ function getFlatAgentCandidate(dir, fileName) {
12
+ if (RESERVED_TOP_LEVEL_FILENAMES.has(fileName)) {
13
+ return null;
14
+ }
13
15
  if (!MARKDOWN_AGENT_FILE_PATTERN.test(fileName)) {
14
16
  return null;
15
17
  }
18
+ const id = fileName.slice(0, -".md".length);
19
+ // Reject `.`/`..` ids as defense-in-depth against path traversal.
20
+ if (!isSafePathSegment(id)) {
21
+ return null;
22
+ }
16
23
  return {
17
- id: fileName.slice(0, -".md".length),
18
- file,
24
+ id,
25
+ file: `${dir}/${fileName}`,
19
26
  };
20
27
  }
21
- function registerMarkdownAgent(definition, file, result) {
28
+ async function getDirectoryAgentCandidate(dir, entryName, context) {
29
+ // Reject `.`/`..` and other non-segment names before joining into a path.
30
+ if (!isSafePathSegment(entryName)) {
31
+ return null;
32
+ }
33
+ const rootPath = `${dir}/${entryName}`;
34
+ const agentFile = `${rootPath}/${DIRECTORY_AGENT_FILENAME}`;
35
+ if (!(await discoveryFileExists(agentFile, context))) {
36
+ return null;
37
+ }
38
+ return { id: entryName, file: agentFile, rootPath };
39
+ }
40
+ /**
41
+ * Registers a directory agent's colocated capabilities. This is PURE
42
+ * REGISTRATION — binding (`skills:` / `tools:` selectors) happens at
43
+ * invocation time via the owner-aware resolvers, identically for flat and
44
+ * directory agents.
45
+ *
46
+ * Two distinct agent ids can sanitize to the same provider-safe namespace
47
+ * (e.g. "a.b" and "a_b" -> "a_b"), which would collide owned capability ids;
48
+ * detected and reported instead of silently overwriting.
49
+ */
50
+ async function registerColocatedCapabilities(definition, rootPath, result, context, namespaceOwners) {
51
+ const namespace = sanitizeCapabilityNamespace(definition.id);
52
+ const existingOwner = namespaceOwners.get(namespace);
53
+ if (existingOwner !== undefined && existingOwner !== definition.id) {
54
+ result.errors.push({
55
+ file: rootPath,
56
+ error: ensureError(`Agent "${definition.id}" shares the sanitized capability namespace ` +
57
+ `"${namespace}" with agent "${existingOwner}". Rename one to avoid ` +
58
+ `colliding colocated tool/skill ids.`),
59
+ });
60
+ return;
61
+ }
62
+ namespaceOwners.set(namespace, definition.id);
63
+ // Skills and tools live in disjoint subtrees; register them concurrently.
64
+ await Promise.all([
65
+ registerAgentColocatedSkills({ agentId: definition.id, rootPath, context, result }),
66
+ registerAgentColocatedTools({ agentId: definition.id, rootPath, context, result }),
67
+ ]);
68
+ }
69
+ async function registerMarkdownAgent(definition, file, rootPath, result, context, namespaceOwners) {
22
70
  if (result.agents.has(definition.id)) {
71
+ result.errors.push({
72
+ file,
73
+ error: ensureError(`Duplicate agent id "${definition.id}". An agent with this id was already ` +
74
+ `discovered (e.g. both a flat "${definition.id}.md" and a "${definition.id}/" ` +
75
+ `directory exist); keeping the first.`),
76
+ });
23
77
  return;
24
78
  }
79
+ if (rootPath) {
80
+ await registerColocatedCapabilities(definition, rootPath, result, context, namespaceOwners);
81
+ }
25
82
  const runtimeAgent = createRuntimeAgentFromMarkdownDefinition(definition);
26
83
  if (runtimeAgent.id !== definition.id) {
27
84
  agentRegistry.delete(runtimeAgent.id);
@@ -30,22 +87,42 @@ function registerMarkdownAgent(definition, file, result) {
30
87
  trackAgentPath(definition.id, file);
31
88
  result.agents.set(definition.id, runtimeAgent);
32
89
  }
90
+ async function discoverMarkdownAgentCandidate(candidate, result, context, namespaceOwners) {
91
+ try {
92
+ const definition = parseRuntimeAgentMarkdownDefinition({
93
+ id: candidate.id,
94
+ content: await readDiscoveryTextFile(candidate.file, context),
95
+ });
96
+ await registerMarkdownAgent(definition, candidate.file, candidate.rootPath, result, context, namespaceOwners);
97
+ }
98
+ catch (error) {
99
+ result.errors.push({ file: candidate.file, error: ensureError(error) });
100
+ }
101
+ }
102
+ /**
103
+ * Discovers markdown agents from a directory.
104
+ *
105
+ * Supports two layouts side by side:
106
+ * - Flat: `agents/{id}.md`
107
+ * - Directory: `agents/{id}/AGENT.md` (+ colocated `SKILL.md` / `skills/` /
108
+ * `tools/`, registered with owner metadata)
109
+ *
110
+ * Binding is NOT decided here: both layouts pass their parsed definition to
111
+ * the same adapter, and the owner-aware resolvers apply one rule for every
112
+ * agent kind at invocation time.
113
+ */
33
114
  export async function discoverRuntimeAgentMarkdownDefinitions(dir, result, context) {
34
- const files = (await findMarkdownFiles(dir, context)).sort((left, right) => left.localeCompare(right));
35
- for (const file of files) {
36
- const candidate = getMarkdownAgentCandidate(file);
115
+ const entries = (await listDiscoveryDirectoryEntries(dir, context)).sort((left, right) => left.name.localeCompare(right.name));
116
+ const namespaceOwners = new Map();
117
+ for (const entry of entries) {
118
+ const candidate = entry.isDirectory
119
+ ? await getDirectoryAgentCandidate(dir, entry.name, context)
120
+ : entry.isFile
121
+ ? getFlatAgentCandidate(dir, entry.name)
122
+ : null;
37
123
  if (!candidate) {
38
124
  continue;
39
125
  }
40
- try {
41
- const definition = parseRuntimeAgentMarkdownDefinition({
42
- id: candidate.id,
43
- content: await readDiscoveryTextFile(candidate.file, context),
44
- });
45
- registerMarkdownAgent(definition, candidate.file, result);
46
- }
47
- catch (error) {
48
- result.errors.push({ file: candidate.file, error: ensureError(error) });
49
- }
126
+ await discoverMarkdownAgentCandidate(candidate, result, context, namespaceOwners);
50
127
  }
51
128
  }
@@ -4,6 +4,7 @@ export declare const AGENT_TIMEOUT: import("../types.js").RegisteredError;
4
4
  export declare const AGENT_INTENT_ERROR: import("../types.js").RegisteredError;
5
5
  export declare const ORCHESTRATION_ERROR: import("../types.js").RegisteredError;
6
6
  export declare const COST_LIMIT_EXCEEDED: import("../types.js").RegisteredError;
7
+ export declare const TOOL_ID_CONFLICT: import("../types.js").RegisteredError;
7
8
  /** Registry fragment for AGENT errors (slug → definition). */
8
9
  export declare const AGENT_REGISTRY: {
9
10
  readonly "agent-error": import("../types.js").RegisteredError;
@@ -12,5 +13,6 @@ export declare const AGENT_REGISTRY: {
12
13
  readonly "agent-intent-error": import("../types.js").RegisteredError;
13
14
  readonly "orchestration-error": import("../types.js").RegisteredError;
14
15
  readonly "cost-limit-exceeded": import("../types.js").RegisteredError;
16
+ readonly "tool-id-conflict": import("../types.js").RegisteredError;
15
17
  };
16
18
  //# sourceMappingURL=agent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../../src/src/errors/error-registry/agent.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,uCAMtB,CAAC;AAEH,eAAO,MAAM,eAAe,uCAM1B,CAAC;AAEH,eAAO,MAAM,aAAa,uCAMxB,CAAC;AAEH,eAAO,MAAM,kBAAkB,uCAM7B,CAAC;AAEH,eAAO,MAAM,mBAAmB,uCAM9B,CAAC;AAEH,eAAO,MAAM,mBAAmB,uCAM9B,CAAC;AAEH,8DAA8D;AAC9D,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../../src/src/errors/error-registry/agent.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,uCAMtB,CAAC;AAEH,eAAO,MAAM,eAAe,uCAM1B,CAAC;AAEH,eAAO,MAAM,aAAa,uCAMxB,CAAC;AAEH,eAAO,MAAM,kBAAkB,uCAM7B,CAAC;AAEH,eAAO,MAAM,mBAAmB,uCAM9B,CAAC;AAEH,eAAO,MAAM,mBAAmB,uCAM9B,CAAC;AAEH,eAAO,MAAM,gBAAgB,uCAM3B,CAAC;AAEH,8DAA8D;AAC9D,eAAO,MAAM,cAAc;;;;;;;;CAQjB,CAAC"}
@@ -41,6 +41,13 @@ export const COST_LIMIT_EXCEEDED = defineError({
41
41
  title: "Cost limit exceeded",
42
42
  suggestion: "Wait for the budget period to reset or increase the limit",
43
43
  });
44
+ export const TOOL_ID_CONFLICT = defineError({
45
+ slug: "tool-id-conflict",
46
+ category: "AGENT",
47
+ status: 409,
48
+ title: "Tool ID conflict",
49
+ suggestion: "Use a unique tool ID or rename one of the conflicting tools",
50
+ });
44
51
  /** Registry fragment for AGENT errors (slug → definition). */
45
52
  export const AGENT_REGISTRY = {
46
53
  "agent-error": AGENT_ERROR,
@@ -49,4 +56,5 @@ export const AGENT_REGISTRY = {
49
56
  "agent-intent-error": AGENT_INTENT_ERROR,
50
57
  "orchestration-error": ORCHESTRATION_ERROR,
51
58
  "cost-limit-exceeded": COST_LIMIT_EXCEEDED,
59
+ "tool-id-conflict": TOOL_ID_CONFLICT,
52
60
  };
@@ -31,6 +31,7 @@ export declare const ERROR_REGISTRY: {
31
31
  readonly "agent-intent-error": import("./types.js").RegisteredError;
32
32
  readonly "orchestration-error": import("./types.js").RegisteredError;
33
33
  readonly "cost-limit-exceeded": import("./types.js").RegisteredError;
34
+ readonly "tool-id-conflict": import("./types.js").RegisteredError;
34
35
  readonly "deployment-error": import("./types.js").RegisteredError;
35
36
  readonly "platform-error": import("./types.js").RegisteredError;
36
37
  readonly "env-var-missing": import("./types.js").RegisteredError;
@@ -1 +1 @@
1
- {"version":3,"file":"error-registry.d.ts","sourceRoot":"","sources":["../../../src/src/errors/error-registry.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAgBhD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYjB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,cAAc,CAAC;AAEpD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,wCAE7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,0CAE1D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,EAAE,CAEzC"}
1
+ {"version":3,"file":"error-registry.d.ts","sourceRoot":"","sources":["../../../src/src/errors/error-registry.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAgBhD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAE5C;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYjB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,cAAc,CAAC;AAEpD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,wCAE7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,0CAE1D;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,SAAS,EAAE,CAEzC"}
@@ -11,4 +11,6 @@ export declare const EXTENSION_VALIDATION_ERROR: import("../errors/types.js").Re
11
11
  export declare const CIRCULAR_DEPENDENCY_ERROR: import("../errors/types.js").RegisteredError;
12
12
  /** Shared extension conflict error value. */
13
13
  export declare const EXTENSION_CONFLICT_ERROR: import("../errors/types.js").RegisteredError;
14
+ /** Shared extension setup timeout error value. */
15
+ export declare const EXTENSION_SETUP_TIMEOUT_ERROR: import("../errors/types.js").RegisteredError;
14
16
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,8CAMlC,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,0BAA0B,8CAMrC,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,yBAAyB,8CAMpC,CAAC;AAEH,6CAA6C;AAC7C,eAAO,MAAM,wBAAwB,8CAMnC,CAAC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,8CAMlC,CAAC;AAEH,+CAA+C;AAC/C,eAAO,MAAM,0BAA0B,8CAMrC,CAAC;AAEH,8CAA8C;AAC9C,eAAO,MAAM,yBAAyB,8CAMpC,CAAC;AAEH,6CAA6C;AAC7C,eAAO,MAAM,wBAAwB,8CAMnC,CAAC;AAEH,kDAAkD;AAClD,eAAO,MAAM,6BAA6B,8CAOxC,CAAC"}
@@ -36,3 +36,11 @@ export const EXTENSION_CONFLICT_ERROR = defineError({
36
36
  title: "Conflicting extensions detected",
37
37
  suggestion: "Remove or disable one of the conflicting extensions in your configuration",
38
38
  });
39
+ /** Shared extension setup timeout error value. */
40
+ export const EXTENSION_SETUP_TIMEOUT_ERROR = defineError({
41
+ slug: "extension-setup-timeout",
42
+ category: "RUNTIME",
43
+ status: 500,
44
+ title: "Extension setup timed out",
45
+ suggestion: "Check the extension's setup() for blocking operations, or increase VF_EXTENSION_SETUP_TIMEOUT_MS",
46
+ });
@@ -1,9 +1,12 @@
1
- /**
2
- * Extension loader — topological sort, lifecycle management, preset flattening.
3
- *
4
- * @module extensions/loader
5
- */
6
1
  import type { ExtensionLogger, ResolvedExtension } from "./types.js";
2
+ /** Options for {@link ExtensionLoader.setupAll}. */
3
+ export interface SetupAllOptions {
4
+ /**
5
+ * Per-extension setup() timeout in milliseconds.
6
+ * Defaults to 30 000 ms. Pass `0` to disable.
7
+ */
8
+ setupTimeoutMs?: number;
9
+ }
7
10
  /** Implement extension loader. */
8
11
  export declare class ExtensionLoader {
9
12
  private logger;
@@ -32,7 +35,7 @@ export declare class ExtensionLoader {
32
35
  * Run the full setup lifecycle for all extensions.
33
36
  * If called while extensions are already loaded, tears them down first.
34
37
  */
35
- setupAll(extensions: ResolvedExtension[], projectConfig: Record<string, unknown>): Promise<void>;
38
+ setupAll(extensions: ResolvedExtension[], projectConfig: Record<string, unknown>, options?: SetupAllOptions): Promise<void>;
36
39
  /**
37
40
  * Teardown all loaded extensions in reverse order.
38
41
  */
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/loader.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,OAAO,KAAK,EAA+B,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAElG,kCAAkC;AAClC,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,MAAM,CAA+B;IAE7C;;;;OAIG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;gBAI5C,MAAM,EAAE,eAAe;IAInC;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;IAIpE,OAAO,CAAC,mBAAmB;IA8B3B;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;IAyErE;;;OAGG;IACG,QAAQ,CACZ,UAAU,EAAE,iBAAiB,EAAE,EAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,OAAO,CAAC,IAAI,CAAC;IAuFhB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBnC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/src/extensions/loader.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAA+B,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAKlG,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,kCAAkC;AAClC,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,MAAM,CAA+B;IAE7C;;;;OAIG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;gBAI5C,MAAM,EAAE,eAAe;IAInC;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;IAIpE,OAAO,CAAC,mBAAmB;IA8B3B;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,iBAAiB,EAAE;IAyErE;;;OAGG;IACG,QAAQ,CACZ,UAAU,EAAE,iBAAiB,EAAE,EAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,IAAI,CAAC;IAuHhB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAmBnC"}