From b2ac61b848fbf0bc13a07fd5dc90b87098b994a4 Mon Sep 17 00:00:00 2001 From: Jay Date: Tue, 14 Apr 2026 03:47:30 +0900 Subject: [PATCH] fix: robust regex parser for XML actions resolving file creation and terminal failures (v1.0.31) --- package.json | 2 +- src/extension.ts | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4f30e0c..4aac7c0 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "connect-ai-lab", "displayName": "Connect AI", "description": "100% 로컬 AI 코딩 에이전트 — 파일 생성, 코드 편집, 터미널 실행을 오프라인으로. Ollama + Gemma/Llama/DeepSeek 지원.", - "version": "1.0.30", + "version": "1.0.31", "publisher": "connectailab", "license": "MIT", "icon": "assets/icon.png", diff --git a/src/extension.ts b/src/extension.ts index 493049a..43ad226 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -830,13 +830,22 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { } // ACTION 1: Create files - const createRegex = /([\s\S]*?)<\/create_file>/g; + const createRegex = /]+)['"]?[^>]*>([\s\S]*?)<\/create_file>/gi; let match: RegExpExecArray | null; let firstCreatedFile = ''; while ((match = createRegex.exec(aiMessage)) !== null) { const relPath = match[1].trim(); - const content = match[2].replace(/^\n/, ''); // remove leading newline only + let content = match[2].trim(); + + // Strip markdown code fences if AI accidentally wrapped the content inside the xml + if (content.startsWith('```')) { + const lines = content.split('\n'); + if (lines[0].startsWith('```')) lines.shift(); + if (lines.length > 0 && lines[lines.length - 1].startsWith('```')) lines.pop(); + content = lines.join('\n').trim(); + } + try { const absPath = path.join(rootPath, relPath); const dir = path.dirname(absPath); @@ -857,7 +866,7 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { } // ACTION 2: Edit files - const editRegex = /([\s\S]*?)<\/edit_file>/g; + const editRegex = /]+)['"]?[^>]*>([\s\S]*?)<\/edit_file>/gi; while ((match = editRegex.exec(aiMessage)) !== null) { const relPath = match[1].trim(); const body = match[2]; @@ -897,9 +906,16 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { } // ACTION 3: Run commands - const cmdRegex = /([\s\S]*?)<\/run_command>/g; + const cmdRegex = /([\s\S]*?)<\/run_command>/gi; while ((match = cmdRegex.exec(aiMessage)) !== null) { - const cmd = match[1].trim(); + let cmd = match[1].trim(); + // Clean up if AI outputs markdown inside + if (cmd.startsWith('```')) { + const lines = cmd.split('\n'); + if (lines[0].startsWith('```')) lines.shift(); + if (lines.length > 0 && lines[lines.length - 1].startsWith('```')) lines.pop(); + cmd = lines.join('\n').trim(); + } try { if (!this._terminal || this._terminal.exitStatus !== undefined) { this._terminal = vscode.window.createTerminal({