@specverse/engines 4.3.5 → 5.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/assets/examples/10-api/README.md +3 -3
- package/assets/prompts/core/README.md +1 -1
- package/dist/inference/core/rule-engine.d.ts +0 -12
- package/dist/inference/core/rule-engine.d.ts.map +1 -1
- package/dist/inference/core/rule-engine.js +99 -968
- package/dist/inference/core/rule-engine.js.map +1 -1
- package/dist/inference/core/template-helpers.d.ts +56 -0
- package/dist/inference/core/template-helpers.d.ts.map +1 -0
- package/dist/inference/core/template-helpers.js +87 -0
- package/dist/inference/core/template-helpers.js.map +1 -0
- package/dist/inference/logical/generators/service-generator.d.ts.map +1 -1
- package/dist/inference/logical/generators/service-generator.js +0 -4
- package/dist/inference/logical/generators/service-generator.js.map +1 -1
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.d.ts +9 -7
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.d.ts.map +1 -1
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.js +27 -9
- package/dist/inference/ui-contracts/rules/lifecycle-state-visible-in-detail.js.map +1 -1
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +27 -5
- package/dist/libs/instance-factories/tools/README.md +1 -1
- package/dist/libs/instance-factories/tools/mcp.yaml +1 -1
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +342 -116
- package/dist/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.js +172 -8
- package/dist/libs/instance-factories/tools/vscode.yaml +1 -1
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +27 -5
- package/libs/instance-factories/tools/README.md +1 -1
- package/libs/instance-factories/tools/mcp.yaml +1 -1
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +392 -141
- package/libs/instance-factories/tools/templates/vscode/static/extension.ts +9 -2
- package/libs/instance-factories/tools/templates/vscode/vscode-extension-generator.ts +246 -10
- package/libs/instance-factories/tools/vscode.yaml +1 -1
- package/package.json +5 -4
- package/libs/instance-factories/tools/templates/mcp/static/docs/DEPLOYMENT_GUIDE.md +0 -630
- package/libs/instance-factories/tools/templates/mcp/static/docs/HYBRID_RESOURCE_SYSTEM.md +0 -330
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/EXTENSION_DEPLOYMENT.md +0 -552
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/LOCAL_DEPLOYMENT.md +0 -164
- package/libs/instance-factories/tools/templates/mcp/static/docs/deployments/WEB_DEPLOYMENT.md +0 -247
- package/libs/instance-factories/tools/templates/mcp/static/package.json +0 -94
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-enterprise.js +0 -284
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-extension.js +0 -139
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-local.js +0 -74
- package/libs/instance-factories/tools/templates/mcp/static/scripts/build-web.js +0 -156
- package/libs/instance-factories/tools/templates/mcp/static/scripts/copy-canonical-files.js +0 -41
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-deployments.js +0 -259
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-resources.js +0 -231
- package/libs/instance-factories/tools/templates/mcp/static/scripts/test-hybrid-simple.js +0 -196
- package/libs/instance-factories/tools/templates/mcp/static/src/controllers/MCPServerController.ts +0 -293
- package/libs/instance-factories/tools/templates/mcp/static/src/events/EventEmitter.ts +0 -90
- package/libs/instance-factories/tools/templates/mcp/static/src/index.ts +0 -24
- package/libs/instance-factories/tools/templates/mcp/static/src/interfaces/ResourceProvider.ts +0 -15
- package/libs/instance-factories/tools/templates/mcp/static/src/models/LibrarySuggestion.ts +0 -106
- package/libs/instance-factories/tools/templates/mcp/static/src/models/SpecVerseResource.ts +0 -75
- package/libs/instance-factories/tools/templates/mcp/static/src/server/mcp-server.ts +0 -239
- package/libs/instance-factories/tools/templates/mcp/static/src/services/CLIProxyService.ts +0 -1501
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EmbeddedResourcesAdapter.ts +0 -211
- package/libs/instance-factories/tools/templates/mcp/static/src/services/EntityModuleService.ts +0 -308
- package/libs/instance-factories/tools/templates/mcp/static/src/services/HybridResourcesProvider.ts +0 -210
- package/libs/instance-factories/tools/templates/mcp/static/src/services/LibraryToolsService.ts +0 -356
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorBridge.ts +0 -522
- package/libs/instance-factories/tools/templates/mcp/static/src/services/OrchestratorToolsService.ts +0 -530
- package/libs/instance-factories/tools/templates/mcp/static/src/services/PromptToolsService.ts +0 -594
- package/libs/instance-factories/tools/templates/mcp/static/src/services/ResourcesProviderService.ts +0 -170
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.init.test.ts +0 -544
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/CLIProxyService.test.ts +0 -189
- package/libs/instance-factories/tools/templates/mcp/static/src/tests/unit/ResourcesProviderService.test.ts +0 -89
- package/libs/instance-factories/tools/templates/mcp/static/src/types/index.ts +0 -110
- package/libs/instance-factories/tools/templates/mcp/static/tsconfig.json +0 -28
- package/libs/instance-factories/tools/templates/vscode/static/schemas/specverse-v3-schema.json +0 -4279
- /package/libs/instance-factories/tools/templates/vscode/static/themes/{specverse-complete-theme.json → specverse-dark-theme.json} +0 -0
|
@@ -1,22 +1,63 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync, copyFileSync } from "fs";
|
|
1
|
+
import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync, copyFileSync, unlinkSync } from "fs";
|
|
2
2
|
import { join, dirname } from "path";
|
|
3
3
|
import { fileURLToPath } from "url";
|
|
4
|
+
import { createRequire } from "module";
|
|
4
5
|
const __generatorDir = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const __require = createRequire(import.meta.url);
|
|
7
|
+
function resolveComposedSchemaPath() {
|
|
8
|
+
try {
|
|
9
|
+
const entitiesPkg = __require.resolve("@specverse/entities/package.json");
|
|
10
|
+
const schemaPath = join(dirname(entitiesPkg), "schema", "SPECVERSE-SCHEMA.json");
|
|
11
|
+
if (existsSync(schemaPath)) return schemaPath;
|
|
12
|
+
} catch {
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
5
16
|
function generateVSCodeExtension(context) {
|
|
6
17
|
const { spec, outputDir } = context;
|
|
7
18
|
const extensionDir = join(outputDir || ".", "tools", "vscode-extension");
|
|
8
19
|
if (!existsSync(extensionDir)) mkdirSync(extensionDir, { recursive: true });
|
|
9
20
|
const distribution = extractDistribution(spec);
|
|
10
21
|
let cliCommands = [];
|
|
22
|
+
const submenuDefs = [];
|
|
11
23
|
if (distribution?.commands) {
|
|
12
|
-
|
|
24
|
+
const specCommandsByName = buildCLICommandMap(spec);
|
|
25
|
+
const standardByName = new Map(
|
|
26
|
+
getStandardCommands().map((c) => [c.command, c])
|
|
27
|
+
);
|
|
28
|
+
cliCommands = distribution.commands.flatMap((cmd) => {
|
|
13
29
|
const parts = (cmd.from || cmd.command || "").split(".");
|
|
14
30
|
const name = parts[parts.length - 1] || "unknown";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
const specNode = findSpecCommand(spec, cmd.from || name);
|
|
32
|
+
const subs = specNode?.subcommands;
|
|
33
|
+
if (subs && Object.keys(subs).length > 0) {
|
|
34
|
+
const submenuId = `specverse.${name}`;
|
|
35
|
+
const submenuLabel = cmd.title || specNode?.description || capitalize(name);
|
|
36
|
+
submenuDefs.push({ id: submenuId, label: capitalize(name) });
|
|
37
|
+
return Object.entries(subs).map(([childName, childDef]) => ({
|
|
38
|
+
command: `specverse.${name}.${childName}`,
|
|
39
|
+
title: `${capitalize(name)} ${capitalize(childName)}`,
|
|
40
|
+
category: "SpecVerse",
|
|
41
|
+
submenu: submenuId,
|
|
42
|
+
submenuLabel
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
const commandId = `specverse.${name}`;
|
|
46
|
+
let title = cmd.title;
|
|
47
|
+
if (!title && cmd.from) {
|
|
48
|
+
const specCmd = specCommandsByName.get(cmd.from);
|
|
49
|
+
if (specCmd?.description) title = specCmd.description;
|
|
50
|
+
}
|
|
51
|
+
if (!title) {
|
|
52
|
+
const std = standardByName.get(commandId);
|
|
53
|
+
if (std) title = std.title;
|
|
54
|
+
}
|
|
55
|
+
if (!title) title = capitalize(name);
|
|
56
|
+
return [{
|
|
57
|
+
command: commandId,
|
|
58
|
+
title,
|
|
18
59
|
category: "SpecVerse"
|
|
19
|
-
};
|
|
60
|
+
}];
|
|
20
61
|
});
|
|
21
62
|
}
|
|
22
63
|
if (cliCommands.length === 0) {
|
|
@@ -44,6 +85,56 @@ function generateVSCodeExtension(context) {
|
|
|
44
85
|
scopeName: lang.grammar,
|
|
45
86
|
path: `./syntaxes/${lang.id}.tmLanguage.json`
|
|
46
87
|
}));
|
|
88
|
+
packageJson.activationEvents = [];
|
|
89
|
+
const fileMatch = distribution.languages.flatMap((lang) => (lang.extensions || []).map((ext) => `*${ext}`));
|
|
90
|
+
if (fileMatch.length > 0) {
|
|
91
|
+
packageJson.contributes.jsonValidation = [{
|
|
92
|
+
fileMatch,
|
|
93
|
+
url: "./schemas/specverse-schema.json"
|
|
94
|
+
}];
|
|
95
|
+
}
|
|
96
|
+
const extnames = distribution.languages.flatMap((lang) => lang.extensions || []);
|
|
97
|
+
const langIds = distribution.languages.map((lang) => lang.id);
|
|
98
|
+
const explorerWhen = extnames.map((e) => `resourceExtname == ${e}`).join(" || ");
|
|
99
|
+
const editorWhen = langIds.map((id) => `editorLangId == ${id}`).join(" || ");
|
|
100
|
+
const seenSubmenus = /* @__PURE__ */ new Set();
|
|
101
|
+
const topEntries = [];
|
|
102
|
+
for (const c of cliCommands) {
|
|
103
|
+
if (c.submenu) {
|
|
104
|
+
if (!seenSubmenus.has(c.submenu)) {
|
|
105
|
+
seenSubmenus.add(c.submenu);
|
|
106
|
+
topEntries.push({ submenu: c.submenu });
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
topEntries.push({ command: c.command });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (topEntries.length > 0 && (explorerWhen || editorWhen)) {
|
|
113
|
+
const explorerMenu = topEntries.map((e, i) => ({
|
|
114
|
+
...e.submenu ? { submenu: e.submenu } : { command: e.command },
|
|
115
|
+
when: explorerWhen,
|
|
116
|
+
group: `specverse@${i + 1}`
|
|
117
|
+
}));
|
|
118
|
+
const editorMenu = topEntries.map((e, i) => ({
|
|
119
|
+
...e.submenu ? { submenu: e.submenu } : { command: e.command },
|
|
120
|
+
when: editorWhen,
|
|
121
|
+
group: `specverse@${i + 1}`
|
|
122
|
+
}));
|
|
123
|
+
const menus = {
|
|
124
|
+
"explorer/context": explorerMenu,
|
|
125
|
+
"editor/context": editorMenu
|
|
126
|
+
};
|
|
127
|
+
for (const sub of submenuDefs) {
|
|
128
|
+
menus[sub.id] = cliCommands.filter((c) => c.submenu === sub.id).map((c) => ({ command: c.command }));
|
|
129
|
+
}
|
|
130
|
+
packageJson.contributes.menus = menus;
|
|
131
|
+
if (submenuDefs.length > 0) {
|
|
132
|
+
packageJson.contributes.submenus = submenuDefs.map((s) => ({
|
|
133
|
+
id: s.id,
|
|
134
|
+
label: s.label
|
|
135
|
+
}));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
47
138
|
}
|
|
48
139
|
if (distribution.themes && distribution.themes.length > 0) {
|
|
49
140
|
packageJson.contributes.themes = distribution.themes.map((theme) => ({
|
|
@@ -61,6 +152,29 @@ function generateVSCodeExtension(context) {
|
|
|
61
152
|
if (existsSync(staticDir)) {
|
|
62
153
|
copyRecursive(staticDir, extensionDir);
|
|
63
154
|
}
|
|
155
|
+
const schemaSrc = resolveComposedSchemaPath();
|
|
156
|
+
if (schemaSrc) {
|
|
157
|
+
const schemasDir = join(extensionDir, "schemas");
|
|
158
|
+
if (!existsSync(schemasDir)) mkdirSync(schemasDir, { recursive: true });
|
|
159
|
+
copyFileSync(schemaSrc, join(schemasDir, "specverse-schema.json"));
|
|
160
|
+
}
|
|
161
|
+
if (distribution?.languages && distribution.languages.length > 0) {
|
|
162
|
+
const syntaxesDir = join(extensionDir, "syntaxes");
|
|
163
|
+
if (existsSync(syntaxesDir)) {
|
|
164
|
+
const langId = distribution.languages[0].id;
|
|
165
|
+
const targetName = `${langId}.tmLanguage.json`;
|
|
166
|
+
const targetPath = join(syntaxesDir, targetName);
|
|
167
|
+
if (!existsSync(targetPath)) {
|
|
168
|
+
const existing = readdirSync(syntaxesDir).find(
|
|
169
|
+
(f) => f.endsWith(".tmLanguage.json") && f !== targetName
|
|
170
|
+
);
|
|
171
|
+
if (existing) {
|
|
172
|
+
copyFileSync(join(syntaxesDir, existing), targetPath);
|
|
173
|
+
unlinkSync(join(syntaxesDir, existing));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
64
178
|
const srcDir = join(extensionDir, "src");
|
|
65
179
|
if (!existsSync(srcDir)) mkdirSync(srcDir, { recursive: true });
|
|
66
180
|
const extTs = join(staticDir, "extension.ts");
|
|
@@ -102,6 +216,56 @@ function extractDistribution(spec) {
|
|
|
102
216
|
}
|
|
103
217
|
return allDistributions.length > 0 ? allDistributions[0] : null;
|
|
104
218
|
}
|
|
219
|
+
function findSpecCommand(spec, ref) {
|
|
220
|
+
if (!ref) return null;
|
|
221
|
+
const parts = ref.split(".");
|
|
222
|
+
const target = parts[parts.length - 1];
|
|
223
|
+
const components = spec?.components || {};
|
|
224
|
+
const componentList = Array.isArray(components) ? components : Object.entries(components).map(([name, data]) => ({ name, ...data }));
|
|
225
|
+
for (const comp of componentList) {
|
|
226
|
+
const cliCommands = comp?.commands;
|
|
227
|
+
if (!cliCommands) continue;
|
|
228
|
+
for (const [, rootDef] of Object.entries(cliCommands)) {
|
|
229
|
+
const subcommands = rootDef?.subcommands || {};
|
|
230
|
+
if (subcommands[target]) return subcommands[target];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
function buildCLICommandMap(spec) {
|
|
236
|
+
const map = /* @__PURE__ */ new Map();
|
|
237
|
+
const components = spec?.components || {};
|
|
238
|
+
const componentList = Array.isArray(components) ? components : Object.entries(components).map(([name, data]) => ({ name, ...data }));
|
|
239
|
+
for (const comp of componentList) {
|
|
240
|
+
const compName = comp.name || "";
|
|
241
|
+
const cliCommands = comp?.commands;
|
|
242
|
+
if (!cliCommands) continue;
|
|
243
|
+
for (const [rootName, rootDef] of Object.entries(cliCommands)) {
|
|
244
|
+
const subcommands = rootDef?.subcommands || {};
|
|
245
|
+
for (const [subName, subDef] of Object.entries(subcommands)) {
|
|
246
|
+
const sub = subDef;
|
|
247
|
+
const entry = { description: sub.description, title: sub.title };
|
|
248
|
+
if (compName) map.set(`${compName}.${subName}`, entry);
|
|
249
|
+
map.set(`${rootName}.${subName}`, entry);
|
|
250
|
+
if (!map.has(subName)) map.set(subName, entry);
|
|
251
|
+
const nestedSubs = sub?.subcommands;
|
|
252
|
+
if (nestedSubs) {
|
|
253
|
+
for (const [nestedName, nestedDef] of Object.entries(nestedSubs)) {
|
|
254
|
+
const nestedEntry = {
|
|
255
|
+
description: nestedDef.description,
|
|
256
|
+
title: nestedDef.title
|
|
257
|
+
};
|
|
258
|
+
const qualified = `${subName}.${nestedName}`;
|
|
259
|
+
if (compName) map.set(`${compName}.${qualified}`, nestedEntry);
|
|
260
|
+
map.set(`${rootName}.${qualified}`, nestedEntry);
|
|
261
|
+
if (!map.has(qualified)) map.set(qualified, nestedEntry);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return map;
|
|
268
|
+
}
|
|
105
269
|
function extractCLICommands(spec) {
|
|
106
270
|
const commands = [];
|
|
107
271
|
const components = spec?.components || {};
|
|
@@ -159,7 +323,7 @@ function generatePackageJson(commands, _entityTypes, specVersion = "1.0.0") {
|
|
|
159
323
|
publisher: "specverse",
|
|
160
324
|
engines: { vscode: "^1.80.0" },
|
|
161
325
|
categories: ["Programming Languages", "Linters", "Snippets"],
|
|
162
|
-
activationEvents: [
|
|
326
|
+
activationEvents: [],
|
|
163
327
|
main: "./dist/extension.js",
|
|
164
328
|
contributes: {
|
|
165
329
|
languages: [{
|
|
@@ -175,7 +339,7 @@ function generatePackageJson(commands, _entityTypes, specVersion = "1.0.0") {
|
|
|
175
339
|
}],
|
|
176
340
|
jsonValidation: [{
|
|
177
341
|
fileMatch: ["*.specly", "*.specverse"],
|
|
178
|
-
url: "./schemas/specverse-
|
|
342
|
+
url: "./schemas/specverse-schema.json"
|
|
179
343
|
}],
|
|
180
344
|
themes: [
|
|
181
345
|
{ label: "SpecVerse Dark", uiTheme: "vs-dark", path: "./themes/specverse-complete-theme.json" },
|
|
@@ -249,7 +249,7 @@ import type { ParserEngine, InferenceEngine } from '@specverse/types';`,
|
|
|
249
249
|
},
|
|
250
250
|
realize: {
|
|
251
251
|
imports: `import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
252
|
-
import { resolve, join } from 'path';
|
|
252
|
+
import { resolve, join, dirname } from 'path';
|
|
253
253
|
import { EngineRegistry } from '@specverse/entities';
|
|
254
254
|
import type { ParserEngine, InferenceEngine, RealizeEngine } from '@specverse/types';`,
|
|
255
255
|
handler: `if (!existsSync(file)) {
|
|
@@ -386,10 +386,32 @@ import type { ParserEngine, InferenceEngine, RealizeEngine } from '@specverse/ty
|
|
|
386
386
|
}
|
|
387
387
|
const inferredSpec = { ...componentData, componentName, components: inferredYaml?.components || {} };
|
|
388
388
|
|
|
389
|
-
// Realize — let the realize engine handle its own library
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
389
|
+
// Realize — let the realize engine handle its own library.
|
|
390
|
+
// Locate the nearest implementation manifest by walking up from the
|
|
391
|
+
// spec file, then falling back to the user's cwd. This lets the same
|
|
392
|
+
// invocation work from any subdirectory (CLI, VSCode right-click, CI).
|
|
393
|
+
const cwd = process.env.SPECVERSE_USER_CWD || process.cwd();
|
|
394
|
+
let manifestPath: string | null = null;
|
|
395
|
+
if (options.manifest) {
|
|
396
|
+
manifestPath = resolve(cwd, options.manifest);
|
|
397
|
+
} else {
|
|
398
|
+
let searchDir = dirname(resolve(file));
|
|
399
|
+
while (true) {
|
|
400
|
+
const inManifests = join(searchDir, 'manifests', 'implementation.yaml');
|
|
401
|
+
if (existsSync(inManifests)) { manifestPath = inManifests; break; }
|
|
402
|
+
const flat = join(searchDir, 'implementation.yaml');
|
|
403
|
+
if (existsSync(flat)) { manifestPath = flat; break; }
|
|
404
|
+
const parent = dirname(searchDir);
|
|
405
|
+
if (parent === searchDir) break;
|
|
406
|
+
searchDir = parent;
|
|
407
|
+
}
|
|
408
|
+
if (!manifestPath) {
|
|
409
|
+
const cwdBased = resolve(cwd, 'manifests/implementation.yaml');
|
|
410
|
+
if (existsSync(cwdBased)) manifestPath = cwdBased;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
if (!manifestPath || !existsSync(manifestPath)) {
|
|
414
|
+
console.error('Manifest not found. Looked for manifests/implementation.yaml walking up from the spec file, then in ' + cwd);
|
|
393
415
|
process.exit(1);
|
|
394
416
|
}
|
|
395
417
|
|
|
@@ -24,7 +24,7 @@ The static framework includes:
|
|
|
24
24
|
|
|
25
25
|
The generated MCP server exposes tools like `specverse-create`, `specverse-analyse`, `specverse-validate`, `specverse-realize`, and `specverse-suggest`, plus resources for schema, conventions, library catalog, and prompt templates.
|
|
26
26
|
|
|
27
|
-
**Package**: `@specverse/mcp` v3.5.2, depends on `@modelcontextprotocol/sdk` and `@specverse/
|
|
27
|
+
**Package**: `@specverse/mcp` v3.5.2, depends on `@modelcontextprotocol/sdk` and `@specverse/engines`.
|
|
28
28
|
|
|
29
29
|
### VSCode Extension (`templates/vscode/`)
|
|
30
30
|
|