@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.
- package/README.md +44 -0
- package/dist/config.d.ts +164 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +386 -0
- package/dist/config.js.map +1 -0
- package/dist/constants.d.ts +15 -5
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +24 -8
- package/dist/constants.js.map +1 -0
- package/dist/execution/command.d.ts +102 -0
- package/dist/execution/command.d.ts.map +1 -0
- package/dist/execution/command.js +262 -0
- package/dist/execution/command.js.map +1 -0
- package/dist/execution/index.d.ts +12 -0
- package/dist/execution/index.d.ts.map +1 -0
- package/dist/execution/index.js +17 -0
- package/dist/execution/index.js.map +1 -0
- package/dist/execution/runtime.d.ts +82 -0
- package/dist/execution/runtime.d.ts.map +1 -0
- package/dist/execution/runtime.js +273 -0
- package/dist/execution/runtime.js.map +1 -0
- package/dist/execution/types.d.ts +306 -0
- package/dist/execution/types.d.ts.map +1 -0
- package/dist/execution/types.js +14 -0
- package/dist/execution/types.js.map +1 -0
- package/dist/execution/validation.d.ts +43 -0
- package/dist/execution/validation.d.ts.map +1 -0
- package/dist/execution/validation.js +430 -0
- package/dist/execution/validation.js.map +1 -0
- package/dist/index.d.ts +21 -21
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -25
- package/dist/index.js.map +1 -0
- package/dist/manifest/index.d.ts +7 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +10 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/manifest/loader.d.ts +76 -0
- package/dist/manifest/loader.d.ts.map +1 -0
- package/dist/manifest/loader.js +146 -0
- package/dist/manifest/loader.js.map +1 -0
- package/dist/manifest/parser.d.ts +64 -0
- package/dist/manifest/parser.d.ts.map +1 -0
- package/dist/manifest/parser.js +135 -0
- package/dist/manifest/parser.js.map +1 -0
- package/dist/manifest/validator.d.ts +95 -0
- package/dist/manifest/validator.d.ts.map +1 -0
- package/dist/manifest/validator.js +258 -0
- package/dist/manifest/validator.js.map +1 -0
- package/dist/paths.d.ts +57 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +93 -0
- package/dist/paths.js.map +1 -0
- package/dist/registry.d.ts +73 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +147 -0
- package/dist/registry.js.map +1 -0
- package/dist/resolver.d.ts +89 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +282 -0
- package/dist/resolver.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/manifest.d.ts +201 -0
- package/dist/types/manifest.d.ts.map +1 -0
- package/dist/types/manifest.js +13 -0
- package/dist/types/manifest.js.map +1 -0
- package/dist/types.d.ts +5 -132
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -3
- package/dist/types.js.map +1 -0
- package/dist/utils/fs.d.ts +105 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +233 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/logger.d.ts +102 -25
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +214 -57
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/version.d.ts +60 -2
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +255 -31
- package/dist/utils/version.js.map +1 -0
- package/package.json +16 -58
- package/src/config.ts +510 -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 +238 -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/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/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/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/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/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/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/index.ts
CHANGED
|
@@ -1,39 +1,247 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @enactprotocol/shared
|
|
3
|
+
*
|
|
4
|
+
* Core business logic and utilities for Enact.
|
|
5
|
+
* Provides manifest parsing, configuration management, tool resolution,
|
|
6
|
+
* and execution engine interfaces.
|
|
7
|
+
*/
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
export const version = "0.1.0";
|
|
7
10
|
|
|
8
|
-
//
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
// Constants
|
|
12
|
+
export {
|
|
13
|
+
ENACT_BASE_URL,
|
|
14
|
+
ENACT_API_URL,
|
|
15
|
+
ENACT_WEB_URL,
|
|
16
|
+
ENACT_TOOL_TYPE,
|
|
17
|
+
ENACT_AUDIT_TYPE,
|
|
18
|
+
ENACT_BUILD_TYPE,
|
|
19
|
+
INTOTO_STATEMENT_TYPE,
|
|
20
|
+
SLSA_PROVENANCE_TYPE,
|
|
21
|
+
} from "./constants";
|
|
13
22
|
|
|
14
|
-
//
|
|
15
|
-
export {
|
|
16
|
-
|
|
23
|
+
// Path utilities
|
|
24
|
+
export {
|
|
25
|
+
getEnactHome,
|
|
26
|
+
getProjectEnactDir,
|
|
27
|
+
getToolsDir,
|
|
28
|
+
getCacheDir,
|
|
29
|
+
getConfigPath,
|
|
30
|
+
getGlobalEnvPath,
|
|
31
|
+
getProjectEnvPath,
|
|
32
|
+
type ToolScope,
|
|
33
|
+
} from "./paths";
|
|
17
34
|
|
|
18
|
-
//
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
// Configuration manager
|
|
36
|
+
export {
|
|
37
|
+
loadConfig,
|
|
38
|
+
saveConfig,
|
|
39
|
+
getConfigValue,
|
|
40
|
+
setConfigValue,
|
|
41
|
+
resetConfig,
|
|
42
|
+
configExists,
|
|
43
|
+
ensureGlobalSetup,
|
|
44
|
+
DEFAULT_CONFIG,
|
|
45
|
+
// Local trust management (new unified API)
|
|
46
|
+
getTrustedIdentities,
|
|
47
|
+
addTrustedIdentity,
|
|
48
|
+
removeTrustedIdentity,
|
|
49
|
+
isIdentityTrusted,
|
|
50
|
+
getMinimumAttestations,
|
|
51
|
+
getTrustPolicy,
|
|
52
|
+
emailToProviderIdentity,
|
|
53
|
+
// Legacy aliases (deprecated)
|
|
54
|
+
getTrustedAuditors,
|
|
55
|
+
addTrustedAuditor,
|
|
56
|
+
removeTrustedAuditor,
|
|
57
|
+
isAuditorTrusted,
|
|
58
|
+
type EnactConfig,
|
|
59
|
+
type TrustConfig,
|
|
60
|
+
type CacheConfig,
|
|
61
|
+
type ExecutionConfig,
|
|
62
|
+
type RegistryConfig,
|
|
63
|
+
} from "./config";
|
|
26
64
|
|
|
65
|
+
// Manifest types
|
|
66
|
+
export type {
|
|
67
|
+
ToolManifest,
|
|
68
|
+
PackageManifest,
|
|
69
|
+
ParsedManifest,
|
|
70
|
+
EnvVariable,
|
|
71
|
+
EnvVariables,
|
|
72
|
+
Author,
|
|
73
|
+
ToolAnnotations,
|
|
74
|
+
ResourceRequirements,
|
|
75
|
+
ToolExample,
|
|
76
|
+
ValidationResult,
|
|
77
|
+
ValidationError,
|
|
78
|
+
ValidationWarning,
|
|
79
|
+
ToolLocation,
|
|
80
|
+
ToolResolution,
|
|
81
|
+
ManifestFileName,
|
|
82
|
+
} from "./types/manifest";
|
|
27
83
|
|
|
28
|
-
|
|
29
|
-
export * from './services/McpCoreService';
|
|
84
|
+
export { MANIFEST_FILES, PACKAGE_MANIFEST_FILE } from "./types/manifest";
|
|
30
85
|
|
|
31
|
-
//
|
|
32
|
-
export
|
|
86
|
+
// Manifest parsing, validation, and loading
|
|
87
|
+
export {
|
|
88
|
+
// Parser
|
|
89
|
+
ManifestParseError,
|
|
90
|
+
parseManifest,
|
|
91
|
+
parseManifestAuto,
|
|
92
|
+
parseYaml,
|
|
93
|
+
extractFrontmatter,
|
|
94
|
+
detectFormat,
|
|
95
|
+
type ManifestFormat,
|
|
96
|
+
// Validator
|
|
97
|
+
validateManifest,
|
|
98
|
+
validateManifestStrict,
|
|
99
|
+
isValidToolName,
|
|
100
|
+
isValidVersion,
|
|
101
|
+
isValidTimeout,
|
|
102
|
+
ToolManifestSchema,
|
|
103
|
+
// Loader
|
|
104
|
+
ManifestLoadError,
|
|
105
|
+
loadManifest,
|
|
106
|
+
loadManifestFromDir,
|
|
107
|
+
findManifestFile,
|
|
108
|
+
hasManifest,
|
|
109
|
+
tryLoadManifest,
|
|
110
|
+
tryLoadManifestFromDir,
|
|
111
|
+
type LoadedManifest,
|
|
112
|
+
} from "./manifest";
|
|
33
113
|
|
|
34
|
-
//
|
|
35
|
-
export
|
|
36
|
-
|
|
114
|
+
// Tool resolver
|
|
115
|
+
export {
|
|
116
|
+
ToolResolveError,
|
|
117
|
+
resolveTool,
|
|
118
|
+
resolveToolAuto,
|
|
119
|
+
resolveToolFromPath,
|
|
120
|
+
tryResolveTool,
|
|
121
|
+
normalizeToolName,
|
|
122
|
+
toolNameToPath,
|
|
123
|
+
getToolPath,
|
|
124
|
+
getToolSearchPaths,
|
|
125
|
+
type ResolveOptions,
|
|
126
|
+
} from "./resolver";
|
|
37
127
|
|
|
38
|
-
//
|
|
39
|
-
export
|
|
128
|
+
// Local tool registry (tools.json management)
|
|
129
|
+
export {
|
|
130
|
+
loadToolsRegistry,
|
|
131
|
+
saveToolsRegistry,
|
|
132
|
+
addToolToRegistry,
|
|
133
|
+
removeToolFromRegistry,
|
|
134
|
+
isToolInstalled,
|
|
135
|
+
getInstalledVersion,
|
|
136
|
+
getToolCachePath,
|
|
137
|
+
listInstalledTools,
|
|
138
|
+
getInstalledToolInfo,
|
|
139
|
+
getToolsJsonPath,
|
|
140
|
+
type ToolsRegistry,
|
|
141
|
+
type RegistryScope,
|
|
142
|
+
type InstalledToolInfo,
|
|
143
|
+
} from "./registry";
|
|
144
|
+
|
|
145
|
+
// Logger utility
|
|
146
|
+
export {
|
|
147
|
+
Logger,
|
|
148
|
+
createLogger,
|
|
149
|
+
configureLogger,
|
|
150
|
+
getLogger,
|
|
151
|
+
debug,
|
|
152
|
+
info,
|
|
153
|
+
warn,
|
|
154
|
+
error,
|
|
155
|
+
type LogLevel,
|
|
156
|
+
type LogEntry,
|
|
157
|
+
type LoggerOptions,
|
|
158
|
+
} from "./utils/logger";
|
|
159
|
+
|
|
160
|
+
// Version utilities
|
|
161
|
+
export {
|
|
162
|
+
parseVersion,
|
|
163
|
+
isValidVersion as isValidSemver,
|
|
164
|
+
compareVersions,
|
|
165
|
+
parseRange,
|
|
166
|
+
satisfiesRange,
|
|
167
|
+
sortVersions,
|
|
168
|
+
getHighestVersion,
|
|
169
|
+
incrementVersion,
|
|
170
|
+
coerceVersion,
|
|
171
|
+
formatVersion,
|
|
172
|
+
type ParsedVersion,
|
|
173
|
+
type VersionRange,
|
|
174
|
+
} from "./utils/version";
|
|
175
|
+
|
|
176
|
+
// File system helpers
|
|
177
|
+
export {
|
|
178
|
+
ensureDir,
|
|
179
|
+
ensureParentDir,
|
|
180
|
+
pathExists,
|
|
181
|
+
isDirectory,
|
|
182
|
+
isFile,
|
|
183
|
+
readJsonFile,
|
|
184
|
+
tryReadJsonFile,
|
|
185
|
+
writeJsonFile,
|
|
186
|
+
readTextFile,
|
|
187
|
+
tryReadTextFile,
|
|
188
|
+
writeTextFile,
|
|
189
|
+
copyFile,
|
|
190
|
+
copyDir,
|
|
191
|
+
remove,
|
|
192
|
+
listDir,
|
|
193
|
+
listDirEntries,
|
|
194
|
+
findFiles,
|
|
195
|
+
findFilesRecursive,
|
|
196
|
+
getStats,
|
|
197
|
+
getFileSize,
|
|
198
|
+
touchFile,
|
|
199
|
+
} from "./utils/fs";
|
|
200
|
+
|
|
201
|
+
// Execution engine (browser-safe utilities only)
|
|
202
|
+
// NOTE: DaggerExecutionProvider moved to @enactprotocol/execution package
|
|
203
|
+
export {
|
|
204
|
+
// Types
|
|
205
|
+
type ExecutionInput,
|
|
206
|
+
type FileInput,
|
|
207
|
+
type ExecutionOutput,
|
|
208
|
+
type ExecutionResult,
|
|
209
|
+
type ExecutionMetadata,
|
|
210
|
+
type ExecutionError,
|
|
211
|
+
type ExecutionErrorCode,
|
|
212
|
+
type ExecutionOptions,
|
|
213
|
+
type RetryConfig,
|
|
214
|
+
type ContainerRuntime,
|
|
215
|
+
type RuntimeDetection,
|
|
216
|
+
type RuntimeStatus,
|
|
217
|
+
type EngineHealth,
|
|
218
|
+
type EngineState,
|
|
219
|
+
type ExecutionProvider,
|
|
220
|
+
type ParsedCommand,
|
|
221
|
+
type CommandToken,
|
|
222
|
+
type InterpolationOptions,
|
|
223
|
+
type InputValidationResult,
|
|
224
|
+
type InputValidationError,
|
|
225
|
+
type DryRunResult,
|
|
226
|
+
// Constants
|
|
227
|
+
DEFAULT_RETRY_CONFIG,
|
|
228
|
+
// Runtime
|
|
229
|
+
detectRuntime,
|
|
230
|
+
clearRuntimeCache,
|
|
231
|
+
isRuntimeAvailable,
|
|
232
|
+
getAvailableRuntimes,
|
|
233
|
+
RuntimeStatusTracker,
|
|
234
|
+
createRuntimeTracker,
|
|
235
|
+
// Command
|
|
236
|
+
parseCommand,
|
|
237
|
+
interpolateCommand,
|
|
238
|
+
shellEscape,
|
|
239
|
+
parseCommandArgs,
|
|
240
|
+
prepareCommand,
|
|
241
|
+
getMissingParams,
|
|
242
|
+
// Validation
|
|
243
|
+
validateInputs,
|
|
244
|
+
applyDefaults,
|
|
245
|
+
getRequiredParams,
|
|
246
|
+
getParamInfo,
|
|
247
|
+
} from "./execution";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest module exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Parser
|
|
6
|
+
export {
|
|
7
|
+
ManifestParseError,
|
|
8
|
+
parseManifest,
|
|
9
|
+
parseManifestAuto,
|
|
10
|
+
parseYaml,
|
|
11
|
+
extractFrontmatter,
|
|
12
|
+
detectFormat,
|
|
13
|
+
type ManifestFormat,
|
|
14
|
+
} from "./parser";
|
|
15
|
+
|
|
16
|
+
// Validator
|
|
17
|
+
export {
|
|
18
|
+
validateManifest,
|
|
19
|
+
validateManifestStrict,
|
|
20
|
+
isValidToolName,
|
|
21
|
+
isValidVersion,
|
|
22
|
+
isValidTimeout,
|
|
23
|
+
ToolManifestSchema,
|
|
24
|
+
} from "./validator";
|
|
25
|
+
|
|
26
|
+
// Loader
|
|
27
|
+
export {
|
|
28
|
+
ManifestLoadError,
|
|
29
|
+
loadManifest,
|
|
30
|
+
loadManifestFromDir,
|
|
31
|
+
findManifestFile,
|
|
32
|
+
hasManifest,
|
|
33
|
+
tryLoadManifest,
|
|
34
|
+
tryLoadManifestFromDir,
|
|
35
|
+
type LoadedManifest,
|
|
36
|
+
} from "./loader";
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manifest loader - combines parsing and validation
|
|
3
|
+
*
|
|
4
|
+
* Provides high-level functions to load tool manifests from files
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
8
|
+
import { basename, join } from "node:path";
|
|
9
|
+
import type { ParsedManifest, ToolManifest, ValidationResult } from "../types/manifest";
|
|
10
|
+
import { MANIFEST_FILES } from "../types/manifest";
|
|
11
|
+
import { ManifestParseError, parseManifestAuto } from "./parser";
|
|
12
|
+
import { validateManifest } from "./validator";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Error thrown when loading a manifest fails
|
|
16
|
+
*/
|
|
17
|
+
export class ManifestLoadError extends Error {
|
|
18
|
+
constructor(
|
|
19
|
+
message: string,
|
|
20
|
+
public readonly filePath: string,
|
|
21
|
+
public readonly originalError?: Error
|
|
22
|
+
) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "ManifestLoadError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Result of loading a manifest
|
|
30
|
+
*/
|
|
31
|
+
export interface LoadedManifest {
|
|
32
|
+
/** The validated manifest */
|
|
33
|
+
manifest: ToolManifest;
|
|
34
|
+
/** The markdown body (if from .md file) */
|
|
35
|
+
body?: string;
|
|
36
|
+
/** The format the manifest was loaded from */
|
|
37
|
+
format: "yaml" | "md";
|
|
38
|
+
/** The file path the manifest was loaded from */
|
|
39
|
+
filePath: string;
|
|
40
|
+
/** Validation warnings (if any) */
|
|
41
|
+
warnings?: ValidationResult["warnings"];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Load a manifest from a file path
|
|
46
|
+
*
|
|
47
|
+
* @param filePath - Path to the manifest file (enact.yaml, enact.yml, or enact.md)
|
|
48
|
+
* @returns LoadedManifest with validated manifest and metadata
|
|
49
|
+
* @throws ManifestLoadError if file doesn't exist, parse fails, or validation fails
|
|
50
|
+
*/
|
|
51
|
+
export function loadManifest(filePath: string): LoadedManifest {
|
|
52
|
+
// Check file exists
|
|
53
|
+
if (!existsSync(filePath)) {
|
|
54
|
+
throw new ManifestLoadError(`Manifest file not found: ${filePath}`, filePath);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Read file content
|
|
58
|
+
let content: string;
|
|
59
|
+
try {
|
|
60
|
+
content = readFileSync(filePath, "utf-8");
|
|
61
|
+
} catch (error) {
|
|
62
|
+
throw new ManifestLoadError(
|
|
63
|
+
`Failed to read manifest file: ${(error as Error).message}`,
|
|
64
|
+
filePath,
|
|
65
|
+
error as Error
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Parse the manifest
|
|
70
|
+
let parsed: ParsedManifest;
|
|
71
|
+
try {
|
|
72
|
+
parsed = parseManifestAuto(content, basename(filePath));
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof ManifestParseError) {
|
|
75
|
+
throw new ManifestLoadError(`Failed to parse manifest: ${error.message}`, filePath, error);
|
|
76
|
+
}
|
|
77
|
+
throw new ManifestLoadError(
|
|
78
|
+
`Failed to parse manifest: ${(error as Error).message}`,
|
|
79
|
+
filePath,
|
|
80
|
+
error as Error
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Validate the manifest
|
|
85
|
+
const validation = validateManifest(parsed.manifest);
|
|
86
|
+
|
|
87
|
+
if (!validation.valid) {
|
|
88
|
+
const errorMessages =
|
|
89
|
+
validation.errors?.map((e) => ` - ${e.path}: ${e.message}`).join("\n") ?? "";
|
|
90
|
+
throw new ManifestLoadError(`Manifest validation failed:\n${errorMessages}`, filePath);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Build result
|
|
94
|
+
const result: LoadedManifest = {
|
|
95
|
+
manifest: parsed.manifest,
|
|
96
|
+
format: parsed.format,
|
|
97
|
+
filePath,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
if (parsed.body) {
|
|
101
|
+
result.body = parsed.body;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (validation.warnings && validation.warnings.length > 0) {
|
|
105
|
+
result.warnings = validation.warnings;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Find and load a manifest from a directory
|
|
113
|
+
*
|
|
114
|
+
* Searches for enact.md, enact.yaml, or enact.yml in the given directory
|
|
115
|
+
*
|
|
116
|
+
* @param dir - Directory to search for manifest
|
|
117
|
+
* @returns LoadedManifest if found
|
|
118
|
+
* @throws ManifestLoadError if no manifest found or loading fails
|
|
119
|
+
*/
|
|
120
|
+
export function loadManifestFromDir(dir: string): LoadedManifest {
|
|
121
|
+
// Try each manifest filename in order of preference
|
|
122
|
+
for (const filename of MANIFEST_FILES) {
|
|
123
|
+
const filePath = join(dir, filename);
|
|
124
|
+
if (existsSync(filePath)) {
|
|
125
|
+
return loadManifest(filePath);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
throw new ManifestLoadError(
|
|
130
|
+
`No manifest found in directory: ${dir}. Expected one of: ${MANIFEST_FILES.join(", ")}`,
|
|
131
|
+
dir
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Find a manifest file in a directory without loading it
|
|
137
|
+
*
|
|
138
|
+
* @param dir - Directory to search
|
|
139
|
+
* @returns Path to manifest file or null if not found
|
|
140
|
+
*/
|
|
141
|
+
export function findManifestFile(dir: string): string | null {
|
|
142
|
+
for (const filename of MANIFEST_FILES) {
|
|
143
|
+
const filePath = join(dir, filename);
|
|
144
|
+
if (existsSync(filePath)) {
|
|
145
|
+
return filePath;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Check if a directory contains a manifest file
|
|
153
|
+
*
|
|
154
|
+
* @param dir - Directory to check
|
|
155
|
+
* @returns true if a manifest file exists
|
|
156
|
+
*/
|
|
157
|
+
export function hasManifest(dir: string): boolean {
|
|
158
|
+
return findManifestFile(dir) !== null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Try to load a manifest, returning null instead of throwing
|
|
163
|
+
*
|
|
164
|
+
* @param filePath - Path to the manifest file
|
|
165
|
+
* @returns LoadedManifest or null if loading fails
|
|
166
|
+
*/
|
|
167
|
+
export function tryLoadManifest(filePath: string): LoadedManifest | null {
|
|
168
|
+
try {
|
|
169
|
+
return loadManifest(filePath);
|
|
170
|
+
} catch {
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Try to load a manifest from a directory, returning null instead of throwing
|
|
177
|
+
*
|
|
178
|
+
* @param dir - Directory to search
|
|
179
|
+
* @returns LoadedManifest or null if no manifest found or loading fails
|
|
180
|
+
*/
|
|
181
|
+
export function tryLoadManifestFromDir(dir: string): LoadedManifest | null {
|
|
182
|
+
try {
|
|
183
|
+
return loadManifestFromDir(dir);
|
|
184
|
+
} catch {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YAML and Markdown parser for Enact tool manifests
|
|
3
|
+
*
|
|
4
|
+
* Handles parsing of:
|
|
5
|
+
* - enact.yaml files (pure YAML)
|
|
6
|
+
* - enact.md files (YAML frontmatter + Markdown body)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import yaml from "js-yaml";
|
|
10
|
+
import type { ParsedManifest, ToolManifest } from "../types/manifest";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown when parsing fails
|
|
14
|
+
*/
|
|
15
|
+
export class ManifestParseError extends Error {
|
|
16
|
+
public readonly originalError: Error | undefined;
|
|
17
|
+
|
|
18
|
+
constructor(message: string, originalError?: Error) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = "ManifestParseError";
|
|
21
|
+
this.originalError = originalError;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Regex to match YAML frontmatter in Markdown files
|
|
27
|
+
* Matches content between --- delimiters at the start of the file
|
|
28
|
+
*/
|
|
29
|
+
const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse format type
|
|
33
|
+
*/
|
|
34
|
+
export type ManifestFormat = "yaml" | "md";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Extract YAML frontmatter from Markdown content
|
|
38
|
+
*
|
|
39
|
+
* @param content - The full Markdown file content
|
|
40
|
+
* @returns Object with frontmatter YAML and body Markdown, or null if no frontmatter
|
|
41
|
+
*/
|
|
42
|
+
export function extractFrontmatter(content: string): {
|
|
43
|
+
frontmatter: string;
|
|
44
|
+
body: string;
|
|
45
|
+
} | null {
|
|
46
|
+
const match = content.match(FRONTMATTER_REGEX);
|
|
47
|
+
|
|
48
|
+
if (!match) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const frontmatter = match[1];
|
|
53
|
+
const body = match[2];
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
frontmatter: frontmatter ? frontmatter.trim() : "",
|
|
57
|
+
body: body ? body.trim() : "",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Parse YAML content into a ToolManifest object
|
|
63
|
+
*
|
|
64
|
+
* @param yamlContent - Raw YAML string
|
|
65
|
+
* @returns Parsed object (not yet validated)
|
|
66
|
+
* @throws ManifestParseError if YAML parsing fails
|
|
67
|
+
*/
|
|
68
|
+
export function parseYaml(yamlContent: string): Record<string, unknown> {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = yaml.load(yamlContent);
|
|
71
|
+
|
|
72
|
+
if (parsed === null || parsed === undefined) {
|
|
73
|
+
throw new ManifestParseError("YAML content is empty or null");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
77
|
+
throw new ManifestParseError("YAML content must be an object, not an array or primitive");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return parsed as Record<string, unknown>;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error instanceof ManifestParseError) {
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const yamlError = error as Error;
|
|
87
|
+
throw new ManifestParseError(`Failed to parse YAML: ${yamlError.message}`, yamlError);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse a manifest from content string
|
|
93
|
+
*
|
|
94
|
+
* @param content - The file content (YAML or Markdown with frontmatter)
|
|
95
|
+
* @param format - The format of the content ('yaml' or 'md')
|
|
96
|
+
* @returns ParsedManifest with manifest object and optional body
|
|
97
|
+
* @throws ManifestParseError if parsing fails
|
|
98
|
+
*/
|
|
99
|
+
export function parseManifest(content: string, format: ManifestFormat): ParsedManifest {
|
|
100
|
+
if (!content || content.trim() === "") {
|
|
101
|
+
throw new ManifestParseError("Manifest content is empty");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (format === "yaml") {
|
|
105
|
+
const parsed = parseYaml(content);
|
|
106
|
+
return {
|
|
107
|
+
manifest: parsed as unknown as ToolManifest,
|
|
108
|
+
format: "yaml",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Handle Markdown format
|
|
113
|
+
const extracted = extractFrontmatter(content);
|
|
114
|
+
|
|
115
|
+
if (!extracted) {
|
|
116
|
+
throw new ManifestParseError(
|
|
117
|
+
"Markdown file must contain YAML frontmatter between --- delimiters"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!extracted.frontmatter) {
|
|
122
|
+
throw new ManifestParseError("YAML frontmatter is empty");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const parsed = parseYaml(extracted.frontmatter);
|
|
126
|
+
|
|
127
|
+
const result: ParsedManifest = {
|
|
128
|
+
manifest: parsed as unknown as ToolManifest,
|
|
129
|
+
format: "md",
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (extracted.body) {
|
|
133
|
+
result.body = extracted.body;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Detect manifest format from filename
|
|
141
|
+
*
|
|
142
|
+
* @param filename - The manifest filename
|
|
143
|
+
* @returns The detected format
|
|
144
|
+
* @throws ManifestParseError if format cannot be detected
|
|
145
|
+
*/
|
|
146
|
+
export function detectFormat(filename: string): ManifestFormat {
|
|
147
|
+
const lower = filename.toLowerCase();
|
|
148
|
+
|
|
149
|
+
if (lower.endsWith(".yaml") || lower.endsWith(".yml")) {
|
|
150
|
+
return "yaml";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (lower.endsWith(".md")) {
|
|
154
|
+
return "md";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
throw new ManifestParseError(
|
|
158
|
+
`Cannot detect manifest format from filename: ${filename}. Expected .yaml, .yml, or .md extension.`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Parse manifest content with automatic format detection
|
|
164
|
+
*
|
|
165
|
+
* @param content - The file content
|
|
166
|
+
* @param filename - The filename (for format detection)
|
|
167
|
+
* @returns ParsedManifest
|
|
168
|
+
* @throws ManifestParseError if parsing fails
|
|
169
|
+
*/
|
|
170
|
+
export function parseManifestAuto(content: string, filename: string): ParsedManifest {
|
|
171
|
+
const format = detectFormat(filename);
|
|
172
|
+
return parseManifest(content, format);
|
|
173
|
+
}
|