scene-capability-engine 3.3.13 → 3.3.15
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 +9 -3
- package/README.zh.md +9 -3
- package/bin/scene-capability-engine.js +8 -2
- package/docs/command-reference.md +9 -0
- package/lib/commands/scene.js +8 -3
- package/lib/commands/templates.js +93 -17
- package/lib/scene-runtime/moqui-extractor.js +1 -1
- package/lib/templates/cache-manager.js +3 -3
- package/lib/templates/frontmatter-generator.js +11 -1
- package/lib/templates/metadata-collector.js +48 -10
- package/lib/templates/path-utils.js +1 -1
- package/lib/templates/registry-parser.js +292 -13
- package/lib/templates/template-exporter.js +30 -10
- package/lib/templates/template-manager.js +62 -8
- package/lib/templates/template-validator.js +24 -1
- package/lib/workspace/multi/global-config.js +1 -1
- package/lib/workspace/multi/path-utils.js +3 -3
- package/lib/workspace/multi/workspace-registry.js +1 -1
- package/lib/workspace/multi/workspace-state-manager.js +64 -2
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const fs = require('fs-extra');
|
|
8
8
|
const path = require('path');
|
|
9
|
+
const semver = require('semver');
|
|
9
10
|
const { ValidationError } = require('./template-error');
|
|
10
11
|
|
|
11
12
|
class TemplateValidator {
|
|
@@ -14,7 +15,8 @@ class TemplateValidator {
|
|
|
14
15
|
this.requiredFrontmatterFields = [
|
|
15
16
|
'name', 'category', 'description', 'difficulty',
|
|
16
17
|
'tags', 'applicable_scenarios', 'author',
|
|
17
|
-
'created_at', 'updated_at', 'version'
|
|
18
|
+
'created_at', 'updated_at', 'version',
|
|
19
|
+
'template_type', 'min_sce_version'
|
|
18
20
|
];
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -251,6 +253,27 @@ class TemplateValidator {
|
|
|
251
253
|
result.errors.push(`${filename}: Invalid difficulty "${metadata.difficulty}"`);
|
|
252
254
|
}
|
|
253
255
|
|
|
256
|
+
// Validate template type
|
|
257
|
+
const validTemplateTypes = ['spec-scaffold', 'capability-template', 'runtime-playbook'];
|
|
258
|
+
if (metadata.template_type && !validTemplateTypes.includes(metadata.template_type)) {
|
|
259
|
+
result.errors.push(`${filename}: Invalid template_type "${metadata.template_type}"`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Validate SCE compatibility semver
|
|
263
|
+
if (metadata.min_sce_version && !semver.valid(metadata.min_sce_version)) {
|
|
264
|
+
result.errors.push(`${filename}: Invalid min_sce_version "${metadata.min_sce_version}"`);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (metadata.max_sce_version && !semver.valid(metadata.max_sce_version)) {
|
|
268
|
+
result.errors.push(`${filename}: Invalid max_sce_version "${metadata.max_sce_version}"`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (metadata.min_sce_version && metadata.max_sce_version &&
|
|
272
|
+
semver.valid(metadata.min_sce_version) && semver.valid(metadata.max_sce_version) &&
|
|
273
|
+
semver.gt(metadata.min_sce_version, metadata.max_sce_version)) {
|
|
274
|
+
result.errors.push(`${filename}: min_sce_version must be <= max_sce_version`);
|
|
275
|
+
}
|
|
276
|
+
|
|
254
277
|
return result;
|
|
255
278
|
}
|
|
256
279
|
|
|
@@ -26,7 +26,7 @@ class GlobalConfig {
|
|
|
26
26
|
/**
|
|
27
27
|
* Get the default configuration file path
|
|
28
28
|
*
|
|
29
|
-
* @returns {string} Path to ~/.
|
|
29
|
+
* @returns {string} Path to ~/.sce/workspace-state.json
|
|
30
30
|
* @deprecated Use WorkspaceStateManager.getDefaultStatePath() instead
|
|
31
31
|
*/
|
|
32
32
|
getDefaultConfigPath() {
|
|
@@ -84,16 +84,16 @@ class PathUtils {
|
|
|
84
84
|
/**
|
|
85
85
|
* Get the default sce configuration directory
|
|
86
86
|
*
|
|
87
|
-
* @returns {string} Path to ~/.
|
|
87
|
+
* @returns {string} Path to ~/.sce directory
|
|
88
88
|
*/
|
|
89
89
|
static getConfigDir() {
|
|
90
|
-
return path.join(os.homedir(), '.
|
|
90
|
+
return path.join(os.homedir(), '.sce');
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
94
|
* Get the default workspace state file path
|
|
95
95
|
*
|
|
96
|
-
* @returns {string} Path to ~/.
|
|
96
|
+
* @returns {string} Path to ~/.sce/workspace-state.json
|
|
97
97
|
*/
|
|
98
98
|
static getWorkspaceStatePath() {
|
|
99
99
|
return path.join(this.getConfigDir(), 'workspace-state.json');
|
|
@@ -26,7 +26,7 @@ class WorkspaceRegistry {
|
|
|
26
26
|
/**
|
|
27
27
|
* Get the default configuration file path
|
|
28
28
|
*
|
|
29
|
-
* @returns {string} Path to ~/.
|
|
29
|
+
* @returns {string} Path to ~/.sce/workspace-state.json
|
|
30
30
|
* @deprecated Use WorkspaceStateManager.getDefaultStatePath() instead
|
|
31
31
|
*/
|
|
32
32
|
getDefaultConfigPath() {
|
|
@@ -10,7 +10,7 @@ const Workspace = require('./workspace');
|
|
|
10
10
|
* data in a single configuration file. This ensures atomic updates and
|
|
11
11
|
* eliminates data inconsistency risks.
|
|
12
12
|
*
|
|
13
|
-
* Architecture: Single file (~/.
|
|
13
|
+
* Architecture: Single file (~/.sce/workspace-state.json) contains:
|
|
14
14
|
* - All workspace entries
|
|
15
15
|
* - Active workspace selection
|
|
16
16
|
* - User preferences
|
|
@@ -41,13 +41,34 @@ class WorkspaceStateManager {
|
|
|
41
41
|
/**
|
|
42
42
|
* Get the default state file path
|
|
43
43
|
*
|
|
44
|
-
* @returns {string} Path to ~/.
|
|
44
|
+
* @returns {string} Path to ~/.sce/workspace-state.json
|
|
45
45
|
*/
|
|
46
46
|
getDefaultStatePath() {
|
|
47
|
+
const homeDir = os.homedir();
|
|
48
|
+
return path.join(homeDir, '.sce', 'workspace-state.json');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the legacy state file path used by prior versions
|
|
53
|
+
*
|
|
54
|
+
* @returns {string} Path to ~/.kse/workspace-state.json
|
|
55
|
+
*/
|
|
56
|
+
getLegacyStatePath() {
|
|
47
57
|
const homeDir = os.homedir();
|
|
48
58
|
return path.join(homeDir, '.kse', 'workspace-state.json');
|
|
49
59
|
}
|
|
50
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Whether state manager is operating on the default state path.
|
|
63
|
+
*
|
|
64
|
+
* Automatic legacy migration should only run in this mode.
|
|
65
|
+
*
|
|
66
|
+
* @returns {boolean}
|
|
67
|
+
*/
|
|
68
|
+
isDefaultStatePath() {
|
|
69
|
+
return path.resolve(this.statePath) === path.resolve(this.getDefaultStatePath());
|
|
70
|
+
}
|
|
71
|
+
|
|
51
72
|
/**
|
|
52
73
|
* Load workspace state from disk
|
|
53
74
|
*
|
|
@@ -66,6 +87,15 @@ class WorkspaceStateManager {
|
|
|
66
87
|
return true;
|
|
67
88
|
}
|
|
68
89
|
|
|
90
|
+
// Migrate legacy single-file state from ~/.kse/workspace-state.json
|
|
91
|
+
if (await this.hasLegacyStateFile()) {
|
|
92
|
+
console.log('Migrating workspace state to new .sce directory...');
|
|
93
|
+
await this.migrateFromLegacyStateFile();
|
|
94
|
+
await this.loadNewFormat();
|
|
95
|
+
this.loaded = true;
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
69
99
|
// Check for legacy format and migrate
|
|
70
100
|
if (await this.hasLegacyFiles()) {
|
|
71
101
|
console.log('Migrating workspace configuration to new format...');
|
|
@@ -137,6 +167,10 @@ class WorkspaceStateManager {
|
|
|
137
167
|
* @returns {Promise<boolean>}
|
|
138
168
|
*/
|
|
139
169
|
async hasLegacyFiles() {
|
|
170
|
+
if (!this.isDefaultStatePath()) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
|
|
140
174
|
const homeDir = os.homedir();
|
|
141
175
|
const legacyWorkspacesPath = path.join(homeDir, '.kse', 'workspaces.json');
|
|
142
176
|
const legacyConfigPath = path.join(homeDir, '.kse', 'config.json');
|
|
@@ -147,6 +181,34 @@ class WorkspaceStateManager {
|
|
|
147
181
|
return workspacesExists || configExists;
|
|
148
182
|
}
|
|
149
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Check whether legacy single-file state exists
|
|
186
|
+
*
|
|
187
|
+
* @private
|
|
188
|
+
* @returns {Promise<boolean>}
|
|
189
|
+
*/
|
|
190
|
+
async hasLegacyStateFile() {
|
|
191
|
+
if (!this.isDefaultStatePath()) {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const legacyStatePath = this.getLegacyStatePath();
|
|
196
|
+
return fs.pathExists(legacyStatePath);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Copy legacy single-file state into the new default location.
|
|
201
|
+
*
|
|
202
|
+
* @private
|
|
203
|
+
* @returns {Promise<void>}
|
|
204
|
+
*/
|
|
205
|
+
async migrateFromLegacyStateFile() {
|
|
206
|
+
const legacyStatePath = this.getLegacyStatePath();
|
|
207
|
+
const stateDir = path.dirname(this.statePath);
|
|
208
|
+
await fs.ensureDir(stateDir);
|
|
209
|
+
await fs.copy(legacyStatePath, this.statePath);
|
|
210
|
+
}
|
|
211
|
+
|
|
150
212
|
/**
|
|
151
213
|
* Migrate from legacy format (workspaces.json + config.json)
|
|
152
214
|
*
|
package/package.json
CHANGED