coderio 1.0.2 → 1.0.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -147,7 +147,94 @@ report path: coderio/<design-name_node-id>/process/validation/index.html
147
147
  | `validate` | `val` | Run validation on generated code |
148
148
  | `images` | - | Download and process Figma assets |
149
149
 
150
- ### Option 2: Skill (Portable Embedded Workflow)
150
+ ### Option 2: Docker
151
+
152
+ Best for portable environments without Node.js installation.
153
+
154
+ #### 1. Prerequisites
155
+
156
+ - [Docker](https://docs.docker.com/get-docker/)
157
+ - [Figma Personal Access Token](https://www.figma.com/developers/api#access-tokens)
158
+ - LLM API Key ([Anthropic](https://console.anthropic.com/) | [OpenAI](https://platform.openai.com/) | [Google](https://aistudio.google.com/))
159
+
160
+ > **For Windows Users:** The commands below use bash syntax (heredoc, `${PWD}`, `--network=host`, etc.) which are not compatible with CMD or PowerShell. Please use **WSL2** to run them:
161
+ >
162
+ > 1. Install [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) and a Linux distribution (e.g. Ubuntu)
163
+ > 2. Install [Docker Desktop](https://docs.docker.com/desktop/install/windows-install/) and enable **WSL2 integration** in Settings → Resources → WSL Integration
164
+ > 3. Open a WSL2 terminal (run `wsl` in CMD/PowerShell, or open Ubuntu from the Start menu)
165
+ > 4. Run all the following commands inside the WSL2 terminal
166
+
167
+ #### 2. Installation
168
+
169
+ ```bash
170
+ docker pull crpi-p4hwwrt00km3axuk.cn-shanghai.personal.cr.aliyuncs.com/coderio/coderio
171
+ ```
172
+
173
+ #### 3. Configuration
174
+
175
+ Create a working directory and `config.yaml`:
176
+
177
+ ```bash
178
+ mkdir -p ./coderio-app && cd ./coderio-app
179
+ cat > config.yaml << 'EOF'
180
+ model:
181
+ provider: openai # anthropic | openai | google
182
+ model: gemini-3-pro-preview
183
+ baseUrl: https://api.anthropic.com
184
+ apiKey: your-api-key-here
185
+
186
+ figma:
187
+ token: your-figma-token-here
188
+
189
+ debug:
190
+ enabled: false
191
+ EOF
192
+ ```
193
+
194
+ #### 4. Usage
195
+
196
+ ```bash
197
+ docker run -ti --rm \
198
+ --network=host \
199
+ -v ${PWD}:/app \
200
+ -v ./config.yaml:/root/.coderio/config.yaml \
201
+ crpi-p4hwwrt00km3axuk.cn-shanghai.personal.cr.aliyuncs.com/coderio/coderio bash
202
+ ```
203
+
204
+ Once inside the container, use CodeRio commands:
205
+
206
+ ```bash
207
+ # Convert Figma design to code (default mode: code only)
208
+ coderio d2c -s 'https://www.figma.com/design/your-file-id/...'
209
+
210
+ # Full mode: Generate code + visual validation + auto-refinement
211
+ coderio d2c -s 'https://www.figma.com/design/your-file-id/...' -m full
212
+ ```
213
+
214
+ #### 5. Run Your Project
215
+
216
+ ```bash
217
+ # Navigate to generated project
218
+ cd coderio/<design-name_node-id>/my-app
219
+
220
+ # Install dependencies
221
+ pnpm install
222
+
223
+ # Start dev server
224
+ pnpm dev
225
+
226
+ # 🎉 Open http://localhost:5173
227
+ ```
228
+
229
+ #### 6. View Validation Report
230
+
231
+ Generated files are mounted to your host machine. Open the validation report in your browser:
232
+
233
+ ```
234
+ ./coderio/<design-name_node-id>/process/validation/index.html
235
+ ```
236
+
237
+ ### Option 3: Skill (Portable Embedded Workflow)
151
238
 
152
239
  Best for control and precision using AI Agents.
153
240
 
package/dist/cli.js CHANGED
@@ -475,7 +475,7 @@ var AGENT_CONTEXT_WINDOW_TOKENS = 128e3;
475
475
 
476
476
  // src/cli/init.ts
477
477
  function registerCommands(program) {
478
- const version = false ? "0.0.1" : "1.0.1";
478
+ const version = false ? "0.0.1" : "1.0.3-alpha.1";
479
479
  program.name(CLI_NAME).description(`${CLI_NAME} - Convert Figma designs to code`).version(version, "-v, -V, --version", "Output the version number").showHelpAfterError();
480
480
  }
481
481
 
@@ -595,20 +595,36 @@ var Workspace = class {
595
595
  /**
596
596
  * Delete all files and directories inside the workspace
597
597
  * @param workspace - The workspace structure
598
- * @param exclude - Optional list of file/directory names to exclude from deletion
598
+ * @param preserve - Optional list of relative paths (from workspace root) to preserve from deletion
599
599
  */
600
- deleteWorkspace(workspace, exclude = []) {
600
+ deleteWorkspace(workspace, preserve = []) {
601
601
  try {
602
- if (fs2.existsSync(workspace.root)) {
603
- const entries = fs2.readdirSync(workspace.root);
602
+ if (!fs2.existsSync(workspace.root)) return;
603
+ const preserveFiles = new Set(preserve.map((p) => path2.normalize(p)));
604
+ const preserveDirs = /* @__PURE__ */ new Set();
605
+ for (const p of preserveFiles) {
606
+ let dir = path2.dirname(p);
607
+ while (dir !== ".") {
608
+ preserveDirs.add(dir);
609
+ dir = path2.dirname(dir);
610
+ }
611
+ }
612
+ const deleteRecursive = (dirPath, relativeTo = "") => {
613
+ const entries = fs2.readdirSync(dirPath);
604
614
  for (const entry of entries) {
605
- if (exclude.includes(entry)) {
615
+ const fullPath = path2.join(dirPath, entry);
616
+ const relPath = relativeTo ? path2.join(relativeTo, entry) : entry;
617
+ if (preserveFiles.has(relPath)) {
606
618
  continue;
607
619
  }
608
- const fullPath = path2.join(workspace.root, entry);
609
- fs2.rmSync(fullPath, { recursive: true, force: true });
620
+ if (preserveDirs.has(relPath)) {
621
+ deleteRecursive(fullPath, relPath);
622
+ } else {
623
+ fs2.rmSync(fullPath, { recursive: true, force: true });
624
+ }
610
625
  }
611
- }
626
+ };
627
+ deleteRecursive(workspace.root);
612
628
  } catch (error) {
613
629
  const errorMessage = error instanceof Error ? error.message : String(error);
614
630
  logger.printWarnLog(`Failed to delete workspace: ${errorMessage}`);
@@ -5714,21 +5730,45 @@ var FILE_NAMING_CONVENTION = `
5714
5730
  - NEVER use PascalCase or other names for filenames (e.g., DO NOT use \`MainFrame.tsx\` or \`Button.tsx\`).`;
5715
5731
  var OUTPUT_FORMAT = `
5716
5732
  <output_format>
5717
- If only one file (TSX) is needed:
5733
+ **CRITICAL - Output Format Requirements:**
5734
+
5735
+ **CASE 1: Single File (TSX only)**
5736
+ - Return code wrapped in triple backticks with language identifier
5737
+ - NO file name header needed
5738
+ - Example:
5718
5739
  \`\`\`tsx
5719
- // code...
5740
+ export default function Component() {
5741
+ return <div>...</div>;
5742
+ }
5720
5743
  \`\`\`
5721
5744
 
5722
- If multiple files are needed (e.g., TSX + Styles):
5745
+ **CASE 2: Multiple Files (TSX + Styles)**
5746
+ - **REQUIRED**: Each file MUST start with EXACTLY \`## \` (two hash symbols + one space) followed by filename
5747
+ - **REQUIRED**: Filename must be complete with extension (e.g., \`index.tsx\`, \`index.module.css\`)
5748
+ - **FORBIDDEN**: Do NOT use single \`#\`, do NOT omit filename, do NOT use other markers
5749
+ - Follow this exact structure:
5750
+
5723
5751
  ## index.tsx
5724
5752
  \`\`\`tsx
5725
- // code...
5753
+ export default function Component() {
5754
+ return <div>...</div>;
5755
+ }
5726
5756
  \`\`\`
5727
5757
 
5728
5758
  ## index.module.[css|less|scss]
5729
5759
  \`\`\`[css|less|scss]
5730
- // styles...
5760
+ .container {
5761
+ /* styles */
5762
+ }
5731
5763
  \`\`\`
5764
+
5765
+ **VALIDATION CHECKLIST (for multiple files):**
5766
+ \u2713 Each file section starts with \`## \` (two hashes + space)
5767
+ \u2713 Filename includes full extension
5768
+ \u2713 Code wrapped in triple backticks with language
5769
+ \u2717 DO NOT use \`# filename\` (single hash)
5770
+ \u2717 DO NOT omit file headers
5771
+ \u2717 DO NOT use other separators
5732
5772
  </output_format>`;
5733
5773
  function generateChildrenPropsInstructions(modes) {
5734
5774
  const instructions = [];
@@ -6379,12 +6419,16 @@ async function design2code(url, mode) {
6379
6419
  const resume = await promptCheckpointChoice(checkpointer, threadId);
6380
6420
  logger.printInfoLog(`Starting design-to-code process for: ${urlInfo.projectName}`);
6381
6421
  if (resume !== true) {
6382
- workspaceManager.deleteWorkspace(workspace, ["checkpoint"]);
6422
+ workspaceManager.deleteWorkspace(workspace, ["checkpoint/coderio-cli.db"]);
6383
6423
  logger.printInfoLog("Starting fresh...");
6384
6424
  await clearThreadCheckpoint(checkpointer, threadId);
6385
6425
  } else {
6386
6426
  logger.printInfoLog("Resuming from cache...");
6387
6427
  }
6428
+ await callModel({
6429
+ question: "\u8BF7\u4ECB\u7ECD\u4F60\u81EA\u5DF1\uFF0C\u4F60\u662F\u4EC0\u4E48\u6A21\u578B",
6430
+ streaming: false
6431
+ });
6388
6432
  const graph = new StateGraph(GraphStateAnnotation).addNode("initial" /* INITIAL */, initialProject).addNode("process" /* PROCESS */, generateProtocol).addNode("code" /* CODE */, generateCode).addNode("validation" /* VALIDATION */, runValidation).addEdge(START, "initial" /* INITIAL */).addEdge("initial" /* INITIAL */, "process" /* PROCESS */).addEdge("process" /* PROCESS */, "code" /* CODE */).addEdge("code" /* CODE */, "validation" /* VALIDATION */).addEdge("validation" /* VALIDATION */, END).compile({ checkpointer });
6389
6433
  const config = { configurable: { thread_id: threadId } };
6390
6434
  const validationMode = mode ?? "full" /* Full */;