@kvasar/google-stitch 0.1.8 → 0.1.11
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/SKILL.md +80 -13
- package/src/services/stitch-mcp-client.ts +30 -7
- package/src/tools/apply_design_system.ts +59 -5
- package/src/tools/create_design_system.ts +140 -5
- package/src/tools/generate_screen_from_text_tool.ts +108 -84
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -56,7 +56,7 @@ If the user wants to start a new design workspace:
|
|
|
56
56
|
|
|
57
57
|
- `create_project`
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
Example prompts:
|
|
60
60
|
|
|
61
61
|
- create a new project
|
|
62
62
|
- start a new app design
|
|
@@ -65,8 +65,22 @@ Examples:
|
|
|
65
65
|
If the user wants existing project info:
|
|
66
66
|
|
|
67
67
|
- `get_project`
|
|
68
|
+
|
|
69
|
+
Example prompts:
|
|
70
|
+
|
|
71
|
+
- Get the details of project 4044680601076201931
|
|
72
|
+
- Show me the project info
|
|
73
|
+
- What’s in my project?
|
|
74
|
+
|
|
75
|
+
|
|
68
76
|
- `list_projects`
|
|
69
77
|
|
|
78
|
+
Example prompts:
|
|
79
|
+
|
|
80
|
+
- List all my Stitch projects
|
|
81
|
+
- Show me my projects
|
|
82
|
+
- List shared projects
|
|
83
|
+
|
|
70
84
|
---
|
|
71
85
|
|
|
72
86
|
### Screen generation
|
|
@@ -75,7 +89,7 @@ For new screens from prompts:
|
|
|
75
89
|
|
|
76
90
|
- `generate_screen_from_text`
|
|
77
91
|
|
|
78
|
-
|
|
92
|
+
Example prompts:
|
|
79
93
|
|
|
80
94
|
- create login page
|
|
81
95
|
- generate dashboard
|
|
@@ -86,14 +100,40 @@ Always extract:
|
|
|
86
100
|
|
|
87
101
|
- projectId
|
|
88
102
|
- prompt
|
|
89
|
-
- deviceType
|
|
90
|
-
-
|
|
103
|
+
- deviceType (optional)
|
|
104
|
+
- modelId (optional)
|
|
91
105
|
|
|
92
|
-
|
|
106
|
+
## Supported device types:
|
|
93
107
|
|
|
94
|
-
-
|
|
108
|
+
- MOBILE
|
|
109
|
+
- DESKTOP
|
|
110
|
+
- TABLET
|
|
111
|
+
- AGNOSTIC
|
|
95
112
|
|
|
96
|
-
|
|
113
|
+
### Preferred default:
|
|
114
|
+
|
|
115
|
+
- DESKTOP
|
|
116
|
+
|
|
117
|
+
#### Supported models:
|
|
118
|
+
|
|
119
|
+
- GEMINI_3_PRO
|
|
120
|
+
- GEMINI_3_FLASH
|
|
121
|
+
- GEMINI_3_1_PRO
|
|
122
|
+
|
|
123
|
+
#### Preferred default:
|
|
124
|
+
|
|
125
|
+
- GEMINI_3_1_PRO
|
|
126
|
+
|
|
127
|
+
Always structure the tool call as:
|
|
128
|
+
|
|
129
|
+
{
|
|
130
|
+
"projectId": "project-id",
|
|
131
|
+
"prompt": "Generate a modern SaaS dashboard with KPI cards and sidebar",
|
|
132
|
+
"deviceType": "DESKTOP",
|
|
133
|
+
"modelId": "GEMINI_3_1_PRO"
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Never call the tool with only a string prompt.
|
|
97
137
|
|
|
98
138
|
### Screen editing
|
|
99
139
|
|
|
@@ -101,7 +141,7 @@ For modifying existing screens:
|
|
|
101
141
|
|
|
102
142
|
- `edit_screens`
|
|
103
143
|
|
|
104
|
-
|
|
144
|
+
Example prompts:
|
|
105
145
|
|
|
106
146
|
- make button blue
|
|
107
147
|
- add navbar
|
|
@@ -135,17 +175,44 @@ Recommended defaults:
|
|
|
135
175
|
|
|
136
176
|
For brand consistency and theming:
|
|
137
177
|
|
|
178
|
+
|
|
179
|
+
|
|
138
180
|
- `create_design_system`
|
|
181
|
+
|
|
182
|
+
Example prompts:
|
|
183
|
+
|
|
184
|
+
- Create a dark mode design system with Inter font and round corners
|
|
185
|
+
- Set up a design system with blue as the primary color
|
|
186
|
+
- Create a brand identity with Geist font and minimal roundness
|
|
187
|
+
|
|
139
188
|
- `update_design_system`
|
|
189
|
+
|
|
190
|
+
Example prompts:
|
|
191
|
+
|
|
192
|
+
- Update the design system to use dark mode
|
|
193
|
+
- Change the font to Geist in our design system
|
|
194
|
+
- Update the roundness to fully rounded
|
|
195
|
+
|
|
196
|
+
|
|
140
197
|
- `list_design_systems`
|
|
198
|
+
|
|
199
|
+
Example prompts:
|
|
200
|
+
|
|
201
|
+
- List all design systems in project 12345
|
|
202
|
+
- Show me the available design systems
|
|
203
|
+
- What design systems do I have?
|
|
204
|
+
|
|
205
|
+
|
|
141
206
|
- `apply_design_system`
|
|
142
207
|
|
|
143
|
-
|
|
208
|
+
Applies a design system to one or more screens, modifying their appearance to match the system’s tokens (colors, fonts, shapes).
|
|
209
|
+
|
|
210
|
+
Example prompts:
|
|
211
|
+
|
|
212
|
+
- Apply the blue design system to all screens in project 12345
|
|
213
|
+
- Restyle these screens with the brand identity
|
|
214
|
+
- Use design system abc to update my screens
|
|
144
215
|
|
|
145
|
-
- create dark theme
|
|
146
|
-
- use Inter font
|
|
147
|
-
- rounded buttons
|
|
148
|
-
- apply brand colors
|
|
149
216
|
|
|
150
217
|
---
|
|
151
218
|
|
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
2
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
3
3
|
|
|
4
|
+
export type DeviceType =
|
|
5
|
+
| "DEVICE_TYPE_UNSPECIFIED"
|
|
6
|
+
| "MOBILE"
|
|
7
|
+
| "DESKTOP"
|
|
8
|
+
| "TABLET"
|
|
9
|
+
| "AGNOSTIC";
|
|
10
|
+
|
|
11
|
+
export type ModelId =
|
|
12
|
+
| "MODEL_ID_UNSPECIFIED"
|
|
13
|
+
| "GEMINI_3_PRO"
|
|
14
|
+
| "GEMINI_3_FLASH"
|
|
15
|
+
| "GEMINI_3_1_PRO";
|
|
16
|
+
|
|
4
17
|
export class StitchMCPClient {
|
|
5
18
|
private client: Client;
|
|
6
19
|
private transport: StreamableHTTPClientTransport;
|
|
@@ -41,12 +54,22 @@ export class StitchMCPClient {
|
|
|
41
54
|
});
|
|
42
55
|
}
|
|
43
56
|
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
async generateScreen(params: {
|
|
58
|
+
projectId: string;
|
|
59
|
+
prompt: string;
|
|
60
|
+
deviceType?: DeviceType;
|
|
61
|
+
modelId?: ModelId;
|
|
62
|
+
}) {
|
|
63
|
+
await this.connect();
|
|
46
64
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
return this.client.callTool({
|
|
66
|
+
name: "generate_screen_from_text",
|
|
67
|
+
arguments: {
|
|
68
|
+
projectId: params.projectId,
|
|
69
|
+
prompt: params.prompt,
|
|
70
|
+
deviceType: params.deviceType,
|
|
71
|
+
modelId: params.modelId,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
52
75
|
}
|
|
@@ -1,7 +1,61 @@
|
|
|
1
|
-
|
|
1
|
+
type SelectedScreenInstance = {
|
|
2
|
+
id: string;
|
|
3
|
+
sourceScreen: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type ApplyDesignSystemParams = {
|
|
7
|
+
projectId: string;
|
|
8
|
+
selectedScreenInstances: SelectedScreenInstance[];
|
|
9
|
+
assetId: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const applyDesignSystemTool = (client: any) => ({
|
|
2
13
|
name: "apply_design_system",
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
|
|
14
|
+
description:
|
|
15
|
+
"Applies a design system asset to one or more screens, updating colors, fonts, and shapes",
|
|
16
|
+
|
|
17
|
+
parameters: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
projectId: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Required. Project ID without prefix."
|
|
23
|
+
},
|
|
24
|
+
selectedScreenInstances: {
|
|
25
|
+
type: "array",
|
|
26
|
+
description:
|
|
27
|
+
"Required. Screen instances to update from get_project.",
|
|
28
|
+
items: {
|
|
29
|
+
type: "object",
|
|
30
|
+
properties: {
|
|
31
|
+
id: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description:
|
|
34
|
+
"Required. Screen instance ID (not source screen ID)."
|
|
35
|
+
},
|
|
36
|
+
sourceScreen: {
|
|
37
|
+
type: "string",
|
|
38
|
+
description:
|
|
39
|
+
"Required. Resource name format: projects/{project}/screens/{screen}"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
required: ["id", "sourceScreen"]
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
assetId: {
|
|
46
|
+
type: "string",
|
|
47
|
+
description:
|
|
48
|
+
"Required. Design system asset ID without assets/ prefix."
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
required: [
|
|
52
|
+
"projectId",
|
|
53
|
+
"selectedScreenInstances",
|
|
54
|
+
"assetId"
|
|
55
|
+
]
|
|
6
56
|
},
|
|
7
|
-
|
|
57
|
+
|
|
58
|
+
async execute(_: string, params: ApplyDesignSystemParams) {
|
|
59
|
+
return await client.request("apply_design_system", params);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
@@ -1,7 +1,142 @@
|
|
|
1
|
-
|
|
1
|
+
type ColorMode =
|
|
2
|
+
| "COLOR_MODE_UNSPECIFIED"
|
|
3
|
+
| "LIGHT"
|
|
4
|
+
| "DARK";
|
|
5
|
+
|
|
6
|
+
type FontType =
|
|
7
|
+
| "FONT_UNSPECIFIED"
|
|
8
|
+
| "INTER"
|
|
9
|
+
| "DM_SANS"
|
|
10
|
+
| "GEIST";
|
|
11
|
+
|
|
12
|
+
type Roundness =
|
|
13
|
+
| "ROUNDNESS_UNSPECIFIED"
|
|
14
|
+
| "ROUND_FOUR"
|
|
15
|
+
| "ROUND_EIGHT"
|
|
16
|
+
| "ROUND_TWELVE"
|
|
17
|
+
| "ROUND_FULL";
|
|
18
|
+
|
|
19
|
+
type ColorVariant =
|
|
20
|
+
| "COLOR_VARIANT_UNSPECIFIED"
|
|
21
|
+
| "MONOCHROME"
|
|
22
|
+
| "NEUTRAL"
|
|
23
|
+
| "TONAL_SPOT"
|
|
24
|
+
| "VIBRANT"
|
|
25
|
+
| "EXPRESSIVE"
|
|
26
|
+
| "FIDELITY"
|
|
27
|
+
| "CONTENT"
|
|
28
|
+
| "RAINBOW"
|
|
29
|
+
| "FRUIT_SALAD";
|
|
30
|
+
|
|
31
|
+
type DesignTheme = {
|
|
32
|
+
colorMode: ColorMode;
|
|
33
|
+
headlineFont: FontType;
|
|
34
|
+
bodyFont: FontType;
|
|
35
|
+
labelFont?: FontType;
|
|
36
|
+
roundness: Roundness;
|
|
37
|
+
customColor: string;
|
|
38
|
+
colorVariant?: ColorVariant;
|
|
39
|
+
overridePrimaryColor?: string;
|
|
40
|
+
overrideSecondaryColor?: string;
|
|
41
|
+
overrideTertiaryColor?: string;
|
|
42
|
+
overrideNeutralColor?: string;
|
|
43
|
+
designMd?: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type DesignSystem = {
|
|
47
|
+
displayName: string;
|
|
48
|
+
theme: DesignTheme;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
type CreateDesignSystemParams = {
|
|
52
|
+
designSystem: DesignSystem;
|
|
53
|
+
projectId?: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const createDesignSystemTool = (client: any) => ({
|
|
2
57
|
name: "create_design_system",
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
|
|
58
|
+
description:
|
|
59
|
+
"Creates a new design system with colors, typography, roundness, and theme tokens for a Stitch project",
|
|
60
|
+
|
|
61
|
+
parameters: {
|
|
62
|
+
type: "object",
|
|
63
|
+
properties: {
|
|
64
|
+
projectId: {
|
|
65
|
+
type: "string",
|
|
66
|
+
description:
|
|
67
|
+
"Optional. Project ID. If omitted, creates a global design asset."
|
|
68
|
+
},
|
|
69
|
+
designSystem: {
|
|
70
|
+
type: "object",
|
|
71
|
+
description: "Required. Design system definition.",
|
|
72
|
+
properties: {
|
|
73
|
+
displayName: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: "Required. Display name."
|
|
76
|
+
},
|
|
77
|
+
theme: {
|
|
78
|
+
type: "object",
|
|
79
|
+
properties: {
|
|
80
|
+
colorMode: {
|
|
81
|
+
type: "string",
|
|
82
|
+
enum: ["LIGHT", "DARK"]
|
|
83
|
+
},
|
|
84
|
+
headlineFont: {
|
|
85
|
+
type: "string",
|
|
86
|
+
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
87
|
+
},
|
|
88
|
+
bodyFont: {
|
|
89
|
+
type: "string",
|
|
90
|
+
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
91
|
+
},
|
|
92
|
+
labelFont: {
|
|
93
|
+
type: "string",
|
|
94
|
+
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
95
|
+
},
|
|
96
|
+
roundness: {
|
|
97
|
+
type: "string",
|
|
98
|
+
enum: [
|
|
99
|
+
"ROUND_FOUR",
|
|
100
|
+
"ROUND_EIGHT",
|
|
101
|
+
"ROUND_TWELVE",
|
|
102
|
+
"ROUND_FULL"
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
customColor: {
|
|
106
|
+
type: "string",
|
|
107
|
+
description: "Hex seed color"
|
|
108
|
+
},
|
|
109
|
+
colorVariant: {
|
|
110
|
+
type: "string",
|
|
111
|
+
enum: [
|
|
112
|
+
"MONOCHROME",
|
|
113
|
+
"NEUTRAL",
|
|
114
|
+
"TONAL_SPOT",
|
|
115
|
+
"VIBRANT",
|
|
116
|
+
"EXPRESSIVE"
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
designMd: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "Optional markdown design instructions"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
required: [
|
|
125
|
+
"colorMode",
|
|
126
|
+
"headlineFont",
|
|
127
|
+
"bodyFont",
|
|
128
|
+
"roundness",
|
|
129
|
+
"customColor"
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
required: ["displayName", "theme"]
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
required: ["designSystem"]
|
|
6
137
|
},
|
|
7
|
-
|
|
138
|
+
|
|
139
|
+
async execute(_: string, params: CreateDesignSystemParams) {
|
|
140
|
+
return await client.request("create_design_system", params);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
@@ -1,28 +1,43 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
DeviceType,
|
|
3
|
+
ModelId,
|
|
4
|
+
StitchMCPClient
|
|
5
|
+
} from "../services/stitch-mcp-client.js";
|
|
2
6
|
import fs from "node:fs";
|
|
3
7
|
import path from "node:path";
|
|
4
8
|
import os from "node:os";
|
|
5
9
|
|
|
6
|
-
type
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
previewUrl?: string;
|
|
23
|
-
base64Image?: string;
|
|
24
|
-
rawBytes?: string;
|
|
10
|
+
type StitchResponse = {
|
|
11
|
+
screen?: {
|
|
12
|
+
name?: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
prompt?: string;
|
|
15
|
+
screenshot?: {
|
|
16
|
+
url?: string;
|
|
17
|
+
bytes?: string;
|
|
18
|
+
};
|
|
19
|
+
htmlCode?: {
|
|
20
|
+
content?: string;
|
|
21
|
+
url?: string;
|
|
22
|
+
};
|
|
23
|
+
deviceType?: DeviceType;
|
|
24
|
+
width?: string;
|
|
25
|
+
height?: string;
|
|
25
26
|
};
|
|
27
|
+
output_components?: Array<{
|
|
28
|
+
text?: string;
|
|
29
|
+
suggestion?: string;
|
|
30
|
+
design?: {
|
|
31
|
+
screenshot?: {
|
|
32
|
+
url?: string;
|
|
33
|
+
bytes?: string;
|
|
34
|
+
};
|
|
35
|
+
htmlCode?: {
|
|
36
|
+
content?: string;
|
|
37
|
+
url?: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
}>;
|
|
26
41
|
};
|
|
27
42
|
|
|
28
43
|
export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
@@ -33,91 +48,100 @@ export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
|
33
48
|
parameters: {
|
|
34
49
|
type: "object",
|
|
35
50
|
properties: {
|
|
51
|
+
projectId: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "Required. Project ID without prefix."
|
|
54
|
+
},
|
|
36
55
|
prompt: {
|
|
37
56
|
type: "string",
|
|
38
57
|
description: "Describe the UI screen to generate"
|
|
58
|
+
},
|
|
59
|
+
deviceType: {
|
|
60
|
+
type: "string",
|
|
61
|
+
enum: [
|
|
62
|
+
"DEVICE_TYPE_UNSPECIFIED",
|
|
63
|
+
"MOBILE",
|
|
64
|
+
"DESKTOP",
|
|
65
|
+
"TABLET",
|
|
66
|
+
"AGNOSTIC"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
modelId: {
|
|
70
|
+
type: "string",
|
|
71
|
+
enum: [
|
|
72
|
+
"MODEL_ID_UNSPECIFIED",
|
|
73
|
+
"GEMINI_3_PRO",
|
|
74
|
+
"GEMINI_3_FLASH",
|
|
75
|
+
"GEMINI_3_1_PRO"
|
|
76
|
+
]
|
|
39
77
|
}
|
|
40
78
|
},
|
|
41
|
-
required: ["prompt"]
|
|
79
|
+
required: ["projectId", "prompt"]
|
|
42
80
|
},
|
|
43
81
|
|
|
44
|
-
async execute(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
82
|
+
async execute(
|
|
83
|
+
_id: string,
|
|
84
|
+
params: {
|
|
85
|
+
projectId: string;
|
|
86
|
+
prompt: string;
|
|
87
|
+
deviceType?: DeviceType;
|
|
88
|
+
modelId?: ModelId;
|
|
89
|
+
}
|
|
90
|
+
) {
|
|
91
|
+
const result = (await client.generateScreen(params)) as StitchResponse;
|
|
92
|
+
|
|
93
|
+
const screen = result.screen;
|
|
94
|
+
const firstComponent = result.output_components?.[0];
|
|
49
95
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const base64Image = result.data?.base64Image;
|
|
54
|
-
const rawBytes = result.data?.rawBytes;
|
|
96
|
+
const imageUrl =
|
|
97
|
+
screen?.screenshot?.url ||
|
|
98
|
+
firstComponent?.design?.screenshot?.url;
|
|
55
99
|
|
|
56
100
|
if (imageUrl) {
|
|
57
|
-
// If we have an image URL, return it as an image block
|
|
58
101
|
return {
|
|
59
102
|
content: [
|
|
60
103
|
{
|
|
61
104
|
type: "image",
|
|
62
105
|
url: imageUrl,
|
|
63
|
-
caption: "Generated by Google Stitch"
|
|
106
|
+
caption: screen?.title || "Generated by Google Stitch"
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const imageBytes =
|
|
113
|
+
screen?.screenshot?.bytes ||
|
|
114
|
+
firstComponent?.design?.screenshot?.bytes;
|
|
115
|
+
|
|
116
|
+
if (imageBytes) {
|
|
117
|
+
const tempFilePath = path.join(
|
|
118
|
+
os.tmpdir(),
|
|
119
|
+
`stitch-screen-${Date.now()}.png`
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
fs.writeFileSync(
|
|
123
|
+
tempFilePath,
|
|
124
|
+
Buffer.from(imageBytes, "base64")
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "image",
|
|
131
|
+
path: tempFilePath,
|
|
132
|
+
caption: screen?.title || "Generated by Google Stitch"
|
|
64
133
|
}
|
|
65
134
|
]
|
|
66
135
|
};
|
|
67
|
-
} else if (base64Image || rawBytes) {
|
|
68
|
-
// Decode and save base64 or raw bytes to a temporary file
|
|
69
|
-
const tempDir = os.tmpdir();
|
|
70
|
-
const tempFilePath = path.join(tempDir, `stitch-screen-${Date.now()}.png`);
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
let imageData: Buffer;
|
|
74
|
-
if (base64Image) {
|
|
75
|
-
// Remove data URL prefix if present
|
|
76
|
-
const cleanBase64 = base64Image.replace(/^data:image\/\w+;base64,/, '');
|
|
77
|
-
imageData = Buffer.from(cleanBase64, 'base64');
|
|
78
|
-
} else if (rawBytes) {
|
|
79
|
-
// Assuming rawBytes is base64 encoded
|
|
80
|
-
imageData = Buffer.from(rawBytes, 'base64');
|
|
81
|
-
} else {
|
|
82
|
-
throw new Error("No image data found");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
fs.writeFileSync(tempFilePath, imageData);
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
content: [
|
|
89
|
-
{
|
|
90
|
-
type: "image",
|
|
91
|
-
path: tempFilePath,
|
|
92
|
-
caption: "Generated by Google Stitch"
|
|
93
|
-
}
|
|
94
|
-
]
|
|
95
|
-
};
|
|
96
|
-
} catch (error) {
|
|
97
|
-
console.error("Failed to save image:", error);
|
|
98
|
-
// Fall back to HTML if image processing fails
|
|
99
|
-
}
|
|
100
136
|
}
|
|
101
137
|
|
|
102
|
-
// Fallback to HTML if no image data is available
|
|
103
138
|
const html =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)}</pre>`
|
|
111
|
-
: result.jsx
|
|
112
|
-
? `<pre style="white-space:pre-wrap;padding:16px">${escapeHtml(
|
|
113
|
-
result.jsx
|
|
114
|
-
)}</pre>`
|
|
115
|
-
: `<div style="padding:16px">
|
|
116
|
-
<h3>Screen generated</h3>
|
|
117
|
-
<pre>${escapeHtml(
|
|
118
|
-
JSON.stringify(result, null, 2)
|
|
119
|
-
)}</pre>
|
|
120
|
-
</div>`);
|
|
139
|
+
screen?.htmlCode?.content ||
|
|
140
|
+
firstComponent?.design?.htmlCode?.content ||
|
|
141
|
+
`<div style="padding:16px">
|
|
142
|
+
<h3>${escapeHtml(screen?.title || "Generated screen")}</h3>
|
|
143
|
+
<p>${escapeHtml(firstComponent?.text || "")}</p>
|
|
144
|
+
</div>`;
|
|
121
145
|
|
|
122
146
|
return {
|
|
123
147
|
content: [
|