@specverse/engines 5.0.2 → 5.2.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.
- package/assets/prompts/core/standard/default/analyse.prompt.yaml +5 -5
- package/assets/prompts/core/standard/default/app-demo.prompt.yaml +21 -1
- package/assets/prompts/core/standard/default/behavior.prompt.yaml +150 -0
- package/assets/prompts/core/standard/default/create.prompt.yaml +3 -3
- package/assets/prompts/core/standard/default/materialise.prompt.yaml +804 -774
- package/assets/prompts/core/standard/default/realize.prompt.yaml +581 -544
- package/assets/prompts/core/standard/v9/analyse.prompt.yaml +5 -5
- package/assets/prompts/core/standard/v9/app-demo.prompt.yaml +233 -0
- package/assets/prompts/core/standard/v9/behavior.prompt.yaml +33 -9
- package/assets/prompts/core/standard/v9/create.prompt.yaml +3 -3
- package/assets/prompts/core/standard/v9/materialise.prompt.yaml +804 -774
- package/assets/prompts/core/standard/v9/realize.prompt.yaml +581 -544
- package/dist/ai/commands/fill.d.ts.map +1 -1
- package/dist/ai/commands/fill.js +16 -7
- package/dist/ai/commands/fill.js.map +1 -1
- package/dist/ai/commands/template.d.ts.map +1 -1
- package/dist/ai/commands/template.js +17 -8
- package/dist/ai/commands/template.js.map +1 -1
- package/dist/bundles/deriveCatalog.d.ts +18 -0
- package/dist/bundles/deriveCatalog.d.ts.map +1 -0
- package/dist/bundles/deriveCatalog.js +263 -0
- package/dist/bundles/deriveCatalog.js.map +1 -0
- package/dist/bundles/index.d.ts +15 -0
- package/dist/bundles/index.d.ts.map +1 -0
- package/dist/bundles/index.js +15 -0
- package/dist/bundles/index.js.map +1 -0
- package/dist/bundles/types.d.ts +53 -0
- package/dist/bundles/types.d.ts.map +1 -0
- package/dist/bundles/types.js +22 -0
- package/dist/bundles/types.js.map +1 -0
- package/dist/bundles/validate.d.ts +55 -0
- package/dist/bundles/validate.d.ts.map +1 -0
- package/dist/bundles/validate.js +471 -0
- package/dist/bundles/validate.js.map +1 -0
- package/dist/inference/quint-transpiler.js +2 -2
- package/dist/inference/quint-transpiler.js.map +1 -1
- package/dist/libs/instance-factories/applications/templates/react/runtime-package-json-generator.js +1 -1
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +227 -0
- package/dist/libs/instance-factories/tools/templates/mcp/mcp-server-generator.js +295 -14
- package/libs/instance-factories/applications/templates/react/runtime-package-json-generator.ts +1 -1
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +227 -0
- package/libs/instance-factories/tools/templates/mcp/mcp-server-generator.ts +328 -15
- package/package.json +9 -5
- package/assets/examples/09-api/ai-spec.yaml +0 -194
- package/assets/examples/09-api/converted.yaml +0 -95
- package/assets/examples/09-api/diagram-architecture.mmd +0 -10
- package/assets/examples/09-api/diagram-er.mmd +0 -10
- package/assets/examples/09-api/documentation.html +0 -104
- package/assets/examples/09-api/documentation.md +0 -95
- package/assets/examples/09-api/inferred-spec.yaml +0 -420
- package/assets/examples/09-api/openapi.json +0 -61
- package/assets/examples/10-api/README.md +0 -216
- package/assets/examples/10-api/ai-spec.yaml +0 -194
- package/assets/examples/10-api/converted.yaml +0 -96
- package/assets/examples/10-api/diagram-architecture.mmd +0 -10
- package/assets/examples/10-api/diagram-er.mmd +0 -10
- package/assets/examples/10-api/documentation.html +0 -104
- package/assets/examples/10-api/documentation.md +0 -95
- package/assets/examples/10-api/inferred-spec.yaml +0 -7
- package/assets/examples/10-api/metadata.yaml +0 -89
- package/assets/examples/10-api/openapi.json +0 -61
- package/assets/examples/10-api/package-integration-test.js +0 -177
- package/assets/examples/10-api/usage-example.js +0 -323
- package/assets/examples/10-api/usage-example.ts +0 -363
- package/assets/examples/10-api/workflow-test.js +0 -113
- package/assets/examples/validate-examples-with-expected-failures.cjs +0 -328
- package/assets/examples/validate-examples.cjs +0 -225
- package/assets/prompts/MOVED.md +0 -35
- package/assets/prompts/SUMMARY-v8-PROMOTION.md +0 -445
- package/assets/prompts/core/CHANGELOG.md +0 -158
- package/assets/prompts/core/MIGRATION-v6-to-v7.md +0 -379
- package/assets/prompts/core/base-terminal-prompt.md +0 -201
- package/assets/prompts/core/examples/example-usage.ts +0 -140
- package/assets/prompts/core/schemas/prompt.schema.json +0 -309
- package/assets/prompts/core/schemas/prompt.schema.yaml +0 -229
- package/assets/prompts/core/standard/archive/v1/analyse.prompt.yaml +0 -259
- package/assets/prompts/core/standard/archive/v1/create.prompt.yaml +0 -302
- package/assets/prompts/core/standard/archive/v1/materialise.prompt.yaml +0 -328
- package/assets/prompts/core/standard/archive/v1/realize.prompt.yaml +0 -606
- package/assets/prompts/core/standard/archive/v2/README.md +0 -110
- package/assets/prompts/core/standard/archive/v2/analyse.prompt.yaml +0 -151
- package/assets/prompts/core/standard/archive/v2/create.prompt.yaml +0 -151
- package/assets/prompts/core/standard/archive/v2/materialise.prompt.yaml +0 -132
- package/assets/prompts/core/standard/archive/v2/realize.prompt.yaml +0 -147
- package/assets/prompts/core/standard/archive/v3/README.md +0 -279
- package/assets/prompts/core/standard/archive/v3/analyse.prompt.yaml +0 -309
- package/assets/prompts/core/standard/archive/v3/create.prompt.yaml +0 -351
- package/assets/prompts/core/standard/archive/v3/materialise.prompt.yaml +0 -247
- package/assets/prompts/core/standard/archive/v3/realize.prompt.yaml +0 -344
- package/assets/prompts/core/standard/archive/v4/README.md +0 -79
- package/assets/prompts/core/standard/archive/v4/analyse.prompt.yaml +0 -204
- package/assets/prompts/core/standard/archive/v4/create.prompt.yaml +0 -185
- package/assets/prompts/core/standard/archive/v5/README.md +0 -224
- package/assets/prompts/core/standard/archive/v5/analyse.prompt.yaml +0 -209
- package/assets/prompts/core/standard/archive/v5/create.prompt.yaml +0 -225
- package/assets/prompts/core/standard/archive/v5/materialise.prompt.yaml +0 -242
- package/assets/prompts/core/standard/archive/v5/realize.prompt.yaml +0 -336
- package/assets/prompts/core/standard/archive/v6/README.md +0 -187
- package/assets/prompts/core/standard/archive/v6/analyse.prompt.yaml +0 -219
- package/assets/prompts/core/standard/archive/v6/create.prompt.yaml +0 -180
- package/assets/prompts/core/standard/archive/v6/materialise.prompt.yaml +0 -203
- package/assets/prompts/core/standard/archive/v6/realize.prompt.yaml +0 -215
- package/assets/prompts/core/standard/archive/v7/analyse.prompt.nick.yaml +0 -144
- package/assets/prompts/core/standard/archive/v7/analyse.prompt.old.yaml +0 -146
- package/assets/prompts/core/standard/archive/v7/analyse.prompt.yaml +0 -129
- package/assets/prompts/core/standard/archive/v7/create.prompt.yaml +0 -146
- package/assets/prompts/core/standard/archive/v7/materialise.prompt.yaml +0 -297
- package/assets/prompts/core/standard/archive/v7/realize.prompt.yaml +0 -294
- package/assets/prompts/core/standard/archive/v8/README.md +0 -400
- package/assets/prompts/core/standard/archive/v8/analyse.prompt.yaml +0 -185
- package/assets/prompts/core/standard/archive/v8/create.prompt.yaml +0 -203
- package/assets/prompts/core/standard/archive/v8/materialise.prompt.yaml +0 -297
- package/assets/prompts/core/standard/archive/v8/realize.prompt.yaml +0 -294
- package/assets/prompts/templates/api-orchestrator-template.yaml +0 -188
- package/assets/prompts/templates/claude-integration-template.md +0 -121
- package/assets/prompts/templates/terminal-prompt-template.md +0 -97
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { createRequire } from "module";
|
|
2
3
|
import { join } from "path";
|
|
4
|
+
const require2 = createRequire(import.meta.url);
|
|
3
5
|
function generateMCPServer(context) {
|
|
4
6
|
const { spec, outputDir } = context;
|
|
5
7
|
const mcpDir = join(outputDir || ".", "tools", "specverse-mcp");
|
|
6
8
|
const srcDir = join(mcpDir, "src");
|
|
7
9
|
if (!existsSync(srcDir)) mkdirSync(srcDir, { recursive: true });
|
|
8
10
|
const distribution = extractMCPDistribution(spec);
|
|
9
|
-
const version = distribution?.version || spec?.metadata?.version || spec?.version || "5.
|
|
11
|
+
const version = distribution?.version || resolveSelfVersion() || spec?.metadata?.version || spec?.version || "5.1.0";
|
|
10
12
|
const description = distribution?.description || "SpecVerse MCP server \u2014 exposes the specverse CLI as MCP tools and the live spec schema + docs as MCP resources.";
|
|
11
13
|
const displayName = distribution?.displayName || "SpecVerse MCP";
|
|
12
14
|
const cliCommands = extractCLITools(spec);
|
|
@@ -14,10 +16,20 @@ function generateMCPServer(context) {
|
|
|
14
16
|
writeFileSync(join(mcpDir, "tsconfig.json"), generateTsconfig());
|
|
15
17
|
writeFileSync(join(srcDir, "server.ts"), generateServer(displayName, version));
|
|
16
18
|
writeFileSync(join(srcDir, "cli-runner.ts"), generateCliRunner());
|
|
17
|
-
writeFileSync(join(srcDir, "resources.ts"), generateResources());
|
|
19
|
+
writeFileSync(join(srcDir, "resources.ts"), generateResources(cliCommands));
|
|
18
20
|
writeFileSync(join(srcDir, "tools.ts"), generateTools(cliCommands));
|
|
21
|
+
writeFileSync(join(srcDir, "prompts.ts"), generatePrompts());
|
|
19
22
|
return `MCP server generated in: ${mcpDir}
|
|
20
|
-
${cliCommands.length} tools
|
|
23
|
+
${cliCommands.length} tools, 5 resources, 6 prompts (derived from @specverse/engines/assets/prompts)`;
|
|
24
|
+
}
|
|
25
|
+
function resolveSelfVersion() {
|
|
26
|
+
try {
|
|
27
|
+
const pkgPath = require2.resolve("@specverse/self/package.json");
|
|
28
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
29
|
+
return pkg.version || null;
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
21
33
|
}
|
|
22
34
|
function extractCLITools(spec) {
|
|
23
35
|
const out = [];
|
|
@@ -118,9 +130,13 @@ function generatePackageJson(version, description) {
|
|
|
118
130
|
},
|
|
119
131
|
dependencies: {
|
|
120
132
|
"@modelcontextprotocol/sdk": "^1.17.4",
|
|
121
|
-
"@specverse/
|
|
133
|
+
"@specverse/engines": "^5.2.0",
|
|
134
|
+
"@specverse/entities": "^5.1.0",
|
|
135
|
+
"@specverse/self": "^5.2.0",
|
|
136
|
+
"js-yaml": "^4.1.0"
|
|
122
137
|
},
|
|
123
138
|
devDependencies: {
|
|
139
|
+
"@types/js-yaml": "^4.0.9",
|
|
124
140
|
"@types/node": "^20.19.11",
|
|
125
141
|
typescript: "^5.9.2"
|
|
126
142
|
},
|
|
@@ -155,13 +171,15 @@ function generateTsconfig() {
|
|
|
155
171
|
}, null, 2) + "\n";
|
|
156
172
|
}
|
|
157
173
|
function generateServer(displayName, version) {
|
|
174
|
+
const instructions = SERVER_INSTRUCTIONS;
|
|
158
175
|
return `#!/usr/bin/env node
|
|
159
176
|
/**
|
|
160
177
|
* SpecVerse MCP Server \u2014 stdio transport.
|
|
161
178
|
*
|
|
162
|
-
* Wires the MCP protocol to the generated tool registry + live resources
|
|
163
|
-
*
|
|
164
|
-
* (tools from CLI commands
|
|
179
|
+
* Wires the MCP protocol to the generated tool registry + live resources
|
|
180
|
+
* + canonical workflow prompts. Everything is derived from the spec
|
|
181
|
+
* (tools from CLI commands, resources from @specverse/entities + @specverse/self,
|
|
182
|
+
* prompts from @specverse/engines/assets/prompts/core/standard/default).
|
|
165
183
|
*/
|
|
166
184
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
167
185
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -170,13 +188,21 @@ import {
|
|
|
170
188
|
CallToolRequestSchema,
|
|
171
189
|
ListResourcesRequestSchema,
|
|
172
190
|
ReadResourceRequestSchema,
|
|
191
|
+
ListPromptsRequestSchema,
|
|
192
|
+
GetPromptRequestSchema,
|
|
173
193
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
174
194
|
import { TOOLS, callTool } from './tools.js';
|
|
175
195
|
import { RESOURCES, readResource } from './resources.js';
|
|
196
|
+
import { PROMPTS, getPrompt } from './prompts.js';
|
|
197
|
+
|
|
198
|
+
const INSTRUCTIONS = ${JSON.stringify(instructions)};
|
|
176
199
|
|
|
177
200
|
const server = new Server(
|
|
178
201
|
{ name: ${JSON.stringify(displayName)}, version: ${JSON.stringify(version)} },
|
|
179
|
-
{
|
|
202
|
+
{
|
|
203
|
+
capabilities: { tools: {}, resources: {}, prompts: {} },
|
|
204
|
+
instructions: INSTRUCTIONS,
|
|
205
|
+
},
|
|
180
206
|
);
|
|
181
207
|
|
|
182
208
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
@@ -205,10 +231,49 @@ server.setRequestHandler(ReadResourceRequestSchema, async (req: { params: { uri:
|
|
|
205
231
|
return readResource(req.params.uri);
|
|
206
232
|
});
|
|
207
233
|
|
|
234
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
235
|
+
prompts: PROMPTS.map(p => ({
|
|
236
|
+
name: p.name,
|
|
237
|
+
description: p.description,
|
|
238
|
+
arguments: p.arguments,
|
|
239
|
+
})),
|
|
240
|
+
}));
|
|
241
|
+
|
|
242
|
+
server.setRequestHandler(GetPromptRequestSchema, async (req: { params: { name: string; arguments?: Record<string, string> } }) => {
|
|
243
|
+
const { name, arguments: args } = req.params;
|
|
244
|
+
return getPrompt(name, args ?? {});
|
|
245
|
+
});
|
|
246
|
+
|
|
208
247
|
const transport = new StdioServerTransport();
|
|
209
248
|
await server.connect(transport);
|
|
210
249
|
`;
|
|
211
250
|
}
|
|
251
|
+
const SERVER_INSTRUCTIONS = [
|
|
252
|
+
"SpecVerse is a declarative specification language. You describe WHAT a system does in a .specly file, and the engines generate HOW \u2014 backend (Fastify/Prisma), frontend (React/Tailwind), CLI, tools, diagrams.",
|
|
253
|
+
"",
|
|
254
|
+
"Before using tools, read these resources to ground yourself in the language:",
|
|
255
|
+
"- specverse://guide \u2014 canonical user guide (spec language, CLI reference, convention patterns)",
|
|
256
|
+
"- specverse://ai-guidance \u2014 curated hints for generating valid specs",
|
|
257
|
+
"- specverse://minimal-example \u2014 one minimal .specly showing every feature in ~100 lines",
|
|
258
|
+
"- specverse://schema \u2014 the JSON Schema (draft 2020-12) for .specly validation",
|
|
259
|
+
"- specverse://cli-reference \u2014 every spv CLI subcommand with flags + arguments",
|
|
260
|
+
"",
|
|
261
|
+
"Common high-leverage workflows are exposed as MCP prompts (preferred entry point):",
|
|
262
|
+
"- create: natural-language requirements \u2192 minimal .specly",
|
|
263
|
+
"- analyse: existing codebase \u2192 .specly that captures what is implemented",
|
|
264
|
+
"- materialise: .specly \u2192 production code",
|
|
265
|
+
"- realize: generate deployment configs",
|
|
266
|
+
"- behavior: generate AI behavior function stubs",
|
|
267
|
+
"- app-demo: interactive spec creation/modification for the runtime interpreter",
|
|
268
|
+
"",
|
|
269
|
+
"Tools map 1:1 to the spv CLI. Key distinctions:",
|
|
270
|
+
"- validate: check a .specly file parses + matches the schema",
|
|
271
|
+
"- validate-manifest: check an implementation manifest resolves cleanly",
|
|
272
|
+
"- validate-bundle: check an entity bundle (schema + examples + tests + docs + behaviour facets)",
|
|
273
|
+
"- infer: expand a minimal .specly to full architecture (controllers / services / events / views)",
|
|
274
|
+
"- realize: turn inferred spec + manifest into generated code (Fastify / Prisma / React / CLI / tools)",
|
|
275
|
+
"- init: scaffold a new project from a template"
|
|
276
|
+
].join("\n");
|
|
212
277
|
function generateCliRunner() {
|
|
213
278
|
return `/**
|
|
214
279
|
* Thin specverse CLI runner.
|
|
@@ -308,11 +373,16 @@ export async function callTool(name: string, args: Record<string, any>) {
|
|
|
308
373
|
}
|
|
309
374
|
`;
|
|
310
375
|
}
|
|
311
|
-
function generateResources() {
|
|
376
|
+
function generateResources(tools) {
|
|
377
|
+
const cliReference = buildCliReferenceMarkdown(tools);
|
|
312
378
|
return `/**
|
|
313
|
-
* Resource registry \u2014 exposes the
|
|
314
|
-
* MCP resources
|
|
315
|
-
*
|
|
379
|
+
* Resource registry \u2014 exposes the canonical SpecVerse reference material as
|
|
380
|
+
* MCP resources:
|
|
381
|
+
* - schema (JSON Schema draft 2020-12, from @specverse/entities)
|
|
382
|
+
* - ai-guidance (curated LLM hints, from @specverse/entities)
|
|
383
|
+
* - minimal-example (one .specly covering all features, from @specverse/entities)
|
|
384
|
+
* - guide (user guide, from @specverse/self)
|
|
385
|
+
* - cli-reference (derived from the spec at realize time, embedded below)
|
|
316
386
|
*/
|
|
317
387
|
import { readFileSync } from 'fs';
|
|
318
388
|
import { createRequire } from 'module';
|
|
@@ -333,6 +403,13 @@ function resolveEntitiesFile(relative: string): string {
|
|
|
333
403
|
return join(dirname(pkg), relative);
|
|
334
404
|
}
|
|
335
405
|
|
|
406
|
+
function resolveSelfFile(relative: string): string {
|
|
407
|
+
const pkg = require.resolve('@specverse/self/package.json');
|
|
408
|
+
return join(dirname(pkg), relative);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const CLI_REFERENCE_MARKDOWN = ${JSON.stringify(cliReference)};
|
|
412
|
+
|
|
336
413
|
export const RESOURCES: Resource[] = [
|
|
337
414
|
{
|
|
338
415
|
uri: 'specverse://schema',
|
|
@@ -344,13 +421,43 @@ export const RESOURCES: Resource[] = [
|
|
|
344
421
|
mimeType: 'application/json',
|
|
345
422
|
}),
|
|
346
423
|
},
|
|
424
|
+
{
|
|
425
|
+
uri: 'specverse://ai-guidance',
|
|
426
|
+
name: 'SpecVerse AI Guidance Schema',
|
|
427
|
+
description: 'YAML schema annotated with examples and LLM guidance for generating valid specs. Read this before authoring or mutating .specly files.',
|
|
428
|
+
mimeType: 'application/x-yaml',
|
|
429
|
+
resolve: () => ({
|
|
430
|
+
text: readFileSync(resolveEntitiesFile('schema/SPECVERSE-SCHEMA-AI.yaml'), 'utf8'),
|
|
431
|
+
mimeType: 'application/x-yaml',
|
|
432
|
+
}),
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
uri: 'specverse://minimal-example',
|
|
436
|
+
name: 'SpecVerse Minimal Example',
|
|
437
|
+
description: 'One complete minimal .specly demonstrating every feature (~100 lines) \u2014 component, models, relationships, lifecycle, CURVED controller, service, view, event, manifest, deployment.',
|
|
438
|
+
mimeType: 'text/x-yaml',
|
|
439
|
+
resolve: () => ({
|
|
440
|
+
text: readFileSync(resolveEntitiesFile('schema/MINIMAL-SYNTAX-REFERENCE.specly'), 'utf8'),
|
|
441
|
+
mimeType: 'text/x-yaml',
|
|
442
|
+
}),
|
|
443
|
+
},
|
|
347
444
|
{
|
|
348
445
|
uri: 'specverse://guide',
|
|
349
446
|
name: 'SpecVerse Complete Guide',
|
|
350
447
|
description: 'The canonical user guide \u2014 spec language, convention patterns, CLI reference.',
|
|
351
448
|
mimeType: 'text/markdown',
|
|
352
449
|
resolve: () => ({
|
|
353
|
-
text: readFileSync(
|
|
450
|
+
text: readFileSync(resolveSelfFile('docs/guides/SPECVERSE-COMPLETE-GUIDE.md'), 'utf8'),
|
|
451
|
+
mimeType: 'text/markdown',
|
|
452
|
+
}),
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
uri: 'specverse://cli-reference',
|
|
456
|
+
name: 'SpecVerse CLI Reference',
|
|
457
|
+
description: 'Every spv CLI subcommand with its arguments, flags, and exit codes. Derived from the spec at realize time.',
|
|
458
|
+
mimeType: 'text/markdown',
|
|
459
|
+
resolve: () => ({
|
|
460
|
+
text: CLI_REFERENCE_MARKDOWN,
|
|
354
461
|
mimeType: 'text/markdown',
|
|
355
462
|
}),
|
|
356
463
|
},
|
|
@@ -370,6 +477,180 @@ export async function readResource(uri: string) {
|
|
|
370
477
|
}
|
|
371
478
|
`;
|
|
372
479
|
}
|
|
480
|
+
function buildCliReferenceMarkdown(tools) {
|
|
481
|
+
const lines = [];
|
|
482
|
+
lines.push("# SpecVerse CLI Reference");
|
|
483
|
+
lines.push("");
|
|
484
|
+
lines.push("Generated from the self-spec at realize time. Every entry here matches an MCP tool exposed by this server (same name, same input schema).");
|
|
485
|
+
lines.push("");
|
|
486
|
+
for (const tool of tools) {
|
|
487
|
+
const cliCmd = tool.cliArgs.join(" ");
|
|
488
|
+
lines.push(`## \`spv ${cliCmd}\``);
|
|
489
|
+
lines.push("");
|
|
490
|
+
lines.push(tool.description);
|
|
491
|
+
lines.push("");
|
|
492
|
+
const props = tool.inputSchema?.properties || {};
|
|
493
|
+
const required = new Set(tool.inputSchema?.required || []);
|
|
494
|
+
const positional = new Set(tool.positional);
|
|
495
|
+
const argEntries = Object.entries(props);
|
|
496
|
+
if (argEntries.length > 0) {
|
|
497
|
+
lines.push("| Name | Kind | Required | Type | Description |");
|
|
498
|
+
lines.push("|---|---|---|---|---|");
|
|
499
|
+
for (const [name, schema] of argEntries) {
|
|
500
|
+
const kind = positional.has(name) ? "positional" : "flag";
|
|
501
|
+
const req = required.has(name) ? "yes" : "no";
|
|
502
|
+
const type = schema?.type || "string";
|
|
503
|
+
const desc = (schema?.description || "").replace(/\|/g, "\\|");
|
|
504
|
+
lines.push(`| \`${name}\` | ${kind} | ${req} | ${type} | ${desc} |`);
|
|
505
|
+
}
|
|
506
|
+
lines.push("");
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return lines.join("\n");
|
|
510
|
+
}
|
|
511
|
+
function generatePrompts() {
|
|
512
|
+
return `/**
|
|
513
|
+
* Prompt registry \u2014 reads the canonical workflow prompts from
|
|
514
|
+
* @specverse/engines/assets/prompts/core/standard/default/ at startup and
|
|
515
|
+
* serves them as MCP prompts. Each YAML file (create, analyse, materialise,
|
|
516
|
+
* realize, behavior, app-demo) becomes one invocable prompt.
|
|
517
|
+
*/
|
|
518
|
+
import { readdirSync, readFileSync } from 'fs';
|
|
519
|
+
import { createRequire } from 'module';
|
|
520
|
+
import { dirname, join, basename } from 'path';
|
|
521
|
+
import { load as yamlLoad } from 'js-yaml';
|
|
522
|
+
|
|
523
|
+
const require = createRequire(import.meta.url);
|
|
524
|
+
|
|
525
|
+
export interface PromptArgument {
|
|
526
|
+
name: string;
|
|
527
|
+
description?: string;
|
|
528
|
+
required: boolean;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export interface Prompt {
|
|
532
|
+
name: string;
|
|
533
|
+
description: string;
|
|
534
|
+
arguments: PromptArgument[];
|
|
535
|
+
source: any; // parsed YAML \u2014 kept so getPrompt can re-render
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
function resolveEntitiesFile(relative: string): string {
|
|
539
|
+
const pkg = require.resolve('@specverse/entities/package.json');
|
|
540
|
+
return join(dirname(pkg), relative);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function resolveEnginesDir(relative: string): string {
|
|
544
|
+
const pkg = require.resolve('@specverse/engines/package.json');
|
|
545
|
+
return join(dirname(pkg), relative);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
// Auto-filled template vars \u2014 paths into @specverse/entities/schema/
|
|
549
|
+
const SCHEMA_VAR_PATHS: Record<string, string> = {
|
|
550
|
+
aiSchemaPath: resolveEntitiesFile('schema/SPECVERSE-SCHEMA-AI.yaml'),
|
|
551
|
+
referenceSchemaPath: resolveEntitiesFile('schema/MINIMAL-SYNTAX-REFERENCE.specly'),
|
|
552
|
+
referenceExamplePath: resolveEntitiesFile('schema/MINIMAL-SYNTAX-REFERENCE.specly'),
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
// User-facing vars the server does NOT auto-fill \u2014 surfaced as MCP prompt args.
|
|
556
|
+
const USER_FACING = new Set<string>([
|
|
557
|
+
...Object.keys(SCHEMA_VAR_PATHS),
|
|
558
|
+
]);
|
|
559
|
+
|
|
560
|
+
function loadPrompts(): Prompt[] {
|
|
561
|
+
const promptsDir = resolveEnginesDir('assets/prompts/core/standard/default');
|
|
562
|
+
const entries = readdirSync(promptsDir).filter(f => f.endsWith('.prompt.yaml'));
|
|
563
|
+
const prompts: Prompt[] = [];
|
|
564
|
+
for (const entry of entries) {
|
|
565
|
+
const full = join(promptsDir, entry);
|
|
566
|
+
try {
|
|
567
|
+
const parsed = yamlLoad(readFileSync(full, 'utf8')) as any;
|
|
568
|
+
if (!parsed?.name) continue;
|
|
569
|
+
const args = deriveArguments(parsed);
|
|
570
|
+
prompts.push({
|
|
571
|
+
name: parsed.name,
|
|
572
|
+
description: parsed.description || \`SpecVerse \${parsed.name} workflow\`,
|
|
573
|
+
arguments: args,
|
|
574
|
+
source: parsed,
|
|
575
|
+
});
|
|
576
|
+
} catch (err) {
|
|
577
|
+
// One bad prompt shouldn't kill the server; skip it.
|
|
578
|
+
console.error(\`[prompts] skipping \${basename(entry)}: \${(err as Error).message}\`);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return prompts;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Every SpecVerse prompt YAML declares user.variables[] in the canonical shape
|
|
586
|
+
* { name, type?, required?, description?, default? }. We surface the declared
|
|
587
|
+
* list verbatim, filtering out auto-filled schema-path vars.
|
|
588
|
+
*/
|
|
589
|
+
function deriveArguments(parsed: any): PromptArgument[] {
|
|
590
|
+
const declared = parsed?.user?.variables;
|
|
591
|
+
if (!Array.isArray(declared)) return [];
|
|
592
|
+
return declared
|
|
593
|
+
.filter((v: any) => v && typeof v === 'object' && typeof v.name === 'string')
|
|
594
|
+
.filter((v: any) => !USER_FACING.has(v.name))
|
|
595
|
+
.map((v: any) => ({
|
|
596
|
+
name: v.name,
|
|
597
|
+
description: v.description || inferVarDescription(v.name, parsed),
|
|
598
|
+
required: v.required !== false,
|
|
599
|
+
}));
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function inferVarDescription(varName: string, parsed: any): string {
|
|
603
|
+
// Friendly defaults for the known common vars; fall back to a humanised
|
|
604
|
+
// version of the variable name.
|
|
605
|
+
const defaults: Record<string, string> = {
|
|
606
|
+
requirements: 'Natural-language requirements to extract a specification from',
|
|
607
|
+
scale: 'Project scale \u2014 personal, business, or enterprise',
|
|
608
|
+
preferredTech: 'Preferred technology stack hint (e.g. "nextjs", "nestjs", "fastify+prisma", "auto")',
|
|
609
|
+
implementationPath: 'Path to the existing codebase to reverse-engineer into a .specly',
|
|
610
|
+
specPath: 'Path to an existing .specly file',
|
|
611
|
+
manifestPath: 'Path to an implementation manifest (manifests/implementation.yaml)',
|
|
612
|
+
outputDir: 'Output directory for generated artifacts',
|
|
613
|
+
modelName: 'Name of the model the behavior is attached to',
|
|
614
|
+
behaviorName: 'Name of the behavior method on the model',
|
|
615
|
+
};
|
|
616
|
+
if (defaults[varName]) return defaults[varName];
|
|
617
|
+
return varName.replace(/([A-Z])/g, ' $1').replace(/^./, c => c.toUpperCase());
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function substitute(text: string, values: Record<string, string>): string {
|
|
621
|
+
return text.replace(/\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\}\\}/g, (match, name) => {
|
|
622
|
+
if (name in values) return values[name];
|
|
623
|
+
if (name in SCHEMA_VAR_PATHS) return SCHEMA_VAR_PATHS[name];
|
|
624
|
+
return match; // unknown var \u2014 leave the placeholder so it's visible
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
function renderMessages(prompt: Prompt, args: Record<string, string>): { role: 'user'; content: { type: 'text'; text: string } }[] {
|
|
629
|
+
const src = prompt.source;
|
|
630
|
+
const sections: string[] = [];
|
|
631
|
+
if (src?.system?.role) sections.push(\`[System role]\\n\${substitute(src.system.role, args).trim()}\`);
|
|
632
|
+
if (src?.system?.context) sections.push(\`[Context]\\n\${substitute(src.system.context, args).trim()}\`);
|
|
633
|
+
if (src?.user?.template) sections.push(substitute(src.user.template, args).trim());
|
|
634
|
+
const text = sections.filter(Boolean).join('\\n\\n');
|
|
635
|
+
return [{ role: 'user', content: { type: 'text', text } }];
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export const PROMPTS: Prompt[] = loadPrompts();
|
|
639
|
+
|
|
640
|
+
const BY_NAME = new Map<string, Prompt>(PROMPTS.map(p => [p.name, p]));
|
|
641
|
+
|
|
642
|
+
export async function getPrompt(name: string, args: Record<string, string>) {
|
|
643
|
+
const prompt = BY_NAME.get(name);
|
|
644
|
+
if (!prompt) {
|
|
645
|
+
throw new Error(\`Unknown prompt: \${name}\`);
|
|
646
|
+
}
|
|
647
|
+
return {
|
|
648
|
+
description: prompt.description,
|
|
649
|
+
messages: renderMessages(prompt, args),
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
`;
|
|
653
|
+
}
|
|
373
654
|
export {
|
|
374
655
|
generateMCPServer as default
|
|
375
656
|
};
|
package/libs/instance-factories/applications/templates/react/runtime-package-json-generator.ts
CHANGED
|
@@ -38,7 +38,7 @@ export default function generateRuntimePackageJson(context: TemplateContext): st
|
|
|
38
38
|
"react-dom": "^18.2.0",
|
|
39
39
|
"react-router-dom": "^6.18.0",
|
|
40
40
|
"@tanstack/react-query": "^5.0.0",
|
|
41
|
-
"@specverse/runtime": "^
|
|
41
|
+
"@specverse/runtime": "^5.0.0",
|
|
42
42
|
"js-yaml": "^4.1.0",
|
|
43
43
|
"react-hook-form": "^7.48.0",
|
|
44
44
|
"zod": "^3.22.0",
|
|
@@ -201,6 +201,49 @@ import type { ParserEngine } from '@specverse/types';`,
|
|
|
201
201
|
}
|
|
202
202
|
}`
|
|
203
203
|
},
|
|
204
|
+
'validate-bundle': {
|
|
205
|
+
imports: `import { existsSync, statSync } from 'fs';
|
|
206
|
+
import { resolve } from 'path';`,
|
|
207
|
+
handler: `const target = resolve(path);
|
|
208
|
+
if (!existsSync(target)) {
|
|
209
|
+
console.error('Path not found:', target);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
if (!statSync(target).isDirectory()) {
|
|
213
|
+
console.error('Expected a bundle directory, got a file:', target);
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const { validateBundle } = await import('@specverse/engines/bundles');
|
|
218
|
+
const report = await validateBundle(target);
|
|
219
|
+
|
|
220
|
+
if (options.json) {
|
|
221
|
+
console.log(JSON.stringify(report, null, 2));
|
|
222
|
+
if (report.totals.fail > 0) process.exit(1);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const statusSymbol = (s: 'pass' | 'fail' | 'skip'): string => {
|
|
227
|
+
if (s === 'pass') return '✓';
|
|
228
|
+
if (s === 'fail') return '✗';
|
|
229
|
+
return '–';
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
console.log('Bundle: ' + report.bundle + ' (' + report.path + ')');
|
|
233
|
+
console.log('');
|
|
234
|
+
for (const facet of report.facets) {
|
|
235
|
+
const facetLine = ' ' + statusSymbol(facet.status) + ' ' + facet.facet.padEnd(10) + facet.status + ' (' + facet.duration + 'ms)';
|
|
236
|
+
console.log(facetLine);
|
|
237
|
+
for (const issue of facet.issues) {
|
|
238
|
+
const loc = issue.location ? ' [' + issue.location + ']' : '';
|
|
239
|
+
console.log(' - ' + issue.severity + ': ' + issue.message + loc);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
console.log('');
|
|
243
|
+
console.log('Totals: ' + report.totals.pass + ' pass, ' + report.totals.fail + ' fail, ' + report.totals.skip + ' skip (' + report.duration + 'ms)');
|
|
244
|
+
|
|
245
|
+
if (report.totals.fail > 0) process.exit(1);`
|
|
246
|
+
},
|
|
204
247
|
infer: {
|
|
205
248
|
imports: `import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
206
249
|
import { EngineRegistry } from '@specverse/entities';
|
|
@@ -1127,6 +1170,190 @@ import type { ParserEngine } from '@specverse/types';`,
|
|
|
1127
1170
|
await manager.processJob(jobId);
|
|
1128
1171
|
console.log('Job processed successfully');`
|
|
1129
1172
|
},
|
|
1173
|
+
// === skill subcommands ===
|
|
1174
|
+
'skill.install': {
|
|
1175
|
+
imports: `import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
1176
|
+
import { resolve, dirname, join } from 'path';
|
|
1177
|
+
import { homedir } from 'os';
|
|
1178
|
+
import { fileURLToPath } from 'url';
|
|
1179
|
+
import { createRequire } from 'module';`,
|
|
1180
|
+
handler: `const requireResolve = createRequire(import.meta.url);
|
|
1181
|
+
|
|
1182
|
+
// 1. Resolve target directory.
|
|
1183
|
+
let targetDir: string;
|
|
1184
|
+
if (options.target) {
|
|
1185
|
+
targetDir = resolve(options.target);
|
|
1186
|
+
} else if (options.global) {
|
|
1187
|
+
targetDir = join(homedir(), '.claude', 'skills', 'specverse');
|
|
1188
|
+
} else {
|
|
1189
|
+
// Default: project-local (current working directory).
|
|
1190
|
+
targetDir = join(process.env.SPECVERSE_USER_CWD || process.cwd(), '.claude', 'skills', 'specverse');
|
|
1191
|
+
}
|
|
1192
|
+
mkdirSync(targetDir, { recursive: true });
|
|
1193
|
+
mkdirSync(join(targetDir, 'reference'), { recursive: true });
|
|
1194
|
+
mkdirSync(join(targetDir, 'workflows'), { recursive: true });
|
|
1195
|
+
|
|
1196
|
+
// 2. Helpers to resolve into installed packages.
|
|
1197
|
+
// For @specverse/self specifically, we fall back to walking up from
|
|
1198
|
+
// import.meta.url — handy when running the in-repo bootstrap CLI where
|
|
1199
|
+
// self can't resolve its own package.json via require.
|
|
1200
|
+
const selfRoot = (() => {
|
|
1201
|
+
try {
|
|
1202
|
+
const pkgJson = requireResolve.resolve('@specverse/self/package.json');
|
|
1203
|
+
return dirname(pkgJson);
|
|
1204
|
+
} catch {
|
|
1205
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
1206
|
+
for (let i = 0; i < 8; i++) {
|
|
1207
|
+
const candidate = join(dir, 'package.json');
|
|
1208
|
+
if (existsSync(candidate)) {
|
|
1209
|
+
try {
|
|
1210
|
+
const pkg = JSON.parse(readFileSync(candidate, 'utf8'));
|
|
1211
|
+
if (pkg?.name === '@specverse/self') return dir;
|
|
1212
|
+
} catch { /* continue */ }
|
|
1213
|
+
}
|
|
1214
|
+
const parent = dirname(dir);
|
|
1215
|
+
if (parent === dir) break;
|
|
1216
|
+
dir = parent;
|
|
1217
|
+
}
|
|
1218
|
+
return null;
|
|
1219
|
+
}
|
|
1220
|
+
})();
|
|
1221
|
+
|
|
1222
|
+
const resolvePkg = (pkg: string, rel: string): string | null => {
|
|
1223
|
+
if (pkg === '@specverse/self') {
|
|
1224
|
+
return selfRoot ? join(selfRoot, rel) : null;
|
|
1225
|
+
}
|
|
1226
|
+
try {
|
|
1227
|
+
const pkgJson = requireResolve.resolve(pkg + '/package.json');
|
|
1228
|
+
return join(dirname(pkgJson), rel);
|
|
1229
|
+
} catch { return null; }
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
// 3. Copy SKILL.md from @specverse/self.
|
|
1233
|
+
const skillMdSrc = resolvePkg('@specverse/self', 'skills/specverse/SKILL.md');
|
|
1234
|
+
if (!skillMdSrc || !existsSync(skillMdSrc)) {
|
|
1235
|
+
console.error('Cannot locate SKILL.md in @specverse/self — install failed.');
|
|
1236
|
+
process.exit(1);
|
|
1237
|
+
}
|
|
1238
|
+
writeFileSync(join(targetDir, 'SKILL.md'), readFileSync(skillMdSrc, 'utf8'));
|
|
1239
|
+
|
|
1240
|
+
// 4. Copy reference files (schema + ai-guidance + minimal-example + guide).
|
|
1241
|
+
const refCopies: [string, string, string][] = [
|
|
1242
|
+
['@specverse/entities', 'schema/SPECVERSE-SCHEMA.json', 'reference/schema.json'],
|
|
1243
|
+
['@specverse/entities', 'schema/SPECVERSE-SCHEMA-AI.yaml', 'reference/ai-guidance.yaml'],
|
|
1244
|
+
['@specverse/entities', 'schema/MINIMAL-SYNTAX-REFERENCE.specly', 'reference/minimal-example.specly'],
|
|
1245
|
+
['@specverse/self', 'docs/guides/SPECVERSE-COMPLETE-GUIDE.md', 'reference/guide.md'],
|
|
1246
|
+
];
|
|
1247
|
+
let refCopied = 0;
|
|
1248
|
+
for (const [pkg, rel, dest] of refCopies) {
|
|
1249
|
+
const src = resolvePkg(pkg, rel);
|
|
1250
|
+
if (src && existsSync(src)) {
|
|
1251
|
+
writeFileSync(join(targetDir, dest), readFileSync(src, 'utf8'));
|
|
1252
|
+
refCopied++;
|
|
1253
|
+
} else {
|
|
1254
|
+
console.warn(' (skipped ' + dest + ' — ' + pkg + '/' + rel + ' not found)');
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// 5. Build cli-reference.md from the running CLI's own \`--help\`.
|
|
1259
|
+
// Minimal content — a pointer to the spv help and a static summary.
|
|
1260
|
+
const cliRef = [
|
|
1261
|
+
'# SpecVerse CLI Reference',
|
|
1262
|
+
'',
|
|
1263
|
+
'Run \`spv <command> --help\` for flag details on any command. Common subcommands:',
|
|
1264
|
+
'',
|
|
1265
|
+
'| Command | Purpose |',
|
|
1266
|
+
'|---|---|',
|
|
1267
|
+
'| \`spv init <name>\` | Scaffold a new project (templates: default / full-stack / backend-only / frontend-only) |',
|
|
1268
|
+
'| \`spv validate <spec>\` | Parse + schema-validate a .specly file |',
|
|
1269
|
+
'| \`spv validate-bundle <dir>\` | Validate an entity bundle (for engine extenders) |',
|
|
1270
|
+
'| \`spv infer <spec>\` | Expand a minimal spec to full architecture (controllers / services / events / views) |',
|
|
1271
|
+
'| \`spv realize all <spec>\` | Generate production code from inferred spec + manifest |',
|
|
1272
|
+
'| \`spv gen diagrams <spec>\` | Emit mermaid diagrams (ER, lifecycle, architecture) |',
|
|
1273
|
+
'| \`spv ai template <op> <spec>\` | Dump a canonical workflow prompt filled in for a spec |',
|
|
1274
|
+
'| \`spv smoke\` | Verify the \`spv\` install end-to-end |',
|
|
1275
|
+
'| \`spv skill install [--global\\\\|--project]\` | Reinstall / refresh this skill |',
|
|
1276
|
+
'',
|
|
1277
|
+
'For CI invocations, see the \`SPECVERSE-TOOLING.md\` guide in \`@specverse/self/docs/guides/\`.',
|
|
1278
|
+
'',
|
|
1279
|
+
].join('\\n');
|
|
1280
|
+
writeFileSync(join(targetDir, 'reference', 'cli-reference.md'), cliRef);
|
|
1281
|
+
|
|
1282
|
+
// 6. Emit one workflow markdown per prompt YAML in @specverse/engines/assets/prompts/core/standard/default.
|
|
1283
|
+
const yamlLib = await import('js-yaml').catch(() => null) as any;
|
|
1284
|
+
const workflowsDir = resolvePkg('@specverse/engines', 'assets/prompts/core/standard/default');
|
|
1285
|
+
let workflowCount = 0;
|
|
1286
|
+
if (yamlLib && workflowsDir && existsSync(workflowsDir)) {
|
|
1287
|
+
const entries = readdirSync(workflowsDir).filter((f: string) => f.endsWith('.prompt.yaml'));
|
|
1288
|
+
for (const entry of entries) {
|
|
1289
|
+
try {
|
|
1290
|
+
const parsed = yamlLib.load(readFileSync(join(workflowsDir, entry), 'utf8')) as any;
|
|
1291
|
+
if (!parsed?.name) continue;
|
|
1292
|
+
const md = buildWorkflowMarkdown(parsed);
|
|
1293
|
+
writeFileSync(join(targetDir, 'workflows', parsed.name + '.md'), md);
|
|
1294
|
+
workflowCount++;
|
|
1295
|
+
} catch (err: any) {
|
|
1296
|
+
console.warn(' (skipped workflow ' + entry + ' — ' + err.message + ')');
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
} else {
|
|
1300
|
+
console.warn(' (no workflows emitted — js-yaml or @specverse/engines prompts unavailable)');
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// 7. Report.
|
|
1304
|
+
console.log('Installed SpecVerse skill → ' + targetDir);
|
|
1305
|
+
console.log(' SKILL.md + ' + refCopied + ' reference file(s) + ' + workflowCount + ' workflow(s)');
|
|
1306
|
+
if (!options.global && !options.target) {
|
|
1307
|
+
console.log('');
|
|
1308
|
+
console.log('Tip: use --global to install to ~/.claude/skills/ for cross-project use.');
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
function buildWorkflowMarkdown(parsed: any): string {
|
|
1312
|
+
const parts: string[] = [];
|
|
1313
|
+
parts.push('# SpecVerse workflow: ' + parsed.name);
|
|
1314
|
+
parts.push('');
|
|
1315
|
+
if (parsed.description) {
|
|
1316
|
+
parts.push('> ' + parsed.description);
|
|
1317
|
+
parts.push('');
|
|
1318
|
+
}
|
|
1319
|
+
const vars = Array.isArray(parsed?.user?.variables) ? parsed.user.variables : [];
|
|
1320
|
+
if (vars.length > 0) {
|
|
1321
|
+
parts.push('## Inputs');
|
|
1322
|
+
parts.push('');
|
|
1323
|
+
parts.push('| Variable | Required | Description |');
|
|
1324
|
+
parts.push('|---|---|---|');
|
|
1325
|
+
for (const v of vars) {
|
|
1326
|
+
const req = v.required === false ? 'no' : 'yes';
|
|
1327
|
+
const desc = (v.description || '').replace(/\\|/g, '\\\\|');
|
|
1328
|
+
parts.push('| \`' + v.name + '\` | ' + req + ' | ' + desc + ' |');
|
|
1329
|
+
}
|
|
1330
|
+
parts.push('');
|
|
1331
|
+
}
|
|
1332
|
+
if (parsed?.system?.role) {
|
|
1333
|
+
parts.push('## Role');
|
|
1334
|
+
parts.push('');
|
|
1335
|
+
parts.push(String(parsed.system.role).trim());
|
|
1336
|
+
parts.push('');
|
|
1337
|
+
}
|
|
1338
|
+
if (parsed?.system?.context) {
|
|
1339
|
+
parts.push('## Instructions');
|
|
1340
|
+
parts.push('');
|
|
1341
|
+
parts.push(String(parsed.system.context).trim());
|
|
1342
|
+
parts.push('');
|
|
1343
|
+
}
|
|
1344
|
+
if (parsed?.user?.template) {
|
|
1345
|
+
parts.push('## Task template');
|
|
1346
|
+
parts.push('');
|
|
1347
|
+
parts.push('When invoking this workflow, fill the variables above into the template below:');
|
|
1348
|
+
parts.push('');
|
|
1349
|
+
parts.push('\`\`\`');
|
|
1350
|
+
parts.push(String(parsed.user.template).trim());
|
|
1351
|
+
parts.push('\`\`\`');
|
|
1352
|
+
parts.push('');
|
|
1353
|
+
}
|
|
1354
|
+
return parts.join('\\n');
|
|
1355
|
+
}`
|
|
1356
|
+
},
|
|
1130
1357
|
};
|
|
1131
1358
|
|
|
1132
1359
|
function generateLeafCommand(
|