diff --git a/ehalsh.txt b/ehalsh.txt
new file mode 100644
index 0000000..e69de29
diff --git a/package.json b/package.json
index a5d9dbb..cff0501 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": "2.1.3",
+ "version": "2.1.4",
"publisher": "connectailab",
"license": "MIT",
"icon": "assets/icon.png",
diff --git a/src/extension.ts b/src/extension.ts
index c6bf251..85a7fb4 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -78,6 +78,10 @@ Example — user says "서버 실행해줘":
filename.md
Use this to READ documents from the user's personal knowledge base.
+━━━ ACTION 8: READ WEBSITES ━━━
+https://example.com
+Use this to read the textual content of any website on the internet.
+
CRITICAL RULES:
1. ALWAYS respond in the same language the user uses.
2. When the user asks to create, edit, delete files or run commands, you MUST use the action tags above. NEVER just show code without action tags.
@@ -817,7 +821,7 @@ class SidebarChatProvider implements vscode.WebviewViewProvider {
this._view.webview.postMessage({ type: 'streamEnd' });
this._chatHistory.push({ role: 'assistant', content: aiMessage });
- const report = this._executeActions(aiMessage);
+ const report = await this._executeActions(aiMessage);
if (report.length > 0) {
const reportMsg = `\n\n---\n**에이전트 작업 결과**\n${report.join('\n')}`;
this._view.webview.postMessage({ type: 'streamChunk', value: reportMsg });
@@ -1006,7 +1010,7 @@ class SidebarChatProvider implements vscode.WebviewViewProvider {
this._chatHistory.push({ role: 'assistant', content: aiMessage });
// 5. Execute agent actions
- const report = this._executeActions(aiMessage);
+ const report = await this._executeActions(aiMessage);
// 6. Agent report 추가 (있을 때만)
if (report.length > 0) {
@@ -1065,7 +1069,7 @@ class SidebarChatProvider implements vscode.WebviewViewProvider {
// --------------------------------------------------------
// Execute ALL agent actions from AI response
// --------------------------------------------------------
- private _executeActions(aiMessage: string): string[] {
+ private async _executeActions(aiMessage: string): Promise {
const report: string[] = [];
let rootPath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
@@ -1247,6 +1251,32 @@ class SidebarChatProvider implements vscode.WebviewViewProvider {
}
}
+ // ACTION 8: Read Urls (Web Scraping)
+ const urlRegex = /<(?:read_url|url|fetch_url)>([\s\S]*?)<\/(?:read_url|url|fetch_url)>/gi;
+ while ((match = urlRegex.exec(aiMessage)) !== null) {
+ const url = match[1].trim();
+ try {
+ // Fetch the HTML content
+ const { data } = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }, timeout: 10000 });
+ // Strip scripts and styles first
+ let cleaned = data.toString()
+ .replace(/
+`;
+console.log(templateHTML);
+const {JSDOM} = require('jsdom');
+try { new JSDOM(templateHTML, {runScripts:'dangerously'}); console.log('JSDOM OK'); } catch(e) { console.error('ERR:', e.message); }
diff --git a/test11.js b/test11.js
new file mode 100644
index 0000000..ff3b5ca
--- /dev/null
+++ b/test11.js
@@ -0,0 +1,19 @@
+const templateHTML = `
+
+`;
+const {JSDOM} = require('jsdom');
+try { new JSDOM(templateHTML, {runScripts:'dangerously'}); console.log('JSDOM OK'); } catch(e) { console.error('ERR:', e.message); }
diff --git a/test12.js b/test12.js
new file mode 100644
index 0000000..93a170a
--- /dev/null
+++ b/test12.js
@@ -0,0 +1,11 @@
+const ext = require('./out/extension');
+const fs = require('fs');
+const code = fs.readFileSync('out/extension.js', 'utf8');
+const match = code.match(/_getHtml.*?_getHtml\(\)\s*\{\s*return\s+(`(?:[^`]|\\`)*`);?/m);
+if (match) {
+ const html = eval(match[1]);
+ const lines = html.split('\n');
+ console.log("Total lines:", lines.length);
+ console.log("Line 50:", lines[49]);
+ console.log("Line 100:", lines[99]);
+}
diff --git a/test13.js b/test13.js
new file mode 100644
index 0000000..b2eebb3
--- /dev/null
+++ b/test13.js
@@ -0,0 +1,16 @@
+const Module = require('module');
+const originalRequire = Module.prototype.require;
+Module.prototype.require = function(request) {
+ if (request === 'vscode') return {};
+ return originalRequire.apply(this, arguments);
+};
+
+const fs = require('fs');
+const code = fs.readFileSync('out/extension.js', 'utf8');
+const match = code.match(/_getHtml.*?([\s\S]*?)<\/html>.*?;/m);
+if (match) {
+ const html = match[1] + "