@tpitre/story-ui 4.12.1 → 4.13.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/dist/cli/generateRegistry.d.ts +23 -0
- package/dist/cli/generateRegistry.d.ts.map +1 -0
- package/dist/cli/generateRegistry.js +155 -0
- package/dist/cli/index.js +18 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +115 -4
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +26 -0
- package/dist/mcp-server/index.js +86 -1
- package/dist/mcp-server/routes/canvasGenerate.d.ts +25 -0
- package/dist/mcp-server/routes/canvasGenerate.d.ts.map +1 -0
- package/dist/mcp-server/routes/canvasGenerate.js +268 -0
- package/dist/mcp-server/routes/canvasIntent.d.ts +15 -0
- package/dist/mcp-server/routes/canvasIntent.d.ts.map +1 -0
- package/dist/mcp-server/routes/canvasIntent.js +553 -0
- package/dist/mcp-server/routes/canvasPreview.d.ts +14 -0
- package/dist/mcp-server/routes/canvasPreview.d.ts.map +1 -0
- package/dist/mcp-server/routes/canvasPreview.js +25 -0
- package/dist/mcp-server/routes/canvasSave.d.ts +13 -0
- package/dist/mcp-server/routes/canvasSave.d.ts.map +1 -0
- package/dist/mcp-server/routes/canvasSave.js +273 -0
- package/dist/mcp-server/routes/convertToStory.d.ts +17 -0
- package/dist/mcp-server/routes/convertToStory.d.ts.map +1 -0
- package/dist/mcp-server/routes/convertToStory.js +730 -0
- package/dist/mcp-server/routes/generateStory.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStory.js +17 -0
- package/dist/mcp-server/routes/generateStoryStream.d.ts.map +1 -1
- package/dist/mcp-server/routes/generateStoryStream.js +38 -2
- package/dist/mcp-server/routes/manifest.d.ts +19 -0
- package/dist/mcp-server/routes/manifest.d.ts.map +1 -0
- package/dist/mcp-server/routes/manifest.js +100 -0
- package/dist/mcp-server/routes/voiceRender.d.ts +19 -0
- package/dist/mcp-server/routes/voiceRender.d.ts.map +1 -0
- package/dist/mcp-server/routes/voiceRender.js +329 -0
- package/dist/story-generator/manifestManager.d.ts +105 -0
- package/dist/story-generator/manifestManager.d.ts.map +1 -0
- package/dist/story-generator/manifestManager.js +265 -0
- package/dist/templates/StoryUI/StoryUIPanel.css +732 -0
- package/dist/templates/StoryUI/StoryUIPanel.d.ts.map +1 -1
- package/dist/templates/StoryUI/StoryUIPanel.js +399 -50
- package/dist/templates/StoryUI/StoryUIPanel.tsx +2509 -0
- package/dist/templates/StoryUI/index.tsx +2 -0
- package/dist/templates/StoryUI/voice/VoiceCanvas.d.ts +15 -0
- package/dist/templates/StoryUI/voice/VoiceCanvas.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/VoiceCanvas.js +477 -0
- package/dist/templates/StoryUI/voice/VoiceCanvas.tsx +702 -0
- package/dist/templates/StoryUI/voice/VoiceControls.d.ts +12 -0
- package/dist/templates/StoryUI/voice/VoiceControls.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/VoiceControls.js +73 -0
- package/dist/templates/StoryUI/voice/VoiceControls.tsx +167 -0
- package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.d.ts +14 -0
- package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.js +90 -0
- package/dist/templates/StoryUI/voice/canvas/ComponentRenderer.tsx +168 -0
- package/dist/templates/StoryUI/voice/canvas/componentRegistry.d.ts +21 -0
- package/dist/templates/StoryUI/voice/canvas/componentRegistry.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/canvas/componentRegistry.js +24 -0
- package/dist/templates/StoryUI/voice/canvas/componentRegistry.ts +30 -0
- package/dist/templates/StoryUI/voice/canvas/operations.d.ts +8 -0
- package/dist/templates/StoryUI/voice/canvas/operations.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/canvas/operations.js +189 -0
- package/dist/templates/StoryUI/voice/canvas/operations.ts +233 -0
- package/dist/templates/StoryUI/voice/canvas/types.d.ts +89 -0
- package/dist/templates/StoryUI/voice/canvas/types.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/canvas/types.js +2 -0
- package/dist/templates/StoryUI/voice/canvas/types.ts +106 -0
- package/dist/templates/StoryUI/voice/types.d.ts +83 -0
- package/dist/templates/StoryUI/voice/types.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/types.js +2 -0
- package/dist/templates/StoryUI/voice/types.ts +114 -0
- package/dist/templates/StoryUI/voice/useVoiceInput.d.ts +3 -0
- package/dist/templates/StoryUI/voice/useVoiceInput.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/useVoiceInput.js +182 -0
- package/dist/templates/StoryUI/voice/useVoiceInput.ts +224 -0
- package/dist/templates/StoryUI/voice/voiceCommands.d.ts +8 -0
- package/dist/templates/StoryUI/voice/voiceCommands.d.ts.map +1 -0
- package/dist/templates/StoryUI/voice/voiceCommands.js +46 -0
- package/dist/templates/StoryUI/voice/voiceCommands.ts +54 -0
- package/package.json +4 -2
- package/templates/StoryUI/StoryUIPanel.css +732 -0
- package/templates/StoryUI/StoryUIPanel.tsx +423 -42
- package/templates/StoryUI/voice/VoiceCanvas.tsx +702 -0
- package/templates/StoryUI/voice/VoiceControls.tsx +167 -0
- package/templates/StoryUI/voice/canvas/ComponentRenderer.tsx +168 -0
- package/templates/StoryUI/voice/canvas/componentRegistry.ts +30 -0
- package/templates/StoryUI/voice/canvas/operations.ts +233 -0
- package/templates/StoryUI/voice/canvas/types.ts +106 -0
- package/templates/StoryUI/voice/types.ts +114 -0
- package/templates/StoryUI/voice/useVoiceInput.ts +224 -0
- package/templates/StoryUI/voice/voiceCommands.ts +54 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Registry Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates a `componentRegistry.ts` file that maps component names to
|
|
5
|
+
* actual React/Vue/etc imports for use by the Voice Canvas ComponentRenderer.
|
|
6
|
+
*
|
|
7
|
+
* Design-system agnostic — uses existing component discovery to find
|
|
8
|
+
* components from npm packages, local directories, and custom elements.
|
|
9
|
+
*
|
|
10
|
+
* Called during `npx story-ui init` and can be re-run with `npx story-ui registry`.
|
|
11
|
+
*/
|
|
12
|
+
export interface RegistryGeneratorOptions {
|
|
13
|
+
/** Working directory (defaults to cwd) */
|
|
14
|
+
cwd?: string;
|
|
15
|
+
/** Output path relative to cwd (defaults to src/stories/StoryUI/voice/canvas/) */
|
|
16
|
+
outputDir?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate the component registry file using project's discovered components.
|
|
20
|
+
* Returns the path to the generated file.
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateComponentRegistry(options?: RegistryGeneratorOptions): Promise<string>;
|
|
23
|
+
//# sourceMappingURL=generateRegistry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateRegistry.d.ts","sourceRoot":"","sources":["../../cli/generateRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC,CAgDvG"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Registry Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates a `componentRegistry.ts` file that maps component names to
|
|
5
|
+
* actual React/Vue/etc imports for use by the Voice Canvas ComponentRenderer.
|
|
6
|
+
*
|
|
7
|
+
* Design-system agnostic — uses existing component discovery to find
|
|
8
|
+
* components from npm packages, local directories, and custom elements.
|
|
9
|
+
*
|
|
10
|
+
* Called during `npx story-ui init` and can be re-run with `npx story-ui registry`.
|
|
11
|
+
*/
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import { loadUserConfig } from '../story-generator/configLoader.js';
|
|
15
|
+
import { EnhancedComponentDiscovery } from '../story-generator/enhancedComponentDiscovery.js';
|
|
16
|
+
/**
|
|
17
|
+
* Generate the component registry file using project's discovered components.
|
|
18
|
+
* Returns the path to the generated file.
|
|
19
|
+
*/
|
|
20
|
+
export async function generateComponentRegistry(options = {}) {
|
|
21
|
+
const cwd = options.cwd || process.cwd();
|
|
22
|
+
// loadUserConfig reads from cwd — ensure we're in the right directory
|
|
23
|
+
const originalCwd = process.cwd();
|
|
24
|
+
if (cwd !== originalCwd)
|
|
25
|
+
process.chdir(cwd);
|
|
26
|
+
const config = loadUserConfig();
|
|
27
|
+
if (cwd !== originalCwd)
|
|
28
|
+
process.chdir(originalCwd);
|
|
29
|
+
// Discover components using the existing discovery system
|
|
30
|
+
const discovery = new EnhancedComponentDiscovery(config);
|
|
31
|
+
const components = await discovery.discoverAll();
|
|
32
|
+
const componentNames = components.map(c => c.name).sort();
|
|
33
|
+
if (componentNames.length === 0) {
|
|
34
|
+
console.warn('⚠️ No components discovered — registry will be empty');
|
|
35
|
+
}
|
|
36
|
+
const importPath = config.importPath || '@mantine/core';
|
|
37
|
+
const framework = config.componentFramework || 'react';
|
|
38
|
+
const importStyle = config.importStyle || 'barrel';
|
|
39
|
+
// Determine output directory
|
|
40
|
+
const outputDir = options.outputDir
|
|
41
|
+
? path.resolve(cwd, options.outputDir)
|
|
42
|
+
: path.resolve(cwd, 'src/stories/StoryUI/voice/canvas');
|
|
43
|
+
if (!fs.existsSync(outputDir)) {
|
|
44
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
const outputPath = path.join(outputDir, 'componentRegistry.ts');
|
|
47
|
+
// Generate the file content
|
|
48
|
+
let code;
|
|
49
|
+
if (framework === 'react') {
|
|
50
|
+
code = generateReactRegistry(componentNames, importPath, importStyle);
|
|
51
|
+
}
|
|
52
|
+
else if (framework === 'vue') {
|
|
53
|
+
code = generateVueRegistry(componentNames, importPath, importStyle);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Fallback: generic registry with dynamic imports note
|
|
57
|
+
code = generateGenericRegistry(componentNames, importPath, framework);
|
|
58
|
+
}
|
|
59
|
+
fs.writeFileSync(outputPath, code, 'utf-8');
|
|
60
|
+
console.log(`✅ Component registry generated: ${path.relative(cwd, outputPath)} (${componentNames.length} components)`);
|
|
61
|
+
return outputPath;
|
|
62
|
+
}
|
|
63
|
+
// ── React registry generator ────────────────────────────────
|
|
64
|
+
function generateReactRegistry(names, importPath, importStyle) {
|
|
65
|
+
// Separate parent components from sub-components (e.g., "Card.Section")
|
|
66
|
+
const topLevel = names.filter(n => !n.includes('.'));
|
|
67
|
+
const subComponents = names.filter(n => n.includes('.'));
|
|
68
|
+
// For barrel imports, import all top-level from one path
|
|
69
|
+
// For individual imports, import each from its own path
|
|
70
|
+
let imports;
|
|
71
|
+
if (importStyle === 'individual') {
|
|
72
|
+
imports = topLevel.map(name => `import { ${name} } from '${importPath}/${name}';`).join('\n');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Barrel import — single line
|
|
76
|
+
imports = `import {\n${topLevel.map(n => ` ${n},`).join('\n')}\n} from '${importPath}';`;
|
|
77
|
+
}
|
|
78
|
+
// Build registry entries
|
|
79
|
+
const entries = topLevel.map(name => ` '${name}': ${name},`);
|
|
80
|
+
// Sub-components map automatically via dot-notation in ComponentRenderer
|
|
81
|
+
// e.g., "Card.Section" resolves to Card.Section at runtime
|
|
82
|
+
// But we still add them for explicit lookup
|
|
83
|
+
for (const sub of subComponents) {
|
|
84
|
+
const [parent, child] = sub.split('.');
|
|
85
|
+
entries.push(` '${sub}': (${parent} as any).${child},`);
|
|
86
|
+
}
|
|
87
|
+
return `/**
|
|
88
|
+
* Auto-generated component registry for Voice Canvas
|
|
89
|
+
* Source: ${importPath}
|
|
90
|
+
* Components: ${names.length}
|
|
91
|
+
*
|
|
92
|
+
* DO NOT EDIT — regenerate with: npx story-ui registry
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
${imports}
|
|
96
|
+
import type { ComponentRegistry } from './ComponentRenderer';
|
|
97
|
+
|
|
98
|
+
export const registry: ComponentRegistry = {
|
|
99
|
+
${entries.join('\n')}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default registry;
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
// ── Vue registry generator ──────────────────────────────────
|
|
106
|
+
function generateVueRegistry(names, importPath, importStyle) {
|
|
107
|
+
const topLevel = names.filter(n => !n.includes('.'));
|
|
108
|
+
let imports;
|
|
109
|
+
if (importStyle === 'individual') {
|
|
110
|
+
imports = topLevel.map(name => `import { ${name} } from '${importPath}/${name}';`).join('\n');
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
imports = `import {\n${topLevel.map(n => ` ${n},`).join('\n')}\n} from '${importPath}';`;
|
|
114
|
+
}
|
|
115
|
+
const entries = topLevel.map(name => ` '${name}': ${name},`);
|
|
116
|
+
return `/**
|
|
117
|
+
* Auto-generated component registry for Voice Canvas (Vue)
|
|
118
|
+
* Source: ${importPath}
|
|
119
|
+
* Components: ${names.length}
|
|
120
|
+
*
|
|
121
|
+
* DO NOT EDIT — regenerate with: npx story-ui registry
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
${imports}
|
|
125
|
+
|
|
126
|
+
export const registry: Record<string, any> = {
|
|
127
|
+
${entries.join('\n')}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export default registry;
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
// ── Generic fallback ────────────────────────────────────────
|
|
134
|
+
function generateGenericRegistry(names, importPath, framework) {
|
|
135
|
+
return `/**
|
|
136
|
+
* Auto-generated component registry for Voice Canvas (${framework})
|
|
137
|
+
* Source: ${importPath}
|
|
138
|
+
* Components: ${names.length}
|
|
139
|
+
*
|
|
140
|
+
* NOTE: This is a placeholder registry for ${framework}.
|
|
141
|
+
* You may need to customize imports for your framework.
|
|
142
|
+
*
|
|
143
|
+
* DO NOT EDIT — regenerate with: npx story-ui registry
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
// TODO: Add imports for ${framework} components from '${importPath}'
|
|
147
|
+
// ${names.map(n => `// import { ${n} } from '${importPath}';`).join('\n')}
|
|
148
|
+
|
|
149
|
+
export const registry: Record<string, any> = {
|
|
150
|
+
${names.map(n => ` // '${n}': ${n},`).join('\n')}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export default registry;
|
|
154
|
+
`;
|
|
155
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -10,9 +10,24 @@ import { updateCommand, statusCommand } from './update.js';
|
|
|
10
10
|
import net from 'net';
|
|
11
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
12
|
const __dirname = path.dirname(__filename);
|
|
13
|
-
// Read version from package.json
|
|
14
|
-
const
|
|
15
|
-
|
|
13
|
+
// Read version from package.json (try both src/cli and dist/cli paths)
|
|
14
|
+
const packageJsonPaths = [
|
|
15
|
+
path.resolve(__dirname, '..', 'package.json'), // From src/cli
|
|
16
|
+
path.resolve(__dirname, '..', '..', 'package.json'), // From dist/cli
|
|
17
|
+
];
|
|
18
|
+
let packageVersion = 'unknown';
|
|
19
|
+
for (const p of packageJsonPaths) {
|
|
20
|
+
if (fs.existsSync(p)) {
|
|
21
|
+
try {
|
|
22
|
+
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
|
|
23
|
+
if (pkg.version) {
|
|
24
|
+
packageVersion = pkg.version;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch { /* skip */ }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
16
31
|
const program = new Command();
|
|
17
32
|
program
|
|
18
33
|
.name('story-ui')
|
package/dist/cli/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAmDA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../cli/setup.ts"],"names":[],"mappings":"AAmDA;;GAEG;AACH,wBAAgB,iCAAiC,SA8ChD;AAoXD,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC7C,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,YAAiB,iBA6/B5D"}
|
package/dist/cli/setup.js
CHANGED
|
@@ -128,10 +128,19 @@ function setupStorybookPreview(designSystem) {
|
|
|
128
128
|
const designSystemConfigs = {
|
|
129
129
|
chakra: {
|
|
130
130
|
imports: [
|
|
131
|
+
"import React from 'react'",
|
|
131
132
|
"import type { Preview } from '@storybook/react-vite'",
|
|
132
|
-
"import
|
|
133
|
-
"import React from 'react'"
|
|
133
|
+
"import * as ChakraUI from '@chakra-ui/react'",
|
|
134
134
|
],
|
|
135
|
+
globals: `
|
|
136
|
+
const { ChakraProvider, defaultSystem } = ChakraUI;
|
|
137
|
+
|
|
138
|
+
// Expose all Chakra components for Voice Canvas live preview.
|
|
139
|
+
// Voice Canvas uses these globals to render components without import statements.
|
|
140
|
+
(window as any).__STORY_UI_DESIGN_SYSTEM__ = ChakraUI;
|
|
141
|
+
(window as any).__STORY_UI_CANVAS_PROVIDER__ = ({ children }: { children: React.ReactNode }) => (
|
|
142
|
+
<ChakraProvider value={defaultSystem}>{children}</ChakraProvider>
|
|
143
|
+
);`,
|
|
135
144
|
decorator: `(Story) => (
|
|
136
145
|
<ChakraProvider value={defaultSystem}>
|
|
137
146
|
<Story />
|
|
@@ -140,11 +149,20 @@ function setupStorybookPreview(designSystem) {
|
|
|
140
149
|
},
|
|
141
150
|
mantine: {
|
|
142
151
|
imports: [
|
|
152
|
+
"import React from 'react'",
|
|
143
153
|
"import type { Preview } from '@storybook/react-vite'",
|
|
144
|
-
"import
|
|
154
|
+
"import * as MantineCore from '@mantine/core'",
|
|
145
155
|
"import '@mantine/core/styles.css'",
|
|
146
|
-
"import React from 'react'"
|
|
147
156
|
],
|
|
157
|
+
globals: `
|
|
158
|
+
const { MantineProvider } = MantineCore;
|
|
159
|
+
|
|
160
|
+
// Expose all Mantine components for Voice Canvas live preview.
|
|
161
|
+
// Voice Canvas uses these globals to render components without import statements.
|
|
162
|
+
(window as any).__STORY_UI_DESIGN_SYSTEM__ = MantineCore;
|
|
163
|
+
(window as any).__STORY_UI_CANVAS_PROVIDER__ = ({ children }: { children: React.ReactNode }) => (
|
|
164
|
+
<MantineProvider>{children}</MantineProvider>
|
|
165
|
+
);`,
|
|
148
166
|
decorator: `(Story) => (
|
|
149
167
|
<MantineProvider>
|
|
150
168
|
<Story />
|
|
@@ -157,6 +175,7 @@ function setupStorybookPreview(designSystem) {
|
|
|
157
175
|
return;
|
|
158
176
|
// Create the preview content
|
|
159
177
|
const previewContent = `${config.imports.join('\n')}
|
|
178
|
+
${config.globals || ''}
|
|
160
179
|
|
|
161
180
|
const preview: Preview = {
|
|
162
181
|
parameters: {
|
|
@@ -917,6 +936,8 @@ Material UI (MUI) is a React component library implementing Material Design.
|
|
|
917
936
|
// Copy component files
|
|
918
937
|
const templatesDir = path.resolve(__dirname, '../../templates/StoryUI');
|
|
919
938
|
const componentFiles = ['StoryUIPanel.tsx', 'StoryUIPanel.mdx', 'StoryUIPanel.css'];
|
|
939
|
+
// Voice Canvas files (subdirectory)
|
|
940
|
+
const voiceFiles = ['VoiceCanvas.tsx', 'VoiceControls.tsx', 'useVoiceInput.ts', 'voiceCommands.ts', 'types.ts'];
|
|
920
941
|
console.log(chalk.blue('\n📦 Installing Story UI component...'));
|
|
921
942
|
for (const file of componentFiles) {
|
|
922
943
|
const sourcePath = path.join(templatesDir, file);
|
|
@@ -934,6 +955,96 @@ Material UI (MUI) is a React component library implementing Material Design.
|
|
|
934
955
|
console.warn(chalk.yellow(`⚠️ Template file not found: ${file}`));
|
|
935
956
|
}
|
|
936
957
|
}
|
|
958
|
+
// Copy Voice Canvas files
|
|
959
|
+
const voiceSourceDir = path.join(templatesDir, 'voice');
|
|
960
|
+
const voiceTargetDir = path.join(storyUITargetDir, 'voice');
|
|
961
|
+
if (fs.existsSync(voiceSourceDir)) {
|
|
962
|
+
if (!fs.existsSync(voiceTargetDir)) {
|
|
963
|
+
fs.mkdirSync(voiceTargetDir, { recursive: true });
|
|
964
|
+
}
|
|
965
|
+
for (const file of voiceFiles) {
|
|
966
|
+
const sourcePath = path.join(voiceSourceDir, file);
|
|
967
|
+
const targetPath = path.join(voiceTargetDir, file);
|
|
968
|
+
if (fs.existsSync(sourcePath)) {
|
|
969
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
970
|
+
console.log(chalk.green(`✅ Copied voice/${file}`));
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
// Generate component registry for Voice Canvas with static design system import
|
|
975
|
+
// Vite requires static imports — bare specifiers can't be resolved at runtime
|
|
976
|
+
const canvasTargetDir = path.join(voiceTargetDir, 'canvas');
|
|
977
|
+
if (!fs.existsSync(canvasTargetDir)) {
|
|
978
|
+
fs.mkdirSync(canvasTargetDir, { recursive: true });
|
|
979
|
+
}
|
|
980
|
+
// Copy canvas template files (types.ts, operations.ts, ComponentRenderer.tsx)
|
|
981
|
+
const canvasSourceDir = path.join(voiceSourceDir, 'canvas');
|
|
982
|
+
if (fs.existsSync(canvasSourceDir)) {
|
|
983
|
+
for (const file of fs.readdirSync(canvasSourceDir)) {
|
|
984
|
+
if (file === 'componentRegistry.ts')
|
|
985
|
+
continue; // generated below
|
|
986
|
+
const src = path.join(canvasSourceDir, file);
|
|
987
|
+
const dst = path.join(canvasTargetDir, file);
|
|
988
|
+
if (fs.statSync(src).isFile()) {
|
|
989
|
+
fs.copyFileSync(src, dst);
|
|
990
|
+
console.log(chalk.green(`✅ Copied voice/canvas/${file}`));
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
// Generate the registry with a lazy async import of the design system.
|
|
995
|
+
// Uses a literal string in import() so Vite resolves it at build time,
|
|
996
|
+
// but execution is deferred until loadRegistry() is called — avoiding
|
|
997
|
+
// module-level side effects that can crash the docs page.
|
|
998
|
+
if (config.importPath && config.importStyle !== 'individual') {
|
|
999
|
+
const registryContent = `/**
|
|
1000
|
+
* Component registry for Voice Canvas — lazy-loaded from design system.
|
|
1001
|
+
*
|
|
1002
|
+
* Uses dynamic import('${config.importPath}') with a literal string so Vite
|
|
1003
|
+
* resolves it at build time, but the import only executes when loadRegistry()
|
|
1004
|
+
* is called (not at module evaluation time). This prevents crashes from
|
|
1005
|
+
* module-level side effects.
|
|
1006
|
+
*
|
|
1007
|
+
* Generated by story-ui init. Regenerate with: npx story-ui registry
|
|
1008
|
+
*/
|
|
1009
|
+
|
|
1010
|
+
export const registry: Record<string, any> = {};
|
|
1011
|
+
|
|
1012
|
+
let _loaded = false;
|
|
1013
|
+
|
|
1014
|
+
export async function loadRegistry(): Promise<Record<string, any>> {
|
|
1015
|
+
if (_loaded) return registry;
|
|
1016
|
+
|
|
1017
|
+
try {
|
|
1018
|
+
const mod = await import('${config.importPath}');
|
|
1019
|
+
|
|
1020
|
+
for (const [key, value] of Object.entries(mod)) {
|
|
1021
|
+
if (/^[A-Z]/.test(key) && (typeof value === 'function' || typeof value === 'object')) {
|
|
1022
|
+
registry[key] = value;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
_loaded = true;
|
|
1027
|
+
console.log(\\\`[componentRegistry] Loaded \\\${Object.keys(registry).length} components from ${config.importPath}\\\`);
|
|
1028
|
+
} catch (err) {
|
|
1029
|
+
console.error('[componentRegistry] Failed to load design system:', err);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return registry;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
export default registry;
|
|
1036
|
+
`;
|
|
1037
|
+
fs.writeFileSync(path.join(canvasTargetDir, 'componentRegistry.ts'), registryContent);
|
|
1038
|
+
console.log(chalk.green(`✅ Generated voice/canvas/componentRegistry.ts with ${config.importPath} imports`));
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
// For individual import style or unknown, copy the placeholder
|
|
1042
|
+
const placeholderSrc = path.join(canvasSourceDir, 'componentRegistry.ts');
|
|
1043
|
+
if (fs.existsSync(placeholderSrc)) {
|
|
1044
|
+
fs.copyFileSync(placeholderSrc, path.join(canvasTargetDir, 'componentRegistry.ts'));
|
|
1045
|
+
}
|
|
1046
|
+
console.log(chalk.yellow(`⚠️ Voice Canvas registry is empty — populate voice/canvas/componentRegistry.ts manually`));
|
|
1047
|
+
}
|
|
937
1048
|
// Configure Storybook bundler for StoryUIPanel requirements
|
|
938
1049
|
console.log(chalk.blue('\n🔧 Configuring Storybook for Story UI...'));
|
|
939
1050
|
const mainConfigPath = path.join(process.cwd(), '.storybook', 'main.ts');
|
package/dist/cli/update.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../cli/update.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../cli/update.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0UD;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkItF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CA+BpC"}
|
package/dist/cli/update.js
CHANGED
|
@@ -26,6 +26,32 @@ const MANAGED_FILES = [
|
|
|
26
26
|
source: 'templates/StoryUI/index.tsx',
|
|
27
27
|
target: 'src/stories/StoryUI/index.tsx',
|
|
28
28
|
description: 'Panel registration'
|
|
29
|
+
},
|
|
30
|
+
// Voice Canvas files
|
|
31
|
+
{
|
|
32
|
+
source: 'templates/StoryUI/voice/VoiceCanvas.tsx',
|
|
33
|
+
target: 'src/stories/StoryUI/voice/VoiceCanvas.tsx',
|
|
34
|
+
description: 'Voice Canvas component'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
source: 'templates/StoryUI/voice/VoiceControls.tsx',
|
|
38
|
+
target: 'src/stories/StoryUI/voice/VoiceControls.tsx',
|
|
39
|
+
description: 'Voice control UI components'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
source: 'templates/StoryUI/voice/useVoiceInput.ts',
|
|
43
|
+
target: 'src/stories/StoryUI/voice/useVoiceInput.ts',
|
|
44
|
+
description: 'Voice input hook'
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
source: 'templates/StoryUI/voice/voiceCommands.ts',
|
|
48
|
+
target: 'src/stories/StoryUI/voice/voiceCommands.ts',
|
|
49
|
+
description: 'Voice command definitions'
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
source: 'templates/StoryUI/voice/types.ts',
|
|
53
|
+
target: 'src/stories/StoryUI/voice/types.ts',
|
|
54
|
+
description: 'Voice module type definitions'
|
|
29
55
|
}
|
|
30
56
|
];
|
|
31
57
|
// Files that should NEVER be modified by update
|
package/dist/mcp-server/index.js
CHANGED
|
@@ -22,14 +22,23 @@ import { UrlRedirectService } from '../story-generator/urlRedirectService.js';
|
|
|
22
22
|
import { getProviders, getModels, configureProviderRoute, validateApiKey, setDefaultProvider, setModel, getUISettings, applyUISettings, getSettingsConfig } from './routes/providers.js';
|
|
23
23
|
import { listFrameworks, detectCurrentFramework, getFrameworkDetails, validateStoryForFramework, postProcessStoryForFramework, } from './routes/frameworks.js';
|
|
24
24
|
import mcpRemoteRouter from './routes/mcpRemote.js';
|
|
25
|
+
// Voice Canvas endpoints
|
|
26
|
+
import { canvasIntentHandler, warmCanvasComponentCache } from './routes/canvasIntent.js';
|
|
27
|
+
import { canvasSaveHandler } from './routes/canvasSave.js';
|
|
28
|
+
import { canvasGenerateHandler, ensureVoiceCanvasStory } from './routes/canvasGenerate.js';
|
|
29
|
+
import { canvasPreviewHandler } from './routes/canvasPreview.js';
|
|
25
30
|
import { getAdapterRegistry } from '../story-generator/framework-adapters/index.js';
|
|
31
|
+
// Manifest — story ↔ chat source of truth
|
|
32
|
+
import { manifestGetHandler, manifestPatchHandler, manifestDeleteHandler, manifestReconcileHandler, manifestPollHandler, } from './routes/manifest.js';
|
|
33
|
+
import { getManifestManager } from '../story-generator/manifestManager.js';
|
|
26
34
|
// Supported story file extensions for all frameworks
|
|
27
35
|
const STORY_EXTENSIONS = ['.stories.tsx', '.stories.ts', '.stories.svelte', '.stories.js'];
|
|
28
36
|
/**
|
|
29
37
|
* Check if a file is a story file (supports all framework extensions)
|
|
30
38
|
*/
|
|
31
39
|
function isStoryFile(filename) {
|
|
32
|
-
return STORY_EXTENSIONS.some(ext => filename.endsWith(ext))
|
|
40
|
+
return STORY_EXTENSIONS.some(ext => filename.endsWith(ext))
|
|
41
|
+
&& !filename.startsWith('voice-canvas'); // scratchpad — excluded from story lists
|
|
33
42
|
}
|
|
34
43
|
/**
|
|
35
44
|
* Remove story extension from filename to get base name
|
|
@@ -99,6 +108,27 @@ app.get('/mcp/props', getProps);
|
|
|
99
108
|
app.post('/mcp/claude', claudeProxy);
|
|
100
109
|
app.post('/mcp/generate-story', generateStoryFromPrompt);
|
|
101
110
|
app.post('/mcp/generate-story-stream', generateStoryFromPromptStream);
|
|
111
|
+
// Voice Canvas endpoints
|
|
112
|
+
app.post('/mcp/canvas-generate', canvasGenerateHandler); // generate + write voice-canvas.stories.tsx
|
|
113
|
+
app.post('/mcp/canvas-preview', canvasPreviewHandler); // undo/redo: rewrite voice-canvas.stories.tsx
|
|
114
|
+
app.post('/mcp/canvas-save', canvasSaveHandler); // save canvas to named .stories.tsx
|
|
115
|
+
app.post('/mcp/canvas-intent', canvasIntentHandler); // legacy (kept for compatibility)
|
|
116
|
+
// Manifest — story ↔ chat source of truth
|
|
117
|
+
// NOTE: /reconcile must be registered BEFORE /:fileName to avoid route conflict
|
|
118
|
+
app.get('/story-ui/manifest/poll', manifestPollHandler);
|
|
119
|
+
app.post('/story-ui/manifest/reconcile', manifestReconcileHandler);
|
|
120
|
+
app.get('/story-ui/manifest', manifestGetHandler);
|
|
121
|
+
app.patch('/story-ui/manifest/:fileName', manifestPatchHandler);
|
|
122
|
+
app.delete('/story-ui/manifest/:fileName', manifestDeleteHandler);
|
|
123
|
+
// Expose design-system config for auto-registry loading
|
|
124
|
+
app.get('/mcp/canvas-config', (_req, res) => {
|
|
125
|
+
res.json({
|
|
126
|
+
importPath: config.importPath || '',
|
|
127
|
+
importStyle: config.importStyle || 'barrel',
|
|
128
|
+
componentPrefix: config.componentPrefix || '',
|
|
129
|
+
componentFramework: config.componentFramework || 'react',
|
|
130
|
+
});
|
|
131
|
+
});
|
|
102
132
|
// LLM Provider management routes
|
|
103
133
|
app.get('/mcp/providers', getProviders);
|
|
104
134
|
app.get('/mcp/providers/models', getModels);
|
|
@@ -292,6 +322,7 @@ app.delete('/mcp/stories/:storyId', async (req, res) => {
|
|
|
292
322
|
// Proxy routes for frontend compatibility (maps /story-ui/ to /mcp/)
|
|
293
323
|
app.post('/story-ui/generate', generateStoryFromPrompt);
|
|
294
324
|
app.post('/story-ui/generate-stream', generateStoryFromPromptStream);
|
|
325
|
+
// voice-render and convert-to-story aliases removed
|
|
295
326
|
app.post('/story-ui/claude', claudeProxy);
|
|
296
327
|
app.get('/story-ui/components', getComponents);
|
|
297
328
|
app.get('/story-ui/props', getProps);
|
|
@@ -428,6 +459,33 @@ app.post('/story-ui/stories', async (req, res) => {
|
|
|
428
459
|
return res.status(500).json({ error: 'Failed to save story' });
|
|
429
460
|
}
|
|
430
461
|
});
|
|
462
|
+
// Rename story title in file and manifest
|
|
463
|
+
app.patch('/story-ui/stories/:fileName/rename', async (req, res) => {
|
|
464
|
+
try {
|
|
465
|
+
const { fileName } = req.params;
|
|
466
|
+
const { title } = req.body;
|
|
467
|
+
if (!title || typeof title !== 'string' || !title.trim()) {
|
|
468
|
+
return res.status(400).json({ error: 'title is required' });
|
|
469
|
+
}
|
|
470
|
+
const newTitle = title.trim();
|
|
471
|
+
const storiesPath = config.generatedStoriesPath;
|
|
472
|
+
const filePath = safePath(storiesPath, fileName);
|
|
473
|
+
if (!filePath || !fs.existsSync(filePath)) {
|
|
474
|
+
return res.status(404).json({ error: 'Story not found' });
|
|
475
|
+
}
|
|
476
|
+
// Update the title string inside the file (replaces title: 'Generated/OldTitle')
|
|
477
|
+
let content = fs.readFileSync(filePath, 'utf-8');
|
|
478
|
+
content = content.replace(/(title:\s*['"`]Generated\/)[^'"`]*/, `$1${newTitle.replace(/'/g, "\\'")}`);
|
|
479
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
480
|
+
// Update manifest entry title
|
|
481
|
+
getManifestManager().upsert(fileName, { title: newTitle });
|
|
482
|
+
return res.json({ success: true, title: newTitle });
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
486
|
+
return res.status(500).json({ error: message });
|
|
487
|
+
}
|
|
488
|
+
});
|
|
431
489
|
// Delete story by ID (RESTful endpoint)
|
|
432
490
|
// Supports both fileName format (Button-a1b2c3d4.stories.tsx) and legacy storyId format (story-a1b2c3d4)
|
|
433
491
|
app.delete('/story-ui/stories/:id', async (req, res) => {
|
|
@@ -451,6 +509,7 @@ app.delete('/story-ui/stories/:id', async (req, res) => {
|
|
|
451
509
|
}
|
|
452
510
|
if (fs.existsSync(filePath)) {
|
|
453
511
|
fs.unlinkSync(filePath);
|
|
512
|
+
getManifestManager().delete(fileName);
|
|
454
513
|
console.log(`✅ Deleted story: ${filePath}`);
|
|
455
514
|
return res.json({ success: true, message: 'Story deleted successfully' });
|
|
456
515
|
}
|
|
@@ -464,6 +523,7 @@ app.delete('/story-ui/stories/:id', async (req, res) => {
|
|
|
464
523
|
if (matchingFile) {
|
|
465
524
|
const matchedFilePath = path.join(storiesPath, matchingFile);
|
|
466
525
|
fs.unlinkSync(matchedFilePath);
|
|
526
|
+
getManifestManager().delete(matchingFile);
|
|
467
527
|
console.log(`✅ Deleted story by hash match: ${matchedFilePath}`);
|
|
468
528
|
return res.json({ success: true, message: 'Story deleted successfully' });
|
|
469
529
|
}
|
|
@@ -602,6 +662,7 @@ app.delete('/story-ui/stories', async (req, res) => {
|
|
|
602
662
|
}
|
|
603
663
|
if (fs.existsSync(filePath)) {
|
|
604
664
|
fs.unlinkSync(filePath);
|
|
665
|
+
getManifestManager().delete(fileName);
|
|
605
666
|
console.log(`✅ Deleted story: ${filePath}`);
|
|
606
667
|
return res.json({ success: true, message: 'Story deleted successfully' });
|
|
607
668
|
}
|
|
@@ -617,6 +678,7 @@ app.delete('/story-ui/stories', async (req, res) => {
|
|
|
617
678
|
return res.status(400).json({ success: false, error: 'Invalid file path' });
|
|
618
679
|
}
|
|
619
680
|
fs.unlinkSync(filePath);
|
|
681
|
+
getManifestManager().delete(matchingFile);
|
|
620
682
|
console.log(`✅ Deleted story by hash match: ${filePath}`);
|
|
621
683
|
return res.json({ success: true, message: 'Story deleted successfully' });
|
|
622
684
|
}
|
|
@@ -632,12 +694,14 @@ app.delete('/story-ui/stories', async (req, res) => {
|
|
|
632
694
|
// Support all story file extensions
|
|
633
695
|
const storyFiles = files.filter(file => isStoryFile(file));
|
|
634
696
|
let deleted = 0;
|
|
697
|
+
const manifest = getManifestManager();
|
|
635
698
|
for (const file of storyFiles) {
|
|
636
699
|
try {
|
|
637
700
|
const fp = safePath(storiesPath, file);
|
|
638
701
|
if (!fp)
|
|
639
702
|
continue;
|
|
640
703
|
fs.unlinkSync(fp);
|
|
704
|
+
manifest.delete(file);
|
|
641
705
|
deleted++;
|
|
642
706
|
}
|
|
643
707
|
catch (err) {
|
|
@@ -819,6 +883,27 @@ if (storybookProxyEnabled) {
|
|
|
819
883
|
app.listen(PORT, () => {
|
|
820
884
|
console.error(`MCP server running on port ${PORT}`);
|
|
821
885
|
console.error(`Stories will be generated to: ${config.generatedStoriesPath}`);
|
|
886
|
+
// Pre-warm canvas component cache in background so first voice request is fast
|
|
887
|
+
warmCanvasComponentCache().catch(() => { });
|
|
888
|
+
// Ensure voice-canvas scratchpad story file exists before client polling starts.
|
|
889
|
+
// If it's missing, the first canvas generate creates it, triggering a false-positive
|
|
890
|
+
// "externally generated story" detection which reloads the page and kills Voice Canvas.
|
|
891
|
+
try {
|
|
892
|
+
ensureVoiceCanvasStory(config.generatedStoriesPath || './src/stories/generated/');
|
|
893
|
+
}
|
|
894
|
+
catch (err) {
|
|
895
|
+
console.error('[voice-canvas] Could not pre-create story template:', err);
|
|
896
|
+
}
|
|
897
|
+
// Initialize manifest manager (loads file, migrates from StoryTracker, reconciles)
|
|
898
|
+
setTimeout(() => {
|
|
899
|
+
try {
|
|
900
|
+
getManifestManager();
|
|
901
|
+
console.error('[manifest] Initialized and reconciled');
|
|
902
|
+
}
|
|
903
|
+
catch (err) {
|
|
904
|
+
console.error('[manifest] Init error:', err);
|
|
905
|
+
}
|
|
906
|
+
}, 500);
|
|
822
907
|
}).on('error', (err) => {
|
|
823
908
|
if (err.code === 'EADDRINUSE') {
|
|
824
909
|
console.error(`\n❌ Port ${PORT} is already in use!`);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canvas Generate Endpoint
|
|
3
|
+
*
|
|
4
|
+
* Generates a JSX component for the Voice Canvas preview.
|
|
5
|
+
* Uses the same quality pipeline as standard story generation.
|
|
6
|
+
* Writes a voice-canvas.stories.tsx file so the iframe renders with
|
|
7
|
+
* the full Storybook decorator chain (Provider, themes, etc.).
|
|
8
|
+
*
|
|
9
|
+
* Voice Canvas requires a React-based Storybook framework.
|
|
10
|
+
* Components come from window.__STORY_UI_DESIGN_SYSTEM__ set in .storybook/preview.tsx.
|
|
11
|
+
*
|
|
12
|
+
* POST /mcp/canvas-generate
|
|
13
|
+
* Body: { prompt, canvasCode?, provider, model, conversationHistory? }
|
|
14
|
+
* Returns: { canvasCode: string, storyId: string }
|
|
15
|
+
*/
|
|
16
|
+
import { Request, Response } from 'express';
|
|
17
|
+
export declare const VOICE_CANVAS_STORY_ID = "generated-voice-canvas--default";
|
|
18
|
+
export declare function ensureReactLive(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Write the static voice-canvas story template if it doesn't exist yet.
|
|
21
|
+
* Subsequent calls are no-ops — the file never changes after initial creation.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ensureVoiceCanvasStory(storiesDir: string): void;
|
|
24
|
+
export declare function canvasGenerateHandler(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
25
|
+
//# sourceMappingURL=canvasGenerate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvasGenerate.d.ts","sourceRoot":"","sources":["../../../mcp-server/routes/canvasGenerate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAW5C,eAAO,MAAM,qBAAqB,oCAAoC,CAAC;AAmIvE,wBAAgB,eAAe,IAAI,IAAI,CAuBtC;AAID;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAU/D;AAuBD,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,+CAwEtE"}
|