@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
package/src/types.ts CHANGED
@@ -1,189 +1,6 @@
1
- // src/types.ts - Type definitions for Enact CLI Core
2
- export interface EnactTool {
3
- // REQUIRED FIELDS
4
- name: string; // Tool identifier with hierarchical path
5
- description: string; // Human-readable description
6
- command: string; // Shell command to execute with version pins
1
+ /**
2
+ * Type definitions for shared utilities
3
+ */
7
4
 
8
- // RECOMMENDED FIELDS
9
- from?: string; // Container image to run the command on (optional, defaults to system shell)
10
- timeout?: string; // Go duration format: "30s", "5m", "1h" (default: "30s")
11
- tags?: string[]; // Tags for search and categorization
12
- license?: string; // SPDX License identifier (e.g., "MIT", "Apache-2.0")
13
- outputSchema?: JSONSchemaDefinition; // Output structure as JSON Schema (strongly recommended)
14
-
15
- // OPTIONAL FIELDS
16
- enact?: string; // Protocol version (e.g., "1.0.0")
17
- version?: string; // Tool definition version for tracking changes
18
- namespace?: string; // Environment variable namespace (deprecated, use name hierarchy)
19
-
20
- // Resource requirements
21
- resources?: {
22
- memory?: string; // System memory needed (e.g., "16Gi", "32Gi")
23
- gpu?: string; // GPU memory needed (e.g., "24Gi", "48Gi")
24
- disk?: string; // Disk space needed (e.g., "100Gi", "500Gi")
25
- };
26
-
27
- // Environment variables
28
- env?: Record<
29
- string,
30
- {
31
- description: string; // What this variable is for (required)
32
- source: string; // Where to get this value (required)
33
- required: boolean; // Whether this is required (required)
34
- default?: string; // Default value if not set (optional)
35
- }
36
- >;
37
-
38
- // Input/Output JSON Schemas
39
- inputSchema?: JSONSchemaDefinition;
40
-
41
- // Documentation and Testing
42
- doc?: string; // Markdown documentation
43
- authors?: Array<{
44
- name: string; // Author name (required)
45
- email?: string; // Author email (optional)
46
- url?: string; // Author website (optional)
47
- }>;
48
-
49
- examples?: Array<{
50
- input: Record<string, any>; // Input parameters
51
- output?: any; // Expected output
52
- description?: string; // Test description
53
- }>;
54
-
55
- // Behavior Annotations (MCP-aligned, all default to false)
56
- annotations?: {
57
- title?: string; // Human-readable display name
58
- readOnlyHint?: boolean; // No environment modifications
59
- destructiveHint?: boolean; // May make irreversible changes
60
- idempotentHint?: boolean; // Multiple calls = single call
61
- openWorldHint?: boolean; // Interacts with external systems
62
- };
63
-
64
- // Security
65
- signature?: {
66
- algorithm: string; // Hash algorithm: "sha256"
67
- type: string; // Signature type: "ecdsa-p256"
68
- signer: string; // Signer identifier
69
- created: string; // ISO timestamp
70
- value: string; // Base64 encoded signature
71
- role?: string; // Optional description of the signer
72
- };
73
-
74
- // Multi-signature support (array format)
75
- signatures?: {
76
- signer: string; // Signer identifier (UUID or human-readable name)
77
- algorithm: string; // Hash algorithm: "sha256"
78
- type: string; // Signature type: "ecdsa-p256"
79
- value: string; // Base64 encoded signature
80
- created: string; // ISO timestamp
81
- role?: string; // Optional description of the signer (e.g., "author", "reviewer", "approver")
82
- }[];
83
-
84
- // Extensions pattern (x-prefixed fields)
85
- [key: string]: any; // Allow x- prefixed extension fields
86
- }
87
-
88
- // JSON Schema type definitions
89
- export interface JSONSchemaDefinition {
90
- type?: string | string[]; // JSON Schema type(s)
91
- description?: string; // Human-readable description
92
- format?: string; // Format specifier (e.g., "email", "date-time")
93
- default?: any; // Default value
94
- enum?: any[]; // Enumeration of possible values
95
- const?: any; // Constant value
96
-
97
- // String validations
98
- pattern?: string; // Regular expression pattern
99
- minLength?: number; // Minimum string length
100
- maxLength?: number; // Maximum string length
101
-
102
- // Number validations
103
- minimum?: number; // Minimum value
104
- maximum?: number; // Maximum value
105
- exclusiveMinimum?: number; // Exclusive minimum
106
- exclusiveMaximum?: number; // Exclusive maximum
107
- multipleOf?: number; // Multiple of
108
-
109
- // Array validations
110
- items?: JSONSchemaDefinition | JSONSchemaDefinition[]; // Items schema
111
- minItems?: number; // Minimum items
112
- maxItems?: number; // Maximum items
113
- uniqueItems?: boolean; // Items must be unique
114
-
115
- // Object validations
116
- properties?: Record<string, JSONSchemaDefinition>; // Properties
117
- required?: string[]; // Required properties
118
- additionalProperties?: JSONSchemaDefinition | boolean; // Additional properties
119
-
120
- // Combiners
121
- allOf?: JSONSchemaDefinition[]; // All of these schemas
122
- anyOf?: JSONSchemaDefinition[]; // Any of these schemas
123
- oneOf?: JSONSchemaDefinition[]; // Exactly one of these schemas
124
- not?: JSONSchemaDefinition; // Not this schema
125
-
126
- // Other
127
- definitions?: Record<string, JSONSchemaDefinition>; // Definitions
128
- $ref?: string; // JSON Schema reference
129
- $id?: string; // Schema ID
130
- $schema?: string; // Schema version
131
-
132
- // Custom extensions
133
- [key: string]: any; // Additional properties
134
- }
135
-
136
- export interface ExecutionResult {
137
- success: boolean;
138
- output?: any; // Command output/result
139
- error?: {
140
- message: string;
141
- code?: string;
142
- details?: any;
143
- };
144
- metadata: {
145
- executionId: string;
146
- toolName: string; // Changed from toolId
147
- version?: string;
148
- executedAt: string;
149
- environment: string;
150
- timeout?: string;
151
- command?: string; // The actual command that was executed
152
- };
153
- }
154
-
155
- // Execution environment interface
156
- export interface ExecutionEnvironment {
157
- vars: Record<string, any>; // Environment variables
158
- resources?: {
159
- memory?: string;
160
- gpu?: string;
161
- disk?: string;
162
- timeout?: string;
163
- };
164
- namespace?: string; // Environment variable namespace
165
- mount?: string; // Mount local directory to container (format: "localPath" or "localPath:containerPath")
166
- }
167
-
168
- // Updated execution provider interface
169
- export abstract class ExecutionProvider {
170
- abstract setup(tool: EnactTool): Promise<boolean>;
171
- abstract execute(
172
- tool: EnactTool,
173
- inputs: Record<string, any>,
174
- environment: ExecutionEnvironment,
175
- ): Promise<ExecutionResult>;
176
- abstract cleanup(): Promise<boolean>;
177
- abstract resolveEnvironmentVariables(
178
- envConfig: Record<string, any>,
179
- namespace?: string,
180
- ): Promise<Record<string, any>>;
181
-
182
- // New method for command execution
183
- abstract executeCommand(
184
- command: string,
185
- inputs: Record<string, any>,
186
- environment: ExecutionEnvironment,
187
- timeout?: string,
188
- ): Promise<{ stdout: string; stderr: string; exitCode: number }>;
189
- }
5
+ // Placeholder for Phase 3 implementation
6
+ export type EnactManifest = Record<string, unknown>;
@@ -0,0 +1,281 @@
1
+ /**
2
+ * @enactprotocol/shared - File system helpers
3
+ *
4
+ * Provides utilities for common filesystem operations.
5
+ */
6
+
7
+ import {
8
+ copyFileSync,
9
+ existsSync,
10
+ mkdirSync,
11
+ readFileSync,
12
+ readdirSync,
13
+ rmSync,
14
+ statSync,
15
+ writeFileSync,
16
+ } from "node:fs";
17
+ import { dirname, join } from "node:path";
18
+
19
+ /**
20
+ * Ensure a directory exists, creating it if necessary
21
+ */
22
+ export function ensureDir(dirPath: string): void {
23
+ if (!existsSync(dirPath)) {
24
+ mkdirSync(dirPath, { recursive: true });
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Ensure the parent directory of a file exists
30
+ */
31
+ export function ensureParentDir(filePath: string): void {
32
+ const parentDir = dirname(filePath);
33
+ ensureDir(parentDir);
34
+ }
35
+
36
+ /**
37
+ * Check if a path exists
38
+ */
39
+ export function pathExists(path: string): boolean {
40
+ return existsSync(path);
41
+ }
42
+
43
+ /**
44
+ * Check if a path is a directory
45
+ */
46
+ export function isDirectory(path: string): boolean {
47
+ try {
48
+ return existsSync(path) && statSync(path).isDirectory();
49
+ } catch {
50
+ return false;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Check if a path is a file
56
+ */
57
+ export function isFile(path: string): boolean {
58
+ try {
59
+ return existsSync(path) && statSync(path).isFile();
60
+ } catch {
61
+ return false;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Read and parse a JSON file
67
+ * @throws Error if file doesn't exist or isn't valid JSON
68
+ */
69
+ export function readJsonFile<T = unknown>(filePath: string): T {
70
+ const content = readFileSync(filePath, "utf-8");
71
+ return JSON.parse(content) as T;
72
+ }
73
+
74
+ /**
75
+ * Try to read and parse a JSON file
76
+ * @returns The parsed JSON or null if file doesn't exist or is invalid
77
+ */
78
+ export function tryReadJsonFile<T = unknown>(filePath: string): T | null {
79
+ try {
80
+ return readJsonFile<T>(filePath);
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Write data to a JSON file with formatting
88
+ */
89
+ export function writeJsonFile(
90
+ filePath: string,
91
+ data: unknown,
92
+ options?: { indent?: number | undefined }
93
+ ): void {
94
+ const indent = options?.indent ?? 2;
95
+ ensureParentDir(filePath);
96
+ writeFileSync(filePath, `${JSON.stringify(data, null, indent)}\n`, "utf-8");
97
+ }
98
+
99
+ /**
100
+ * Read a text file
101
+ */
102
+ export function readTextFile(filePath: string): string {
103
+ return readFileSync(filePath, "utf-8");
104
+ }
105
+
106
+ /**
107
+ * Try to read a text file
108
+ * @returns The file content or null if file doesn't exist
109
+ */
110
+ export function tryReadTextFile(filePath: string): string | null {
111
+ try {
112
+ return readTextFile(filePath);
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Write content to a text file
120
+ */
121
+ export function writeTextFile(filePath: string, content: string): void {
122
+ ensureParentDir(filePath);
123
+ writeFileSync(filePath, content, "utf-8");
124
+ }
125
+
126
+ /**
127
+ * Copy a file
128
+ */
129
+ export function copyFile(src: string, dest: string): void {
130
+ ensureParentDir(dest);
131
+ copyFileSync(src, dest);
132
+ }
133
+
134
+ /**
135
+ * Copy a directory recursively
136
+ */
137
+ export function copyDir(src: string, dest: string): void {
138
+ ensureDir(dest);
139
+
140
+ const entries = readdirSync(src, { withFileTypes: true });
141
+
142
+ for (const entry of entries) {
143
+ const srcPath = join(src, entry.name);
144
+ const destPath = join(dest, entry.name);
145
+
146
+ if (entry.isDirectory()) {
147
+ copyDir(srcPath, destPath);
148
+ } else {
149
+ copyFile(srcPath, destPath);
150
+ }
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Remove a file or directory
156
+ */
157
+ export function remove(path: string): void {
158
+ if (existsSync(path)) {
159
+ rmSync(path, { recursive: true, force: true });
160
+ }
161
+ }
162
+
163
+ /**
164
+ * List directory contents
165
+ */
166
+ export function listDir(dirPath: string): string[] {
167
+ if (!existsSync(dirPath)) {
168
+ return [];
169
+ }
170
+ return readdirSync(dirPath);
171
+ }
172
+
173
+ /**
174
+ * List directory entries with types
175
+ */
176
+ export function listDirEntries(dirPath: string): Array<{
177
+ name: string;
178
+ type: "file" | "directory" | "unknown";
179
+ path: string;
180
+ }> {
181
+ if (!existsSync(dirPath)) {
182
+ return [];
183
+ }
184
+
185
+ const entries = readdirSync(dirPath, { withFileTypes: true });
186
+ return entries.map((entry) => ({
187
+ name: entry.name,
188
+ type: entry.isDirectory() ? "directory" : entry.isFile() ? "file" : "unknown",
189
+ path: join(dirPath, entry.name),
190
+ }));
191
+ }
192
+
193
+ /**
194
+ * Find files matching a pattern in a directory (non-recursive)
195
+ */
196
+ export function findFiles(dirPath: string, pattern: RegExp | string): string[] {
197
+ const entries = listDir(dirPath);
198
+ const regex = typeof pattern === "string" ? new RegExp(pattern) : pattern;
199
+
200
+ return entries
201
+ .filter((name) => regex.test(name) && isFile(join(dirPath, name)))
202
+ .map((name) => join(dirPath, name));
203
+ }
204
+
205
+ /**
206
+ * Find files recursively
207
+ */
208
+ export function findFilesRecursive(dirPath: string, pattern?: RegExp | string): string[] {
209
+ const results: string[] = [];
210
+
211
+ if (!existsSync(dirPath)) {
212
+ return results;
213
+ }
214
+
215
+ const regex =
216
+ pattern !== undefined ? (typeof pattern === "string" ? new RegExp(pattern) : pattern) : null;
217
+
218
+ function walk(dir: string) {
219
+ const entries = readdirSync(dir, { withFileTypes: true });
220
+
221
+ for (const entry of entries) {
222
+ const fullPath = join(dir, entry.name);
223
+
224
+ if (entry.isDirectory()) {
225
+ walk(fullPath);
226
+ } else if (entry.isFile()) {
227
+ if (!regex || regex.test(entry.name)) {
228
+ results.push(fullPath);
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ walk(dirPath);
235
+ return results;
236
+ }
237
+
238
+ /**
239
+ * Get file stats
240
+ */
241
+ export function getStats(path: string): {
242
+ size: number;
243
+ isFile: boolean;
244
+ isDirectory: boolean;
245
+ created: Date;
246
+ modified: Date;
247
+ } | null {
248
+ try {
249
+ const stats = statSync(path);
250
+ return {
251
+ size: stats.size,
252
+ isFile: stats.isFile(),
253
+ isDirectory: stats.isDirectory(),
254
+ created: stats.birthtime,
255
+ modified: stats.mtime,
256
+ };
257
+ } catch {
258
+ return null;
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Get file size in bytes
264
+ */
265
+ export function getFileSize(filePath: string): number | null {
266
+ const stats = getStats(filePath);
267
+ return stats?.isFile ? stats.size : null;
268
+ }
269
+
270
+ /**
271
+ * Touch a file (create if not exists, update mtime if exists)
272
+ */
273
+ export function touchFile(filePath: string): void {
274
+ ensureParentDir(filePath);
275
+ if (existsSync(filePath)) {
276
+ // Update access and modification time by rewriting the file
277
+ writeFileSync(filePath, readFileSync(filePath));
278
+ } else {
279
+ writeFileSync(filePath, "", "utf-8");
280
+ }
281
+ }