diff --git a/CHANGELOG.md b/CHANGELOG.md index 82ff36c6..71bdc326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [3.8.1](https://github.com/breaking-brake/cc-wf-studio/compare/v3.8.0...v3.8.1) (2025-12-17) + +### Bug Fixes + +* dialog positioning broken by NodePalette transform ([#290](https://github.com/breaking-brake/cc-wf-studio/issues/290)) ([b1adb8f](https://github.com/breaking-brake/cc-wf-studio/commit/b1adb8fdda690aa9288def8088d29da7325c289f)) +* improve JSON parsing to handle nested markdown code blocks ([#289](https://github.com/breaking-brake/cc-wf-studio/issues/289)) ([d0ca208](https://github.com/breaking-brake/cc-wf-studio/commit/d0ca20880ed22a2ed1550746136487015567545d)) + ## [3.8.0](https://github.com/breaking-brake/cc-wf-studio/compare/v3.7.4...v3.8.0) (2025-12-17) ### Features diff --git a/package-lock.json b/package-lock.json index 61f14254..10e53599 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cc-wf-studio", - "version": "3.8.0", + "version": "3.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cc-wf-studio", - "version": "3.8.0", + "version": "3.8.1", "license": "AGPL-3.0-or-later", "dependencies": { "@modelcontextprotocol/sdk": "^1.24.3", diff --git a/package.json b/package.json index 110f01a6..d0dc4e46 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "cc-wf-studio", "displayName": "Claude Code Workflow Studio", "description": "Visual workflow editor for Claude Code Slash Commands, Sub Agents, Agent Skills, and MCP Tools", - "version": "3.8.0", + "version": "3.8.1", "publisher": "breaking-brake", "icon": "resources/icon.png", "repository": { diff --git a/src/extension/services/claude-code-service.ts b/src/extension/services/claude-code-service.ts index 987df97f..d504e5d1 100644 --- a/src/extension/services/claude-code-service.ts +++ b/src/extension/services/claude-code-service.ts @@ -251,16 +251,31 @@ function isSubprocessError(error: unknown): error is SubprocessError { /** * Parse JSON output from Claude Code CLI * + * Handles two output formats: + * 1. Markdown-wrapped: ```json { ... } ``` + * 2. Raw JSON: { ... } + * + * Note: Uses string position-based extraction (not regex) to handle cases + * where the JSON content itself contains markdown code blocks. + * * @param output - Raw output string from CLI * @returns Parsed JSON object or null if parsing fails */ export function parseClaudeCodeOutput(output: string): unknown { try { - // Claude Code might wrap output in markdown code blocks, so extract JSON - const jsonMatch = output.match(/```json\s*([\s\S]*?)\s*```/); - const jsonString = jsonMatch ? jsonMatch[1] : output; + const trimmed = output.trim(); + + // Strategy 1: If wrapped in ```json...```, remove outer markers only + if (trimmed.startsWith('```json') && trimmed.endsWith('```')) { + const jsonContent = trimmed + .slice(7) // Remove ```json + .slice(0, -3) // Remove trailing ``` + .trim(); + return JSON.parse(jsonContent); + } - return JSON.parse(jsonString.trim()); + // Strategy 2: Try parsing as-is + return JSON.parse(trimmed); } catch (_error) { // If parsing fails, return null return null; diff --git a/src/webview/package-lock.json b/src/webview/package-lock.json index 566a23fb..02b4d01a 100644 --- a/src/webview/package-lock.json +++ b/src/webview/package-lock.json @@ -1,15 +1,17 @@ { "name": "cc-wf-studio-webview", - "version": "3.8.0", + "version": "3.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cc-wf-studio-webview", - "version": "3.8.0", + "version": "3.8.1", "license": "AGPL-3.0-or-later", "dependencies": { + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-portal": "^1.1.10", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-toggle-group": "^1.1.11", @@ -885,6 +887,36 @@ } } }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", @@ -1110,6 +1142,30 @@ } } }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", @@ -1143,12 +1199,12 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.10.tgz", + "integrity": "sha512-4kY9IVa6+9nJPsYmngK5Uk2kUmZnv7ChhHAFeQ5oaj8jrR1bIi3xww8nH71pz1/Ve4d/cXO3YxT8eikt1B0a8w==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-primitive": "2.1.4", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { @@ -1166,6 +1222,47 @@ } } }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-presence": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", @@ -1287,6 +1384,30 @@ } } }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", @@ -1422,6 +1543,30 @@ } } }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", diff --git a/src/webview/package.json b/src/webview/package.json index dbe5b919..1e102a04 100644 --- a/src/webview/package.json +++ b/src/webview/package.json @@ -1,6 +1,6 @@ { "name": "cc-wf-studio-webview", - "version": "3.8.0", + "version": "3.8.1", "private": true, "license": "AGPL-3.0-or-later", "type": "module", @@ -13,7 +13,9 @@ "test:watch": "vitest watch" }, "dependencies": { + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-portal": "^1.1.10", "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-toggle-group": "^1.1.11", diff --git a/src/webview/src/App.tsx b/src/webview/src/App.tsx index 5814ff63..1d5905b9 100644 --- a/src/webview/src/App.tsx +++ b/src/webview/src/App.tsx @@ -5,6 +5,7 @@ * Based on: /specs/001-cc-wf-studio/plan.md */ +import * as Collapsible from '@radix-ui/react-collapsible'; import type { ErrorPayload, ImportWorkflowFromSlackPayload, @@ -214,31 +215,21 @@ const App: React.FC = () => { overflow: 'hidden', }} > - {/* Left Panel: Node Palette with collapse/expand animation */} -
- {t('skill.browser.description')} -
- - {/* Tabs */}