@enactprotocol/shared 1.2.13 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/README.md +44 -0
  2. package/dist/config.d.ts +164 -0
  3. package/dist/config.d.ts.map +1 -0
  4. package/dist/config.js +386 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/constants.d.ts +15 -5
  7. package/dist/constants.d.ts.map +1 -0
  8. package/dist/constants.js +24 -8
  9. package/dist/constants.js.map +1 -0
  10. package/dist/execution/command.d.ts +102 -0
  11. package/dist/execution/command.d.ts.map +1 -0
  12. package/dist/execution/command.js +262 -0
  13. package/dist/execution/command.js.map +1 -0
  14. package/dist/execution/index.d.ts +12 -0
  15. package/dist/execution/index.d.ts.map +1 -0
  16. package/dist/execution/index.js +17 -0
  17. package/dist/execution/index.js.map +1 -0
  18. package/dist/execution/runtime.d.ts +82 -0
  19. package/dist/execution/runtime.d.ts.map +1 -0
  20. package/dist/execution/runtime.js +273 -0
  21. package/dist/execution/runtime.js.map +1 -0
  22. package/dist/execution/types.d.ts +306 -0
  23. package/dist/execution/types.d.ts.map +1 -0
  24. package/dist/execution/types.js +14 -0
  25. package/dist/execution/types.js.map +1 -0
  26. package/dist/execution/validation.d.ts +43 -0
  27. package/dist/execution/validation.d.ts.map +1 -0
  28. package/dist/execution/validation.js +430 -0
  29. package/dist/execution/validation.js.map +1 -0
  30. package/dist/index.d.ts +21 -21
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +49 -25
  33. package/dist/index.js.map +1 -0
  34. package/dist/manifest/index.d.ts +7 -0
  35. package/dist/manifest/index.d.ts.map +1 -0
  36. package/dist/manifest/index.js +10 -0
  37. package/dist/manifest/index.js.map +1 -0
  38. package/dist/manifest/loader.d.ts +76 -0
  39. package/dist/manifest/loader.d.ts.map +1 -0
  40. package/dist/manifest/loader.js +146 -0
  41. package/dist/manifest/loader.js.map +1 -0
  42. package/dist/manifest/parser.d.ts +64 -0
  43. package/dist/manifest/parser.d.ts.map +1 -0
  44. package/dist/manifest/parser.js +135 -0
  45. package/dist/manifest/parser.js.map +1 -0
  46. package/dist/manifest/validator.d.ts +95 -0
  47. package/dist/manifest/validator.d.ts.map +1 -0
  48. package/dist/manifest/validator.js +258 -0
  49. package/dist/manifest/validator.js.map +1 -0
  50. package/dist/paths.d.ts +57 -0
  51. package/dist/paths.d.ts.map +1 -0
  52. package/dist/paths.js +93 -0
  53. package/dist/paths.js.map +1 -0
  54. package/dist/registry.d.ts +73 -0
  55. package/dist/registry.d.ts.map +1 -0
  56. package/dist/registry.js +147 -0
  57. package/dist/registry.js.map +1 -0
  58. package/dist/resolver.d.ts +89 -0
  59. package/dist/resolver.d.ts.map +1 -0
  60. package/dist/resolver.js +282 -0
  61. package/dist/resolver.js.map +1 -0
  62. package/dist/types/index.d.ts +6 -0
  63. package/dist/types/index.d.ts.map +1 -0
  64. package/dist/types/index.js +5 -0
  65. package/dist/types/index.js.map +1 -0
  66. package/dist/types/manifest.d.ts +201 -0
  67. package/dist/types/manifest.d.ts.map +1 -0
  68. package/dist/types/manifest.js +13 -0
  69. package/dist/types/manifest.js.map +1 -0
  70. package/dist/types.d.ts +5 -132
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +5 -3
  73. package/dist/types.js.map +1 -0
  74. package/dist/utils/fs.d.ts +105 -0
  75. package/dist/utils/fs.d.ts.map +1 -0
  76. package/dist/utils/fs.js +233 -0
  77. package/dist/utils/fs.js.map +1 -0
  78. package/dist/utils/logger.d.ts +102 -25
  79. package/dist/utils/logger.d.ts.map +1 -0
  80. package/dist/utils/logger.js +214 -57
  81. package/dist/utils/logger.js.map +1 -0
  82. package/dist/utils/version.d.ts +60 -2
  83. package/dist/utils/version.d.ts.map +1 -0
  84. package/dist/utils/version.js +255 -31
  85. package/dist/utils/version.js.map +1 -0
  86. package/package.json +16 -58
  87. package/src/config.ts +510 -0
  88. package/src/constants.ts +36 -0
  89. package/src/execution/command.ts +314 -0
  90. package/src/execution/index.ts +73 -0
  91. package/src/execution/runtime.ts +308 -0
  92. package/src/execution/types.ts +379 -0
  93. package/src/execution/validation.ts +508 -0
  94. package/src/index.ts +238 -30
  95. package/src/manifest/index.ts +36 -0
  96. package/src/manifest/loader.ts +187 -0
  97. package/src/manifest/parser.ts +173 -0
  98. package/src/manifest/validator.ts +309 -0
  99. package/src/paths.ts +108 -0
  100. package/src/registry.ts +219 -0
  101. package/src/resolver.ts +345 -0
  102. package/src/types/index.ts +30 -0
  103. package/src/types/manifest.ts +255 -0
  104. package/src/types.ts +5 -188
  105. package/src/utils/fs.ts +281 -0
  106. package/src/utils/logger.ts +270 -59
  107. package/src/utils/version.ts +304 -36
  108. package/tests/config.test.ts +515 -0
  109. package/tests/execution/command.test.ts +317 -0
  110. package/tests/execution/validation.test.ts +384 -0
  111. package/tests/fixtures/invalid-tool.yaml +4 -0
  112. package/tests/fixtures/valid-tool.md +62 -0
  113. package/tests/fixtures/valid-tool.yaml +40 -0
  114. package/tests/index.test.ts +8 -0
  115. package/tests/manifest/loader.test.ts +291 -0
  116. package/tests/manifest/parser.test.ts +345 -0
  117. package/tests/manifest/validator.test.ts +394 -0
  118. package/tests/manifest-types.test.ts +358 -0
  119. package/tests/paths.test.ts +153 -0
  120. package/tests/registry.test.ts +231 -0
  121. package/tests/resolver.test.ts +272 -0
  122. package/tests/utils/fs.test.ts +388 -0
  123. package/tests/utils/logger.test.ts +480 -0
  124. package/tests/utils/version.test.ts +390 -0
  125. package/tsconfig.json +12 -0
  126. package/dist/LocalToolResolver.d.ts +0 -84
  127. package/dist/LocalToolResolver.js +0 -353
  128. package/dist/api/enact-api.d.ts +0 -130
  129. package/dist/api/enact-api.js +0 -428
  130. package/dist/api/index.d.ts +0 -2
  131. package/dist/api/index.js +0 -2
  132. package/dist/api/types.d.ts +0 -103
  133. package/dist/api/types.js +0 -1
  134. package/dist/core/DaggerExecutionProvider.d.ts +0 -169
  135. package/dist/core/DaggerExecutionProvider.js +0 -1029
  136. package/dist/core/DirectExecutionProvider.d.ts +0 -23
  137. package/dist/core/DirectExecutionProvider.js +0 -406
  138. package/dist/core/EnactCore.d.ts +0 -162
  139. package/dist/core/EnactCore.js +0 -597
  140. package/dist/core/NativeExecutionProvider.d.ts +0 -9
  141. package/dist/core/NativeExecutionProvider.js +0 -16
  142. package/dist/core/index.d.ts +0 -3
  143. package/dist/core/index.js +0 -3
  144. package/dist/exec/index.d.ts +0 -3
  145. package/dist/exec/index.js +0 -3
  146. package/dist/exec/logger.d.ts +0 -11
  147. package/dist/exec/logger.js +0 -57
  148. package/dist/exec/validate.d.ts +0 -5
  149. package/dist/exec/validate.js +0 -167
  150. package/dist/lib/enact-direct.d.ts +0 -150
  151. package/dist/lib/enact-direct.js +0 -159
  152. package/dist/lib/index.d.ts +0 -1
  153. package/dist/lib/index.js +0 -1
  154. package/dist/security/index.d.ts +0 -3
  155. package/dist/security/index.js +0 -3
  156. package/dist/security/security.d.ts +0 -23
  157. package/dist/security/security.js +0 -137
  158. package/dist/security/sign.d.ts +0 -103
  159. package/dist/security/sign.js +0 -666
  160. package/dist/security/verification-enforcer.d.ts +0 -53
  161. package/dist/security/verification-enforcer.js +0 -204
  162. package/dist/services/McpCoreService.d.ts +0 -98
  163. package/dist/services/McpCoreService.js +0 -124
  164. package/dist/services/index.d.ts +0 -1
  165. package/dist/services/index.js +0 -1
  166. package/dist/utils/config.d.ts +0 -111
  167. package/dist/utils/config.js +0 -342
  168. package/dist/utils/env-loader.d.ts +0 -54
  169. package/dist/utils/env-loader.js +0 -270
  170. package/dist/utils/help.d.ts +0 -36
  171. package/dist/utils/help.js +0 -248
  172. package/dist/utils/index.d.ts +0 -7
  173. package/dist/utils/index.js +0 -7
  174. package/dist/utils/silent-monitor.d.ts +0 -67
  175. package/dist/utils/silent-monitor.js +0 -242
  176. package/dist/utils/timeout.d.ts +0 -5
  177. package/dist/utils/timeout.js +0 -23
  178. package/dist/web/env-manager-server.d.ts +0 -29
  179. package/dist/web/env-manager-server.js +0 -367
  180. package/dist/web/index.d.ts +0 -1
  181. package/dist/web/index.js +0 -1
  182. package/src/LocalToolResolver.ts +0 -424
  183. package/src/api/enact-api.ts +0 -604
  184. package/src/api/index.ts +0 -2
  185. package/src/api/types.ts +0 -114
  186. package/src/core/DaggerExecutionProvider.ts +0 -1357
  187. package/src/core/DirectExecutionProvider.ts +0 -484
  188. package/src/core/EnactCore.ts +0 -847
  189. package/src/core/index.ts +0 -3
  190. package/src/exec/index.ts +0 -3
  191. package/src/exec/logger.ts +0 -63
  192. package/src/exec/validate.ts +0 -238
  193. package/src/lib/enact-direct.ts +0 -254
  194. package/src/lib/index.ts +0 -1
  195. package/src/services/McpCoreService.ts +0 -201
  196. package/src/services/index.ts +0 -1
  197. package/src/utils/config.ts +0 -438
  198. package/src/utils/env-loader.ts +0 -370
  199. package/src/utils/help.ts +0 -257
  200. package/src/utils/index.ts +0 -7
  201. package/src/utils/silent-monitor.ts +0 -328
  202. package/src/utils/timeout.ts +0 -26
  203. package/src/web/env-manager-server.ts +0 -465
  204. package/src/web/index.ts +0 -1
  205. package/src/web/static/app.js +0 -663
  206. package/src/web/static/index.html +0 -117
  207. package/src/web/static/style.css +0 -291
@@ -0,0 +1,345 @@
1
+ /**
2
+ * Tool resolver - finds and loads tools from various locations
3
+ *
4
+ * Resolution order:
5
+ * 1. Direct file path (if provided path exists)
6
+ * 2. Project tools (.enact/tools/{name}/)
7
+ * 3. Global tools (via ~/.enact/tools.json → cache)
8
+ * 4. Cache (~/.enact/cache/{name}/{version}/)
9
+ */
10
+
11
+ import { existsSync, readdirSync } from "node:fs";
12
+ import { dirname, isAbsolute, join, resolve } from "node:path";
13
+ import { findManifestFile, loadManifest } from "./manifest/loader";
14
+ import { getCacheDir, getProjectEnactDir } from "./paths";
15
+ import { getInstalledVersion, getToolCachePath } from "./registry";
16
+ import type { ToolLocation, ToolResolution } from "./types/manifest";
17
+
18
+ /**
19
+ * Error thrown when tool resolution fails
20
+ */
21
+ export class ToolResolveError extends Error {
22
+ constructor(
23
+ message: string,
24
+ public readonly toolPath: string,
25
+ public readonly searchedLocations?: string[]
26
+ ) {
27
+ super(message);
28
+ this.name = "ToolResolveError";
29
+ }
30
+ }
31
+
32
+ /**
33
+ * Options for tool resolution
34
+ */
35
+ export interface ResolveOptions {
36
+ /** Starting directory for project search (defaults to cwd) */
37
+ startDir?: string;
38
+ /** Specific version to look for in cache */
39
+ version?: string;
40
+ /** Skip project-level tools */
41
+ skipProject?: boolean;
42
+ /** Skip user-level tools */
43
+ skipUser?: boolean;
44
+ /** Skip cached tools */
45
+ skipCache?: boolean;
46
+ }
47
+
48
+ /**
49
+ * Convert tool name to directory path
50
+ * e.g., "acme/utils/greeter" -> "acme/utils/greeter"
51
+ */
52
+ export function toolNameToPath(name: string): string {
53
+ // Tool names are already path-like, just normalize
54
+ return name.replace(/\\/g, "/");
55
+ }
56
+
57
+ /**
58
+ * Normalize a tool name (lowercase, forward slashes)
59
+ */
60
+ export function normalizeToolName(name: string): string {
61
+ return name.toLowerCase().replace(/\\/g, "/").trim();
62
+ }
63
+
64
+ /**
65
+ * Get the tool path within a tools directory
66
+ */
67
+ export function getToolPath(toolsDir: string, toolName: string): string {
68
+ return join(toolsDir, toolNameToPath(toolName));
69
+ }
70
+
71
+ /**
72
+ * Try to load a tool from a specific directory
73
+ *
74
+ * @param dir - Directory to check
75
+ * @param location - The location type for metadata
76
+ * @returns ToolResolution or null if not found/invalid
77
+ */
78
+ function tryLoadFromDir(dir: string, location: ToolLocation): ToolResolution | null {
79
+ if (!existsSync(dir)) {
80
+ return null;
81
+ }
82
+
83
+ const manifestPath = findManifestFile(dir);
84
+ if (!manifestPath) {
85
+ return null;
86
+ }
87
+
88
+ try {
89
+ const loaded = loadManifest(manifestPath);
90
+ return {
91
+ manifest: loaded.manifest,
92
+ sourceDir: dir,
93
+ location,
94
+ manifestPath,
95
+ version: loaded.manifest.version,
96
+ };
97
+ } catch {
98
+ // Invalid manifest, skip
99
+ return null;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Resolve a tool from a file path
105
+ *
106
+ * @param filePath - Path to manifest file or directory containing manifest
107
+ * @returns ToolResolution
108
+ * @throws ToolResolveError if not found
109
+ */
110
+ export function resolveToolFromPath(filePath: string): ToolResolution {
111
+ const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);
112
+
113
+ // Check if it's a manifest file directly
114
+ if (
115
+ absolutePath.endsWith(".yaml") ||
116
+ absolutePath.endsWith(".yml") ||
117
+ absolutePath.endsWith(".md")
118
+ ) {
119
+ if (!existsSync(absolutePath)) {
120
+ throw new ToolResolveError(`Manifest file not found: ${absolutePath}`, filePath);
121
+ }
122
+
123
+ const loaded = loadManifest(absolutePath);
124
+ return {
125
+ manifest: loaded.manifest,
126
+ sourceDir: dirname(absolutePath),
127
+ location: "file",
128
+ manifestPath: absolutePath,
129
+ version: loaded.manifest.version,
130
+ };
131
+ }
132
+
133
+ // Treat as directory
134
+ const result = tryLoadFromDir(absolutePath, "file");
135
+ if (result) {
136
+ return result;
137
+ }
138
+
139
+ throw new ToolResolveError(`No manifest found at: ${absolutePath}`, filePath);
140
+ }
141
+
142
+ /**
143
+ * Resolve a tool by name, searching through standard locations
144
+ *
145
+ * @param toolName - Tool name (e.g., "acme/utils/greeter")
146
+ * @param options - Resolution options
147
+ * @returns ToolResolution
148
+ * @throws ToolResolveError if not found
149
+ */
150
+ export function resolveTool(toolName: string, options: ResolveOptions = {}): ToolResolution {
151
+ const normalizedName = normalizeToolName(toolName);
152
+ const searchedLocations: string[] = [];
153
+
154
+ // 1. Try project tools (.enact/tools/{name}/)
155
+ if (!options.skipProject) {
156
+ const projectDir = getProjectEnactDir(options.startDir);
157
+ if (projectDir) {
158
+ const projectToolsDir = join(projectDir, "tools");
159
+ const toolDir = getToolPath(projectToolsDir, normalizedName);
160
+ searchedLocations.push(toolDir);
161
+
162
+ const result = tryLoadFromDir(toolDir, "project");
163
+ if (result) {
164
+ return result;
165
+ }
166
+ }
167
+ }
168
+
169
+ // 2. Try global tools (via ~/.enact/tools.json → cache)
170
+ if (!options.skipUser) {
171
+ const globalVersion = getInstalledVersion(normalizedName, "global");
172
+ if (globalVersion) {
173
+ const cachePath = getToolCachePath(normalizedName, globalVersion);
174
+ searchedLocations.push(cachePath);
175
+
176
+ const result = tryLoadFromDir(cachePath, "user");
177
+ if (result) {
178
+ return result;
179
+ }
180
+ }
181
+ }
182
+
183
+ // 3. Try cache (with optional version)
184
+ if (!options.skipCache) {
185
+ const cacheDir = getCacheDir();
186
+ const toolCacheBase = getToolPath(cacheDir, normalizedName);
187
+
188
+ if (options.version) {
189
+ // Look for specific version
190
+ const versionDir = join(toolCacheBase, `v${options.version.replace(/^v/, "")}`);
191
+ searchedLocations.push(versionDir);
192
+
193
+ const result = tryLoadFromDir(versionDir, "cache");
194
+ if (result) {
195
+ return result;
196
+ }
197
+ } else {
198
+ // Look for latest cached version
199
+ if (existsSync(toolCacheBase)) {
200
+ const latestVersion = findLatestCachedVersion(toolCacheBase);
201
+ if (latestVersion) {
202
+ const versionDir = join(toolCacheBase, latestVersion);
203
+ searchedLocations.push(versionDir);
204
+
205
+ const result = tryLoadFromDir(versionDir, "cache");
206
+ if (result) {
207
+ return result;
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ throw new ToolResolveError(
215
+ `Tool not found: ${toolName}. Searched locations:\n${searchedLocations.map((l) => ` - ${l}`).join("\n")}`,
216
+ toolName,
217
+ searchedLocations
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Find the latest cached version directory
223
+ */
224
+ function findLatestCachedVersion(toolCacheBase: string): string | null {
225
+ try {
226
+ const entries = readdirSync(toolCacheBase, { withFileTypes: true });
227
+ const versions = entries
228
+ .filter((e) => e.isDirectory() && e.name.startsWith("v"))
229
+ .map((e) => e.name)
230
+ .sort((a, b) => {
231
+ // Sort by semver (v1.0.0 format)
232
+ const aVer = a.slice(1).split(".").map(Number);
233
+ const bVer = b.slice(1).split(".").map(Number);
234
+ for (let i = 0; i < 3; i++) {
235
+ if ((aVer[i] ?? 0) !== (bVer[i] ?? 0)) {
236
+ return (bVer[i] ?? 0) - (aVer[i] ?? 0);
237
+ }
238
+ }
239
+ return 0;
240
+ });
241
+
242
+ return versions[0] ?? null;
243
+ } catch {
244
+ return null;
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Try to resolve a tool, returning null instead of throwing
250
+ *
251
+ * @param toolNameOrPath - Tool name or path
252
+ * @param options - Resolution options
253
+ * @returns ToolResolution or null
254
+ */
255
+ export function tryResolveTool(
256
+ toolNameOrPath: string,
257
+ options: ResolveOptions = {}
258
+ ): ToolResolution | null {
259
+ try {
260
+ // Check if it looks like a path
261
+ if (
262
+ toolNameOrPath.startsWith("/") ||
263
+ toolNameOrPath.startsWith("./") ||
264
+ toolNameOrPath.startsWith("../") ||
265
+ toolNameOrPath.includes("\\") ||
266
+ existsSync(toolNameOrPath)
267
+ ) {
268
+ return resolveToolFromPath(toolNameOrPath);
269
+ }
270
+
271
+ return resolveTool(toolNameOrPath, options);
272
+ } catch {
273
+ return null;
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Resolve a tool, automatically detecting if input is a path or name
279
+ *
280
+ * @param toolNameOrPath - Tool name or path to manifest/directory
281
+ * @param options - Resolution options
282
+ * @returns ToolResolution
283
+ * @throws ToolResolveError if not found
284
+ */
285
+ export function resolveToolAuto(
286
+ toolNameOrPath: string,
287
+ options: ResolveOptions = {}
288
+ ): ToolResolution {
289
+ // Check if it looks like a path
290
+ if (
291
+ toolNameOrPath.startsWith("/") ||
292
+ toolNameOrPath.startsWith("./") ||
293
+ toolNameOrPath.startsWith("../") ||
294
+ toolNameOrPath.includes("\\")
295
+ ) {
296
+ return resolveToolFromPath(toolNameOrPath);
297
+ }
298
+
299
+ // Check if the path exists as-is (could be a relative directory without ./)
300
+ if (existsSync(toolNameOrPath)) {
301
+ const result = tryLoadFromDir(resolve(toolNameOrPath), "file");
302
+ if (result) {
303
+ return result;
304
+ }
305
+ }
306
+
307
+ // Treat as tool name
308
+ return resolveTool(toolNameOrPath, options);
309
+ }
310
+
311
+ /**
312
+ * Get all locations where a tool might be installed
313
+ *
314
+ * @param toolName - Tool name
315
+ * @param options - Resolution options
316
+ * @returns Array of potential paths
317
+ */
318
+ export function getToolSearchPaths(toolName: string, options: ResolveOptions = {}): string[] {
319
+ const normalizedName = normalizeToolName(toolName);
320
+ const paths: string[] = [];
321
+
322
+ // Project tools
323
+ if (!options.skipProject) {
324
+ const projectDir = getProjectEnactDir(options.startDir);
325
+ if (projectDir) {
326
+ paths.push(join(projectDir, "tools", toolNameToPath(normalizedName)));
327
+ }
328
+ }
329
+
330
+ // Global tools (via tools.json → cache)
331
+ if (!options.skipUser) {
332
+ const globalVersion = getInstalledVersion(normalizedName, "global");
333
+ if (globalVersion) {
334
+ paths.push(getToolCachePath(normalizedName, globalVersion));
335
+ }
336
+ }
337
+
338
+ // Cache
339
+ if (!options.skipCache) {
340
+ const cacheDir = getCacheDir();
341
+ paths.push(join(cacheDir, toolNameToPath(normalizedName)));
342
+ }
343
+
344
+ return paths;
345
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Type exports from @enactprotocol/shared
3
+ */
4
+
5
+ export type {
6
+ // Manifest types
7
+ ToolManifest,
8
+ PackageManifest,
9
+ ParsedManifest,
10
+ // Sub-types
11
+ EnvVariable,
12
+ EnvVariables,
13
+ Author,
14
+ ToolAnnotations,
15
+ ResourceRequirements,
16
+ ToolExample,
17
+ // Validation types
18
+ ValidationResult,
19
+ ValidationError,
20
+ ValidationWarning,
21
+ // Resolution types
22
+ ToolLocation,
23
+ ToolResolution,
24
+ ManifestFileName,
25
+ } from "./manifest";
26
+
27
+ export {
28
+ MANIFEST_FILES,
29
+ PACKAGE_MANIFEST_FILE,
30
+ } from "./manifest";
@@ -0,0 +1,255 @@
1
+ /**
2
+ * TypeScript types for Enact tool manifests
3
+ * These types define the structure of enact.yaml and enact.md frontmatter
4
+ */
5
+
6
+ import type { JSONSchema7 } from "json-schema";
7
+
8
+ /**
9
+ * Environment variable declaration in a tool manifest
10
+ */
11
+ export interface EnvVariable {
12
+ /** Human-readable description of what this variable is for */
13
+ description: string;
14
+ /** If true, stored in OS keyring; if false, stored in .env files */
15
+ secret?: boolean;
16
+ /** Default value if not set (only for non-secrets) */
17
+ default?: string;
18
+ }
19
+
20
+ /**
21
+ * Environment variables map
22
+ */
23
+ export type EnvVariables = Record<string, EnvVariable>;
24
+
25
+ /**
26
+ * Author information
27
+ */
28
+ export interface Author {
29
+ /** Author name */
30
+ name: string;
31
+ /** Author email (optional) */
32
+ email?: string;
33
+ /** Author website URL (optional) */
34
+ url?: string;
35
+ }
36
+
37
+ /**
38
+ * Behavior annotations for AI models
39
+ */
40
+ export interface ToolAnnotations {
41
+ /** Human-readable display name */
42
+ title?: string;
43
+ /** Tool does not modify the environment */
44
+ readOnlyHint?: boolean;
45
+ /** Tool may make irreversible changes */
46
+ destructiveHint?: boolean;
47
+ /** Multiple executions produce the same result */
48
+ idempotentHint?: boolean;
49
+ /** Tool interacts with external systems (network, APIs) */
50
+ openWorldHint?: boolean;
51
+ }
52
+
53
+ /**
54
+ * Resource requirements for tool execution
55
+ */
56
+ export interface ResourceRequirements {
57
+ /** System memory needed (e.g., "512Mi", "2Gi") */
58
+ memory?: string;
59
+ /** GPU memory needed (e.g., "24Gi") */
60
+ gpu?: string;
61
+ /** Disk space needed (e.g., "100Gi") */
62
+ disk?: string;
63
+ }
64
+
65
+ /**
66
+ * Example/test case for a tool
67
+ */
68
+ export interface ToolExample {
69
+ /** Input parameters for this example */
70
+ input?: Record<string, unknown>;
71
+ /** Expected output (for validation) */
72
+ output?: unknown;
73
+ /** Description of this test case */
74
+ description?: string;
75
+ }
76
+
77
+ /**
78
+ * Complete tool manifest structure
79
+ * This represents the YAML frontmatter in enact.md or the full enact.yaml
80
+ */
81
+ export interface ToolManifest {
82
+ // ==================== Required Fields ====================
83
+
84
+ /** Hierarchical tool identifier (e.g., "org/category/tool-name") */
85
+ name: string;
86
+
87
+ /** Human-readable description of what the tool does */
88
+ description: string;
89
+
90
+ // ==================== Recommended Fields ====================
91
+
92
+ /** Version of the Enact protocol specification (e.g., "2.0.0") */
93
+ enact?: string;
94
+
95
+ /** Tool version in semver format (e.g., "1.2.3") */
96
+ version?: string;
97
+
98
+ /** Container base image for tool execution (e.g., "node:18-alpine") */
99
+ from?: string;
100
+
101
+ /** Build command(s) to run before execution (cached by Dagger) */
102
+ build?: string | string[];
103
+
104
+ /** Shell command to execute with ${parameter} substitution */
105
+ command?: string;
106
+
107
+ /** Maximum execution time (e.g., "30s", "5m", "1h") */
108
+ timeout?: string;
109
+
110
+ /** SPDX license identifier (e.g., "MIT", "Apache-2.0") */
111
+ license?: string;
112
+
113
+ /** Keywords for tool discovery and categorization */
114
+ tags?: string[];
115
+
116
+ // ==================== Schema Fields ====================
117
+
118
+ /** JSON Schema defining input parameters */
119
+ inputSchema?: JSONSchema7;
120
+
121
+ /** JSON Schema defining output structure */
122
+ outputSchema?: JSONSchema7;
123
+
124
+ // ==================== Environment Variables ====================
125
+
126
+ /** Environment variables and secrets required by the tool */
127
+ env?: EnvVariables;
128
+
129
+ // ==================== Behavior & Resources ====================
130
+
131
+ /** Behavior hints for AI models */
132
+ annotations?: ToolAnnotations;
133
+
134
+ /** Resource limits and requirements */
135
+ resources?: ResourceRequirements;
136
+
137
+ // ==================== Documentation ====================
138
+
139
+ /** Extended documentation (Markdown) */
140
+ doc?: string;
141
+
142
+ /** Tool creators and maintainers */
143
+ authors?: Author[];
144
+
145
+ // ==================== Testing ====================
146
+
147
+ /** Test cases and expected outputs */
148
+ examples?: ToolExample[];
149
+
150
+ // ==================== Custom Extensions ====================
151
+
152
+ /** Custom fields starting with x- (not included in signature verification) */
153
+ [key: `x-${string}`]: unknown;
154
+ }
155
+
156
+ /**
157
+ * Package-level configuration (enact-package.yaml)
158
+ * Provides shared configuration for all tools in a directory
159
+ */
160
+ export interface PackageManifest {
161
+ /** Version of the Enact protocol specification */
162
+ enact?: string;
163
+
164
+ /** Shared environment variables for all tools in this folder */
165
+ env?: EnvVariables;
166
+
167
+ /** Shared authors for all tools */
168
+ authors?: Author[];
169
+
170
+ /** Shared license for all tools */
171
+ license?: string;
172
+
173
+ /** Custom extension fields */
174
+ [key: `x-${string}`]: unknown;
175
+ }
176
+
177
+ /**
178
+ * Parsed manifest with optional markdown body
179
+ */
180
+ export interface ParsedManifest {
181
+ /** The parsed YAML frontmatter */
182
+ manifest: ToolManifest;
183
+ /** The markdown body content (if from .md file) */
184
+ body?: string | undefined;
185
+ /** The file format the manifest was loaded from */
186
+ format: "yaml" | "md";
187
+ }
188
+
189
+ /**
190
+ * Result of manifest validation
191
+ */
192
+ export interface ValidationResult {
193
+ /** Whether the manifest is valid */
194
+ valid: boolean;
195
+ /** Validation errors (if any) */
196
+ errors?: ValidationError[] | undefined;
197
+ /** Warnings (non-fatal issues) */
198
+ warnings?: ValidationWarning[] | undefined;
199
+ }
200
+
201
+ /**
202
+ * A validation error
203
+ */
204
+ export interface ValidationError {
205
+ /** Path to the field with the error (e.g., "inputSchema.properties.name") */
206
+ path: string;
207
+ /** Error message */
208
+ message: string;
209
+ /** Error code for programmatic handling */
210
+ code: string;
211
+ }
212
+
213
+ /**
214
+ * A validation warning
215
+ */
216
+ export interface ValidationWarning {
217
+ /** Path to the field with the warning */
218
+ path: string;
219
+ /** Warning message */
220
+ message: string;
221
+ /** Warning code */
222
+ code: string;
223
+ }
224
+
225
+ /**
226
+ * Tool location types for resolution
227
+ */
228
+ export type ToolLocation = "file" | "project" | "user" | "cache" | "registry";
229
+
230
+ /**
231
+ * Result of tool resolution
232
+ */
233
+ export interface ToolResolution {
234
+ /** The loaded and validated manifest */
235
+ manifest: ToolManifest;
236
+ /** Directory containing the tool */
237
+ sourceDir: string;
238
+ /** Where the tool was found */
239
+ location: ToolLocation;
240
+ /** Path to the manifest file */
241
+ manifestPath: string;
242
+ /** Tool version (if available) */
243
+ version?: string | undefined;
244
+ }
245
+
246
+ /**
247
+ * Supported manifest file names
248
+ */
249
+ export const MANIFEST_FILES = ["enact.md", "enact.yaml", "enact.yml"] as const;
250
+ export type ManifestFileName = (typeof MANIFEST_FILES)[number];
251
+
252
+ /**
253
+ * Package manifest file name
254
+ */
255
+ export const PACKAGE_MANIFEST_FILE = "enact-package.yaml";