@enactprotocol/shared 1.2.13 → 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.
Files changed (134) hide show
  1. package/README.md +44 -0
  2. package/package.json +16 -58
  3. package/src/config.ts +476 -0
  4. package/src/constants.ts +36 -0
  5. package/src/execution/command.ts +314 -0
  6. package/src/execution/index.ts +73 -0
  7. package/src/execution/runtime.ts +308 -0
  8. package/src/execution/types.ts +379 -0
  9. package/src/execution/validation.ts +508 -0
  10. package/src/index.ts +237 -30
  11. package/src/manifest/index.ts +36 -0
  12. package/src/manifest/loader.ts +187 -0
  13. package/src/manifest/parser.ts +173 -0
  14. package/src/manifest/validator.ts +309 -0
  15. package/src/paths.ts +108 -0
  16. package/src/registry.ts +219 -0
  17. package/src/resolver.ts +345 -0
  18. package/src/types/index.ts +30 -0
  19. package/src/types/manifest.ts +255 -0
  20. package/src/types.ts +5 -188
  21. package/src/utils/fs.ts +281 -0
  22. package/src/utils/logger.ts +270 -59
  23. package/src/utils/version.ts +304 -36
  24. package/tests/config.test.ts +515 -0
  25. package/tests/execution/command.test.ts +317 -0
  26. package/tests/execution/validation.test.ts +384 -0
  27. package/tests/fixtures/invalid-tool.yaml +4 -0
  28. package/tests/fixtures/valid-tool.md +62 -0
  29. package/tests/fixtures/valid-tool.yaml +40 -0
  30. package/tests/index.test.ts +8 -0
  31. package/tests/manifest/loader.test.ts +291 -0
  32. package/tests/manifest/parser.test.ts +345 -0
  33. package/tests/manifest/validator.test.ts +394 -0
  34. package/tests/manifest-types.test.ts +358 -0
  35. package/tests/paths.test.ts +153 -0
  36. package/tests/registry.test.ts +231 -0
  37. package/tests/resolver.test.ts +272 -0
  38. package/tests/utils/fs.test.ts +388 -0
  39. package/tests/utils/logger.test.ts +480 -0
  40. package/tests/utils/version.test.ts +390 -0
  41. package/tsconfig.json +12 -0
  42. package/tsconfig.tsbuildinfo +1 -0
  43. package/dist/LocalToolResolver.d.ts +0 -84
  44. package/dist/LocalToolResolver.js +0 -353
  45. package/dist/api/enact-api.d.ts +0 -130
  46. package/dist/api/enact-api.js +0 -428
  47. package/dist/api/index.d.ts +0 -2
  48. package/dist/api/index.js +0 -2
  49. package/dist/api/types.d.ts +0 -103
  50. package/dist/api/types.js +0 -1
  51. package/dist/constants.d.ts +0 -7
  52. package/dist/constants.js +0 -10
  53. package/dist/core/DaggerExecutionProvider.d.ts +0 -169
  54. package/dist/core/DaggerExecutionProvider.js +0 -1029
  55. package/dist/core/DirectExecutionProvider.d.ts +0 -23
  56. package/dist/core/DirectExecutionProvider.js +0 -406
  57. package/dist/core/EnactCore.d.ts +0 -162
  58. package/dist/core/EnactCore.js +0 -597
  59. package/dist/core/NativeExecutionProvider.d.ts +0 -9
  60. package/dist/core/NativeExecutionProvider.js +0 -16
  61. package/dist/core/index.d.ts +0 -3
  62. package/dist/core/index.js +0 -3
  63. package/dist/exec/index.d.ts +0 -3
  64. package/dist/exec/index.js +0 -3
  65. package/dist/exec/logger.d.ts +0 -11
  66. package/dist/exec/logger.js +0 -57
  67. package/dist/exec/validate.d.ts +0 -5
  68. package/dist/exec/validate.js +0 -167
  69. package/dist/index.d.ts +0 -21
  70. package/dist/index.js +0 -25
  71. package/dist/lib/enact-direct.d.ts +0 -150
  72. package/dist/lib/enact-direct.js +0 -159
  73. package/dist/lib/index.d.ts +0 -1
  74. package/dist/lib/index.js +0 -1
  75. package/dist/security/index.d.ts +0 -3
  76. package/dist/security/index.js +0 -3
  77. package/dist/security/security.d.ts +0 -23
  78. package/dist/security/security.js +0 -137
  79. package/dist/security/sign.d.ts +0 -103
  80. package/dist/security/sign.js +0 -666
  81. package/dist/security/verification-enforcer.d.ts +0 -53
  82. package/dist/security/verification-enforcer.js +0 -204
  83. package/dist/services/McpCoreService.d.ts +0 -98
  84. package/dist/services/McpCoreService.js +0 -124
  85. package/dist/services/index.d.ts +0 -1
  86. package/dist/services/index.js +0 -1
  87. package/dist/types.d.ts +0 -132
  88. package/dist/types.js +0 -3
  89. package/dist/utils/config.d.ts +0 -111
  90. package/dist/utils/config.js +0 -342
  91. package/dist/utils/env-loader.d.ts +0 -54
  92. package/dist/utils/env-loader.js +0 -270
  93. package/dist/utils/help.d.ts +0 -36
  94. package/dist/utils/help.js +0 -248
  95. package/dist/utils/index.d.ts +0 -7
  96. package/dist/utils/index.js +0 -7
  97. package/dist/utils/logger.d.ts +0 -35
  98. package/dist/utils/logger.js +0 -75
  99. package/dist/utils/silent-monitor.d.ts +0 -67
  100. package/dist/utils/silent-monitor.js +0 -242
  101. package/dist/utils/timeout.d.ts +0 -5
  102. package/dist/utils/timeout.js +0 -23
  103. package/dist/utils/version.d.ts +0 -4
  104. package/dist/utils/version.js +0 -35
  105. package/dist/web/env-manager-server.d.ts +0 -29
  106. package/dist/web/env-manager-server.js +0 -367
  107. package/dist/web/index.d.ts +0 -1
  108. package/dist/web/index.js +0 -1
  109. package/src/LocalToolResolver.ts +0 -424
  110. package/src/api/enact-api.ts +0 -604
  111. package/src/api/index.ts +0 -2
  112. package/src/api/types.ts +0 -114
  113. package/src/core/DaggerExecutionProvider.ts +0 -1357
  114. package/src/core/DirectExecutionProvider.ts +0 -484
  115. package/src/core/EnactCore.ts +0 -847
  116. package/src/core/index.ts +0 -3
  117. package/src/exec/index.ts +0 -3
  118. package/src/exec/logger.ts +0 -63
  119. package/src/exec/validate.ts +0 -238
  120. package/src/lib/enact-direct.ts +0 -254
  121. package/src/lib/index.ts +0 -1
  122. package/src/services/McpCoreService.ts +0 -201
  123. package/src/services/index.ts +0 -1
  124. package/src/utils/config.ts +0 -438
  125. package/src/utils/env-loader.ts +0 -370
  126. package/src/utils/help.ts +0 -257
  127. package/src/utils/index.ts +0 -7
  128. package/src/utils/silent-monitor.ts +0 -328
  129. package/src/utils/timeout.ts +0 -26
  130. package/src/web/env-manager-server.ts +0 -465
  131. package/src/web/index.ts +0 -1
  132. package/src/web/static/app.js +0 -663
  133. package/src/web/static/index.html +0 -117
  134. package/src/web/static/style.css +0 -291
@@ -1,465 +0,0 @@
1
- // src/web/env-manager-server.ts - Web server for managing environment variables
2
- import { createServer, IncomingMessage, ServerResponse } from "http";
3
- import { parse } from "url";
4
- import { readFile, writeFile, mkdir, readdir, stat } from "fs/promises";
5
- import { existsSync } from "fs";
6
- import { join, dirname } from "path";
7
- import { homedir } from "os";
8
- import { fileURLToPath } from "url";
9
- import logger from "../exec/logger";
10
-
11
- // Get the directory of this module
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
-
15
- // Configuration paths
16
- const CONFIG_DIR = join(homedir(), ".enact");
17
- const ENV_BASE_DIR = join(CONFIG_DIR, "env");
18
-
19
- // Find static files - try multiple locations
20
- function findStaticDir(): string {
21
- const candidates = [
22
- join(__dirname, "web", "static"), // If running from built package (dist/web/static)
23
- join(__dirname, "static"), // If running from source
24
- join(__dirname, "..", "src", "web", "static"), // If bundled in dist
25
- join(__dirname, "..", "..", "src", "web", "static"), // If nested deeper
26
- join(process.cwd(), "src", "web", "static"), // From project root
27
- // When installed via npm, static files are in the package root
28
- join(__dirname, "..", "..", "..", "src", "web", "static"), // node_modules/enact-cli/src/web/static from node_modules/enact-cli/dist/web/
29
- join(__dirname, "..", "..", "src", "web", "static"), // node_modules/enact-cli/src/web/static from node_modules/enact-cli/dist/
30
- ];
31
-
32
- for (const candidate of candidates) {
33
- if (existsSync(join(candidate, "index.html"))) {
34
- logger.debug(`Found static directory: ${candidate}`);
35
- return candidate;
36
- }
37
- }
38
-
39
- throw new Error(
40
- "Could not find static directory. Tried: " + candidates.join(", "),
41
- );
42
- }
43
-
44
- const STATIC_DIR = findStaticDir();
45
-
46
- interface PackageEnvInfo {
47
- namespace: string;
48
- path: string;
49
- variables: Record<string, string>;
50
- }
51
-
52
- /**
53
- * Parse simple .env file format (KEY=value)
54
- */
55
- function parseDotEnv(content: string): Record<string, string> {
56
- const vars: Record<string, string> = {};
57
- const lines = content.split("\n");
58
-
59
- for (const line of lines) {
60
- const trimmed = line.trim();
61
- if (!trimmed || trimmed.startsWith("#")) {
62
- continue; // Skip empty lines and comments
63
- }
64
-
65
- const equalIndex = trimmed.indexOf("=");
66
- if (equalIndex === -1) {
67
- continue; // Skip lines without '='
68
- }
69
-
70
- const key = trimmed.slice(0, equalIndex).trim();
71
- let value = trimmed.slice(equalIndex + 1).trim();
72
-
73
- // Remove quotes if present
74
- if (
75
- (value.startsWith('"') && value.endsWith('"')) ||
76
- (value.startsWith("'") && value.endsWith("'"))
77
- ) {
78
- value = value.slice(1, -1);
79
- }
80
-
81
- if (key) {
82
- vars[key] = value;
83
- }
84
- }
85
-
86
- return vars;
87
- }
88
-
89
- /**
90
- * Convert environment variables to .env file format
91
- */
92
- function generateDotEnv(vars: Record<string, string>): string {
93
- return (
94
- Object.entries(vars)
95
- .map(([key, value]) => {
96
- // Escape value if it contains special characters
97
- const needsQuotes =
98
- value.includes(" ") ||
99
- value.includes("\t") ||
100
- value.includes("\n") ||
101
- value.includes('"');
102
- const escapedValue = needsQuotes
103
- ? `"${value.replace(/"/g, '\\"')}"`
104
- : value;
105
- return `${key}=${escapedValue}`;
106
- })
107
- .join("\n") + "\n"
108
- );
109
- }
110
-
111
- /**
112
- * Get all package namespaces with environment variables
113
- */
114
- async function getAllPackageNamespaces(): Promise<PackageEnvInfo[]> {
115
- const packages: PackageEnvInfo[] = [];
116
-
117
- if (!existsSync(ENV_BASE_DIR)) {
118
- return packages;
119
- }
120
-
121
- try {
122
- await scanDirectory(ENV_BASE_DIR, "", packages);
123
- } catch (error) {
124
- logger.error("Failed to scan env directory:", error);
125
- }
126
-
127
- return packages;
128
- }
129
-
130
- /**
131
- * Recursively scan directory for .env files
132
- */
133
- async function scanDirectory(
134
- dir: string,
135
- relativePath: string,
136
- packages: PackageEnvInfo[],
137
- ): Promise<void> {
138
- try {
139
- const entries = await readdir(dir);
140
-
141
- for (const entry of entries) {
142
- const fullPath = join(dir, entry);
143
- const stats = await stat(fullPath);
144
-
145
- if (stats.isDirectory()) {
146
- // Recursively scan subdirectories
147
- const newRelativePath = relativePath
148
- ? `${relativePath}/${entry}`
149
- : entry;
150
- await scanDirectory(fullPath, newRelativePath, packages);
151
- } else if (entry === ".env") {
152
- // Found a .env file
153
- const namespace = relativePath || "root";
154
- try {
155
- const content = await readFile(fullPath, "utf8");
156
- const variables = parseDotEnv(content);
157
-
158
- packages.push({
159
- namespace,
160
- path: fullPath,
161
- variables,
162
- });
163
- } catch (error) {
164
- logger.error(`Failed to read .env file at ${fullPath}:`, error);
165
- }
166
- }
167
- }
168
- } catch (error) {
169
- logger.error(`Failed to scan directory ${dir}:`, error);
170
- }
171
- }
172
-
173
- /**
174
- * Get environment variables for a specific package namespace
175
- */
176
- async function getPackageEnvVars(
177
- namespace: string,
178
- ): Promise<Record<string, string>> {
179
- const envFile = join(ENV_BASE_DIR, namespace, ".env");
180
-
181
- if (!existsSync(envFile)) {
182
- return {};
183
- }
184
-
185
- try {
186
- const content = await readFile(envFile, "utf8");
187
- return parseDotEnv(content);
188
- } catch (error) {
189
- logger.error(`Failed to read env file for ${namespace}:`, error);
190
- return {};
191
- }
192
- }
193
-
194
- /**
195
- * Set environment variable for a package namespace
196
- */
197
- async function setPackageEnvVar(
198
- namespace: string,
199
- key: string,
200
- value: string,
201
- ): Promise<void> {
202
- const envFile = join(ENV_BASE_DIR, namespace, ".env");
203
- const envDir = dirname(envFile);
204
-
205
- // Ensure directory exists
206
- if (!existsSync(envDir)) {
207
- await mkdir(envDir, { recursive: true });
208
- }
209
-
210
- // Read existing variables
211
- const existingVars = await getPackageEnvVars(namespace);
212
-
213
- // Update variables
214
- existingVars[key] = value;
215
-
216
- // Write back to file
217
- const envContent = generateDotEnv(existingVars);
218
- await writeFile(envFile, envContent, "utf8");
219
- }
220
-
221
- /**
222
- * Delete environment variable for a package namespace
223
- */
224
- async function deletePackageEnvVar(
225
- namespace: string,
226
- key: string,
227
- ): Promise<void> {
228
- const existingVars = await getPackageEnvVars(namespace);
229
-
230
- if (!(key in existingVars)) {
231
- throw new Error(
232
- `Environment variable '${key}' not found in package '${namespace}'`,
233
- );
234
- }
235
-
236
- delete existingVars[key];
237
-
238
- const envFile = join(ENV_BASE_DIR, namespace, ".env");
239
- const envContent = generateDotEnv(existingVars);
240
- await writeFile(envFile, envContent, "utf8");
241
- }
242
-
243
- /**
244
- * Serve static files
245
- */
246
- async function serveStaticFile(
247
- filePath: string,
248
- res: ServerResponse,
249
- ): Promise<void> {
250
- try {
251
- const content = await readFile(filePath, "utf8");
252
- const ext = filePath.split(".").pop()?.toLowerCase();
253
-
254
- let contentType = "text/plain";
255
- switch (ext) {
256
- case "html":
257
- contentType = "text/html";
258
- break;
259
- case "css":
260
- contentType = "text/css";
261
- break;
262
- case "js":
263
- contentType = "application/javascript";
264
- break;
265
- case "json":
266
- contentType = "application/json";
267
- break;
268
- }
269
-
270
- res.writeHead(200, { "Content-Type": contentType });
271
- res.end(content);
272
- } catch (error) {
273
- logger.error("Error serving static file:", error);
274
- res.writeHead(404, { "Content-Type": "text/plain" });
275
- res.end("File not found");
276
- }
277
- }
278
-
279
- /**
280
- * Handle HTTP requests
281
- */
282
- async function handleRequest(
283
- req: IncomingMessage,
284
- res: ServerResponse,
285
- ): Promise<void> {
286
- const urlParts = parse(req.url || "", true);
287
- const pathname = urlParts.pathname || "/";
288
- const method = req.method || "GET";
289
-
290
- // Set CORS headers
291
- res.setHeader("Access-Control-Allow-Origin", "*");
292
- res.setHeader(
293
- "Access-Control-Allow-Methods",
294
- "GET, POST, PUT, DELETE, OPTIONS",
295
- );
296
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
297
-
298
- if (method === "OPTIONS") {
299
- res.writeHead(200);
300
- res.end();
301
- return;
302
- }
303
-
304
- try {
305
- if (pathname === "/") {
306
- // Serve main HTML page
307
- await serveStaticFile(join(STATIC_DIR, "index.html"), res);
308
- } else if (pathname === "/style.css") {
309
- // Serve CSS file
310
- await serveStaticFile(join(STATIC_DIR, "style.css"), res);
311
- } else if (pathname === "/app.js") {
312
- // Serve JavaScript file
313
- await serveStaticFile(join(STATIC_DIR, "app.js"), res);
314
- } else if (pathname === "/favicon.ico") {
315
- // Serve a simple SVG favicon
316
- const favicon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y=".9em" font-size="90">🌐</text></svg>`;
317
- res.writeHead(200, { "Content-Type": "image/svg+xml" });
318
- res.end(favicon);
319
- } else if (pathname === "/api/packages" && method === "GET") {
320
- // Get all packages
321
- const packages = await getAllPackageNamespaces();
322
- res.writeHead(200, { "Content-Type": "application/json" });
323
- res.end(JSON.stringify({ packages }));
324
- } else if (pathname === "/api/packages" && method === "POST") {
325
- // Create new package
326
- const body = await getRequestBody(req);
327
- const { namespace } = JSON.parse(body);
328
-
329
- if (!namespace) {
330
- res.writeHead(400, { "Content-Type": "application/json" });
331
- res.end(JSON.stringify({ error: "Namespace is required" }));
332
- return;
333
- }
334
-
335
- const envDir = join(ENV_BASE_DIR, namespace);
336
- const envFile = join(envDir, ".env");
337
-
338
- if (!existsSync(envDir)) {
339
- await mkdir(envDir, { recursive: true });
340
- }
341
-
342
- if (!existsSync(envFile)) {
343
- await writeFile(envFile, "", "utf8");
344
- }
345
-
346
- res.writeHead(200, { "Content-Type": "application/json" });
347
- res.end(JSON.stringify({ success: true }));
348
- } else if (pathname?.startsWith("/api/packages/") && method === "GET") {
349
- // Get specific package variables
350
- const namespace = decodeURIComponent(
351
- pathname.replace("/api/packages/", ""),
352
- );
353
- const variables = await getPackageEnvVars(namespace);
354
-
355
- res.writeHead(200, { "Content-Type": "application/json" });
356
- res.end(JSON.stringify({ namespace, variables }));
357
- } else if (
358
- pathname?.startsWith("/api/packages/") &&
359
- pathname.endsWith("/variables") &&
360
- method === "POST"
361
- ) {
362
- // Add/update variable
363
- const namespace = decodeURIComponent(
364
- pathname.replace("/api/packages/", "").replace("/variables", ""),
365
- );
366
- const body = await getRequestBody(req);
367
- const { key, value } = JSON.parse(body);
368
-
369
- if (!key || value === undefined) {
370
- res.writeHead(400, { "Content-Type": "application/json" });
371
- res.end(JSON.stringify({ error: "Key and value are required" }));
372
- return;
373
- }
374
-
375
- await setPackageEnvVar(namespace, key, value);
376
-
377
- res.writeHead(200, { "Content-Type": "application/json" });
378
- res.end(JSON.stringify({ success: true }));
379
- } else if (pathname?.includes("/variables/") && method === "DELETE") {
380
- // Delete variable
381
- const pathParts = pathname.split("/");
382
- const variableIndex = pathParts.indexOf("variables");
383
- const namespace = decodeURIComponent(
384
- pathParts.slice(3, variableIndex).join("/"),
385
- );
386
- const key = decodeURIComponent(pathParts[variableIndex + 1]);
387
-
388
- await deletePackageEnvVar(namespace, key);
389
-
390
- res.writeHead(200, { "Content-Type": "application/json" });
391
- res.end(JSON.stringify({ success: true }));
392
- } else {
393
- // 404 Not Found
394
- res.writeHead(404, { "Content-Type": "application/json" });
395
- res.end(JSON.stringify({ error: "Not found" }));
396
- }
397
- } catch (error) {
398
- logger.error("Web server error:", error);
399
- res.writeHead(500, { "Content-Type": "application/json" });
400
- res.end(
401
- JSON.stringify({
402
- error: error instanceof Error ? error.message : "Internal server error",
403
- }),
404
- );
405
- }
406
- }
407
-
408
- /**
409
- * Get request body as string
410
- */
411
- function getRequestBody(req: IncomingMessage): Promise<string> {
412
- return new Promise((resolve, reject) => {
413
- let body = "";
414
- req.on("data", (chunk) => {
415
- body += chunk.toString();
416
- });
417
- req.on("end", () => {
418
- resolve(body);
419
- });
420
- req.on("error", reject);
421
- });
422
- }
423
-
424
- /**
425
- * Start the web server
426
- */
427
- export function startEnvManagerServer(
428
- port: number = 5555,
429
- ): Promise<{ server: any; port: number }> {
430
- return new Promise((resolve, reject) => {
431
- const server = createServer(handleRequest);
432
-
433
- // Try to start on the specified port, fallback to a random port if unavailable
434
- server.listen(port, () => {
435
- const actualPort = (server.address() as any)?.port || port;
436
- logger.info(
437
- `🌐 Environment Manager web server started on http://localhost:${actualPort}`,
438
- );
439
- resolve({ server, port: actualPort });
440
- });
441
-
442
- server.on("error", (error: any) => {
443
- if (error.code === "EADDRINUSE") {
444
- // Port is in use, try a random port
445
- server.listen(0, () => {
446
- const actualPort = (server.address() as any)?.port;
447
- logger.info(
448
- `🌐 Environment Manager web server started on http://localhost:${actualPort} (port ${port} was in use)`,
449
- );
450
- resolve({ server, port: actualPort });
451
- });
452
- } else {
453
- reject(error);
454
- }
455
- });
456
- });
457
- }
458
-
459
- // Export additional functions for use by MCP tools
460
- export {
461
- getAllPackageNamespaces,
462
- getPackageEnvVars,
463
- setPackageEnvVar,
464
- deletePackageEnvVar,
465
- };
package/src/web/index.ts DELETED
@@ -1 +0,0 @@
1
- export * from './env-manager-server';