@enactprotocol/shared 1.2.11 → 2.0.0
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.
- package/README.md +44 -0
- package/package.json +16 -58
- package/src/config.ts +476 -0
- package/src/constants.ts +36 -0
- package/src/execution/command.ts +314 -0
- package/src/execution/index.ts +73 -0
- package/src/execution/runtime.ts +308 -0
- package/src/execution/types.ts +379 -0
- package/src/execution/validation.ts +508 -0
- package/src/index.ts +237 -30
- package/src/manifest/index.ts +36 -0
- package/src/manifest/loader.ts +187 -0
- package/src/manifest/parser.ts +173 -0
- package/src/manifest/validator.ts +309 -0
- package/src/paths.ts +108 -0
- package/src/registry.ts +219 -0
- package/src/resolver.ts +345 -0
- package/src/types/index.ts +30 -0
- package/src/types/manifest.ts +255 -0
- package/src/types.ts +5 -188
- package/src/utils/fs.ts +281 -0
- package/src/utils/logger.ts +270 -59
- package/src/utils/version.ts +304 -36
- package/tests/config.test.ts +515 -0
- package/tests/execution/command.test.ts +317 -0
- package/tests/execution/validation.test.ts +384 -0
- package/tests/fixtures/invalid-tool.yaml +4 -0
- package/tests/fixtures/valid-tool.md +62 -0
- package/tests/fixtures/valid-tool.yaml +40 -0
- package/tests/index.test.ts +8 -0
- package/tests/manifest/loader.test.ts +291 -0
- package/tests/manifest/parser.test.ts +345 -0
- package/tests/manifest/validator.test.ts +394 -0
- package/tests/manifest-types.test.ts +358 -0
- package/tests/paths.test.ts +153 -0
- package/tests/registry.test.ts +231 -0
- package/tests/resolver.test.ts +272 -0
- package/tests/utils/fs.test.ts +388 -0
- package/tests/utils/logger.test.ts +480 -0
- package/tests/utils/version.test.ts +390 -0
- package/tsconfig.json +12 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/LocalToolResolver.d.ts +0 -84
- package/dist/LocalToolResolver.js +0 -353
- package/dist/api/enact-api.d.ts +0 -130
- package/dist/api/enact-api.js +0 -428
- package/dist/api/index.d.ts +0 -2
- package/dist/api/index.js +0 -2
- package/dist/api/types.d.ts +0 -103
- package/dist/api/types.js +0 -1
- package/dist/constants.d.ts +0 -7
- package/dist/constants.js +0 -10
- package/dist/core/DaggerExecutionProvider.d.ts +0 -169
- package/dist/core/DaggerExecutionProvider.js +0 -1029
- package/dist/core/DirectExecutionProvider.d.ts +0 -23
- package/dist/core/DirectExecutionProvider.js +0 -406
- package/dist/core/EnactCore.d.ts +0 -162
- package/dist/core/EnactCore.js +0 -597
- package/dist/core/NativeExecutionProvider.d.ts +0 -9
- package/dist/core/NativeExecutionProvider.js +0 -16
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.js +0 -3
- package/dist/exec/index.d.ts +0 -3
- package/dist/exec/index.js +0 -3
- package/dist/exec/logger.d.ts +0 -11
- package/dist/exec/logger.js +0 -57
- package/dist/exec/validate.d.ts +0 -5
- package/dist/exec/validate.js +0 -167
- package/dist/index.d.ts +0 -21
- package/dist/index.js +0 -25
- package/dist/lib/enact-direct.d.ts +0 -150
- package/dist/lib/enact-direct.js +0 -159
- package/dist/lib/index.d.ts +0 -1
- package/dist/lib/index.js +0 -1
- package/dist/security/index.d.ts +0 -3
- package/dist/security/index.js +0 -3
- package/dist/security/security.d.ts +0 -23
- package/dist/security/security.js +0 -137
- package/dist/security/sign.d.ts +0 -103
- package/dist/security/sign.js +0 -666
- package/dist/security/verification-enforcer.d.ts +0 -53
- package/dist/security/verification-enforcer.js +0 -204
- package/dist/services/McpCoreService.d.ts +0 -98
- package/dist/services/McpCoreService.js +0 -124
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/types.d.ts +0 -132
- package/dist/types.js +0 -3
- package/dist/utils/config.d.ts +0 -111
- package/dist/utils/config.js +0 -342
- package/dist/utils/env-loader.d.ts +0 -54
- package/dist/utils/env-loader.js +0 -270
- package/dist/utils/help.d.ts +0 -36
- package/dist/utils/help.js +0 -248
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.js +0 -7
- package/dist/utils/logger.d.ts +0 -35
- package/dist/utils/logger.js +0 -75
- package/dist/utils/silent-monitor.d.ts +0 -67
- package/dist/utils/silent-monitor.js +0 -242
- package/dist/utils/timeout.d.ts +0 -5
- package/dist/utils/timeout.js +0 -23
- package/dist/utils/version.d.ts +0 -4
- package/dist/utils/version.js +0 -35
- package/dist/web/env-manager-server.d.ts +0 -29
- package/dist/web/env-manager-server.js +0 -367
- package/dist/web/index.d.ts +0 -1
- package/dist/web/index.js +0 -1
- package/src/LocalToolResolver.ts +0 -424
- package/src/api/enact-api.ts +0 -604
- package/src/api/index.ts +0 -2
- package/src/api/types.ts +0 -114
- package/src/core/DaggerExecutionProvider.ts +0 -1357
- package/src/core/DirectExecutionProvider.ts +0 -484
- package/src/core/EnactCore.ts +0 -847
- package/src/core/index.ts +0 -3
- package/src/exec/index.ts +0 -3
- package/src/exec/logger.ts +0 -63
- package/src/exec/validate.ts +0 -238
- package/src/lib/enact-direct.ts +0 -254
- package/src/lib/index.ts +0 -1
- package/src/services/McpCoreService.ts +0 -201
- package/src/services/index.ts +0 -1
- package/src/utils/config.ts +0 -438
- package/src/utils/env-loader.ts +0 -370
- package/src/utils/help.ts +0 -257
- package/src/utils/index.ts +0 -7
- package/src/utils/silent-monitor.ts +0 -328
- package/src/utils/timeout.ts +0 -26
- package/src/web/env-manager-server.ts +0 -465
- package/src/web/index.ts +0 -1
- package/src/web/static/app.js +0 -663
- package/src/web/static/index.html +0 -117
- package/src/web/static/style.css +0 -291
package/src/resolver.ts
ADDED
|
@@ -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";
|