Updates
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"result": "Final report with inconsistencies. This should be long enough to pass validation.",
|
||||
"createdAt": 1777985740400,
|
||||
"createdAt": 1778033752470,
|
||||
"modelVersion": "unknown"
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"result": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
||||
"createdAt": 1777985740393,
|
||||
"createdAt": 1778033752468,
|
||||
"modelVersion": "unknown"
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"result": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||
"createdAt": 1777985740387,
|
||||
"createdAt": 1778033752466,
|
||||
"modelVersion": "unknown"
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"result": "---\nid: stress_conflict_1777985740371\ndate: 2026-05-05T12:55:40.404Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\nFinal report with inconsistencies. This should be long enough to pass validation.\n\nFinal report with inconsistencies. This should be long enough to pass validation.\n\n---\n## 💡 Astra의 선제적 제안 (Proactive Next Actions)\nFinal report with inconsistencies. This should be long enough to pass validation.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `60/100` | ⚠️ Medium |\n| **Fallbacks Used** | `0` | ✅ None |\n| **Auto Retries** | `0` | ✅ Stable |\n| **Deduplication** | `0` | Standard |\n| **Processing Time** | `0.0s` | ✅ Fast |\n\n### 🔍 Decision Audit Trail\n- **[PLANNER]** 전략 수립 중... (12ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (4ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (9ms)\n",
|
||||
"createdAt": 1777985740404,
|
||||
"result": "---\nid: stress_conflict_1778033752447\ndate: 2026-05-06T02:15:52.471Z\ntype: knowledge_artifact\nstandard: P-Reinforce v3.0\ntags: [automated, connect_ai, brain_sync]\n---\n\n## 📌 Brief Summary\nFinal report with inconsistencies. This should be long enough to pass validation.\n\nFinal report with inconsistencies. This should be long enough to pass validation.\n\n---\n## 💡 Astra의 선제적 제안 (Proactive Next Actions)\nFinal report with inconsistencies. This should be long enough to pass validation.\n---\n## 🛡️ Reliability & Audit Summary\n> [!NOTE]\n> 이 문서는 ConnectAI의 **Intelligent Resilience** 엔진에 의해 검증 및 정제되었습니다.\n\n| Metric | Value | Status |\n| :--- | :--- | :--- |\n| **Conflict Risk** | `60/100` | ⚠️ Medium |\n| **Fallbacks Used** | `0` | ✅ None |\n| **Auto Retries** | `0` | ✅ Stable |\n| **Deduplication** | `0` | Standard |\n| **Processing Time** | `0.0s` | ✅ Fast |\n\n### 🔍 Decision Audit Trail\n- **[PLANNER]** 전략 수립 중... (18ms)\n- **[RESEARCHER]** 핵심 정보 수집 및 분석 중... (2ms)\n- **[WRITER]** 최종 리포트 작성 및 편집 중... (2ms)\n",
|
||||
"createdAt": 1778033752471,
|
||||
"modelVersion": "unknown"
|
||||
}
|
||||
+11
-11
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"missionId": "stress_conflict_1777985740371",
|
||||
"missionId": "stress_conflict_1778033752447",
|
||||
"status": "completed",
|
||||
"startTime": "2026-05-05T12:55:40.371Z",
|
||||
"totalElapsedMs": 33,
|
||||
"startTime": "2026-05-06T02:15:52.447Z",
|
||||
"totalElapsedMs": 25,
|
||||
"results": {
|
||||
"planner": "Detailed Execution Plan: 1. Research 2. Analyze 3. Write report with high quality.",
|
||||
"researcher": "[CONFLICT WARNING] 성능이 200% 증가했습니다. vs 그러나 동시에 50% 감소했습니다. 최적화와 성능 저하가 동시에 발견됨.",
|
||||
@@ -16,30 +16,30 @@
|
||||
{
|
||||
"from": "idle",
|
||||
"to": "planner",
|
||||
"durationMs": 12,
|
||||
"durationMs": 18,
|
||||
"message": "전략 수립 중...",
|
||||
"ts": "2026-05-05T12:55:40.383Z"
|
||||
"ts": "2026-05-06T02:15:52.465Z"
|
||||
},
|
||||
{
|
||||
"from": "planner",
|
||||
"to": "researcher",
|
||||
"durationMs": 4,
|
||||
"durationMs": 2,
|
||||
"message": "핵심 정보 수집 및 분석 중...",
|
||||
"ts": "2026-05-05T12:55:40.387Z"
|
||||
"ts": "2026-05-06T02:15:52.467Z"
|
||||
},
|
||||
{
|
||||
"from": "researcher",
|
||||
"to": "writer",
|
||||
"durationMs": 9,
|
||||
"durationMs": 2,
|
||||
"message": "최종 리포트 작성 및 편집 중...",
|
||||
"ts": "2026-05-05T12:55:40.396Z"
|
||||
"ts": "2026-05-06T02:15:52.469Z"
|
||||
},
|
||||
{
|
||||
"from": "writer",
|
||||
"to": "completed",
|
||||
"durationMs": 8,
|
||||
"durationMs": 3,
|
||||
"message": "미션 완료",
|
||||
"ts": "2026-05-05T12:55:40.404Z"
|
||||
"ts": "2026-05-06T02:15:52.472Z"
|
||||
}
|
||||
],
|
||||
"resilienceMetrics": {
|
||||
Generated
+224
-3
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "g1nation",
|
||||
"name": "astra",
|
||||
"version": "2.78.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "g1nation",
|
||||
"name": "astra",
|
||||
"version": "2.78.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"marked": "^18.0.2"
|
||||
"marked": "^18.0.2",
|
||||
"pdf-parse": "^2.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
@@ -57,6 +58,7 @@
|
||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.29.0",
|
||||
"@babel/generator": "^7.29.0",
|
||||
@@ -1333,6 +1335,190 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.80.tgz",
|
||||
"integrity": "sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"e2e/*"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@napi-rs/canvas-android-arm64": "0.1.80",
|
||||
"@napi-rs/canvas-darwin-arm64": "0.1.80",
|
||||
"@napi-rs/canvas-darwin-x64": "0.1.80",
|
||||
"@napi-rs/canvas-linux-arm-gnueabihf": "0.1.80",
|
||||
"@napi-rs/canvas-linux-arm64-gnu": "0.1.80",
|
||||
"@napi-rs/canvas-linux-arm64-musl": "0.1.80",
|
||||
"@napi-rs/canvas-linux-riscv64-gnu": "0.1.80",
|
||||
"@napi-rs/canvas-linux-x64-gnu": "0.1.80",
|
||||
"@napi-rs/canvas-linux-x64-musl": "0.1.80",
|
||||
"@napi-rs/canvas-win32-x64-msvc": "0.1.80"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-android-arm64": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.80.tgz",
|
||||
"integrity": "sha512-sk7xhN/MoXeuExlggf91pNziBxLPVUqF2CAVnB57KLG/pz7+U5TKG8eXdc3pm0d7Od0WreB6ZKLj37sX9muGOQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-darwin-arm64": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.80.tgz",
|
||||
"integrity": "sha512-O64APRTXRUiAz0P8gErkfEr3lipLJgM6pjATwavZ22ebhjYl/SUbpgM0xcWPQBNMP1n29afAC/Us5PX1vg+JNQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-darwin-x64": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.80.tgz",
|
||||
"integrity": "sha512-FqqSU7qFce0Cp3pwnTjVkKjjOtxMqRe6lmINxpIZYaZNnVI0H5FtsaraZJ36SiTHNjZlUB69/HhxNDT1Aaa9vA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.80.tgz",
|
||||
"integrity": "sha512-eyWz0ddBDQc7/JbAtY4OtZ5SpK8tR4JsCYEZjCE3dI8pqoWUC8oMwYSBGCYfsx2w47cQgQCgMVRVTFiiO38hHQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-arm64-gnu": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.80.tgz",
|
||||
"integrity": "sha512-qwA63t8A86bnxhuA/GwOkK3jvb+XTQaTiVML0vAWoHyoZYTjNs7BzoOONDgTnNtr8/yHrq64XXzUoLqDzU+Uuw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-arm64-musl": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.80.tgz",
|
||||
"integrity": "sha512-1XbCOz/ymhj24lFaIXtWnwv/6eFHXDrjP0jYkc6iHQ9q8oXKzUX1Lc6bu+wuGiLhGh2GS/2JlfORC5ZcXimRcg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.80.tgz",
|
||||
"integrity": "sha512-XTzR125w5ZMs0lJcxRlS1K3P5RaZ9RmUsPtd1uGt+EfDyYMu4c6SEROYsxyatbbu/2+lPe7MPHOO/0a0x7L/gw==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-x64-gnu": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.80.tgz",
|
||||
"integrity": "sha512-BeXAmhKg1kX3UCrJsYbdQd3hIMDH/K6HnP/pG2LuITaXhXBiNdh//TVVVVCBbJzVQaV5gK/4ZOCMrQW9mvuTqA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-linux-x64-musl": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.80.tgz",
|
||||
"integrity": "sha512-x0XvZWdHbkgdgucJsRxprX/4o4sEed7qo9rCQA9ugiS9qE2QvP0RIiEugtZhfLH3cyI+jIRFJHV4Fuz+1BHHMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@napi-rs/canvas-win32-x64-msvc": {
|
||||
"version": "0.1.80",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.80.tgz",
|
||||
"integrity": "sha512-Z8jPsM6df5V8B1HrCHB05+bDiCxjE9QA//3YrkKIdVDEwn5RKaqOxCJDRJkl48cJbylcrJbW4HxZbTte8juuPg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.10",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
|
||||
@@ -1757,6 +1943,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.10.12",
|
||||
"caniuse-lite": "^1.0.30001782",
|
||||
@@ -2654,6 +2841,7 @@
|
||||
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^29.7.0",
|
||||
"@jest/types": "^29.6.3",
|
||||
@@ -3662,6 +3850,38 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/pdf-parse": {
|
||||
"version": "2.4.5",
|
||||
"resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-2.4.5.tgz",
|
||||
"integrity": "sha512-mHU89HGh7v+4u2ubfnevJ03lmPgQ5WU4CxAVmTSh/sxVTEDYd1er/dKS/A6vg77NX47KTEoihq8jZBLr8Cxuwg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@napi-rs/canvas": "0.1.80",
|
||||
"pdfjs-dist": "5.4.296"
|
||||
},
|
||||
"bin": {
|
||||
"pdf-parse": "bin/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.16.0 <21 || >=22.3.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/mehmet-kozan"
|
||||
}
|
||||
},
|
||||
"node_modules/pdfjs-dist": {
|
||||
"version": "5.4.296",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz",
|
||||
"integrity": "sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q==",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=20.16.0 || >=22.3.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@napi-rs/canvas": "^0.1.80"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@@ -4178,6 +4398,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
||||
+3
-2
@@ -2,7 +2,7 @@
|
||||
"name": "astra",
|
||||
"displayName": "Astra",
|
||||
"description": "The personal intelligence layer for Antigravity and VS Code. A private cognitive partner for deep project context, memory, and proactive strategic decision-making.",
|
||||
"version": "2.78.0",
|
||||
"version": "2.79.0",
|
||||
"publisher": "g1nation",
|
||||
"license": "MIT",
|
||||
"icon": "assets/icon.png",
|
||||
@@ -226,6 +226,7 @@
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"marked": "^18.0.2"
|
||||
"marked": "^18.0.2",
|
||||
"pdf-parse": "^2.4.5"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -333,9 +333,8 @@ export class AgentExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. API Request Setup
|
||||
const { ollamaUrl, defaultModel: configDefaultModel, timeout } = getConfig();
|
||||
const actualModel = modelName || configDefaultModel;
|
||||
// 3. API Request Setup (라인 229에서 이미 추출한 ollamaUrl, configDefaultModel 재사용)
|
||||
const actualModel = (modelName && modelName.trim()) || configDefaultModel;
|
||||
const reqMessages = this.buildRequestHistory(this.chatHistory);
|
||||
|
||||
// Handle Vision Content Injection
|
||||
|
||||
+94
-15
@@ -74,6 +74,16 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
localResourceRoots: [this._extensionUri]
|
||||
};
|
||||
|
||||
// [State Persistence Fix] 사이드바가 다시 보여질 때 세팅값 자동 복원
|
||||
webviewView.onDidChangeVisibility(() => {
|
||||
if (webviewView.visible) {
|
||||
logInfo('Sidebar became visible, restoring state...');
|
||||
void this._sendModels();
|
||||
void this._sendBrainProfiles();
|
||||
void this._sendAgentsList();
|
||||
}
|
||||
});
|
||||
|
||||
webviewView.webview.html = this._getHtml(webviewView.webview);
|
||||
this._agent.setWebview(webviewView.webview);
|
||||
|
||||
@@ -204,6 +214,10 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
case 'deleteAgent':
|
||||
await this._deleteAgent(data.path);
|
||||
break;
|
||||
case 'saveAgentSelection':
|
||||
await this._context.globalState.update(SidebarChatProvider.lastAgentStateKey, data.path || 'none');
|
||||
logInfo(`Agent selection saved: ${data.path}`);
|
||||
break;
|
||||
case 'refreshModels':
|
||||
await this._sendModels();
|
||||
break;
|
||||
@@ -1824,10 +1838,75 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
|
||||
const designerContext = designerGuard !== false ? this._buildDesignerGuardContext() : undefined;
|
||||
|
||||
// [File Processing v2] 파일 타입별 분류 처리
|
||||
let processedPrompt = value || '';
|
||||
let imageFiles: any[] | undefined = undefined;
|
||||
|
||||
if (files && Array.isArray(files) && files.length > 0) {
|
||||
const textContents: string[] = [];
|
||||
const images: any[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
const name = file.name?.toLowerCase() || '';
|
||||
const type = file.type || '';
|
||||
|
||||
if (name.endsWith('.pdf') || type === 'application/pdf') {
|
||||
// PDF: 서버사이드 텍스트 추출 (pdf-parse v2 API)
|
||||
try {
|
||||
const { PDFParse } = require('pdf-parse');
|
||||
const rawBuffer = Buffer.from(file.data, 'base64');
|
||||
const uint8 = new Uint8Array(rawBuffer.buffer, rawBuffer.byteOffset, rawBuffer.byteLength);
|
||||
const parser = new PDFParse(uint8);
|
||||
await parser.load();
|
||||
const textResult = await parser.getText();
|
||||
// pdf-parse v2: getText() returns {pages: [{text, num}], text: string, total: number}
|
||||
const extracted = (typeof textResult === 'string' ? textResult : (textResult?.text || '')).trim();
|
||||
// 페이지 구분 마커 제거하여 깔끔한 텍스트 추출
|
||||
const cleanText = extracted.replace(/\n*-- \d+ of \d+ --\n*/g, '\n').trim();
|
||||
if (cleanText && cleanText.length > 10) {
|
||||
textContents.push(`\n[PDF: ${file.name}]\n${cleanText}`);
|
||||
logInfo(`PDF text extracted successfully.`, { fileName: file.name, chars: cleanText.length });
|
||||
} else {
|
||||
textContents.push(`\n[PDF: ${file.name}]\n(텍스트 추출 결과 없음 - 이미지 기반 PDF일 수 있습니다. 텍스트 레이어가 없는 스캔 문서는 OCR 변환 후 재시도하세요.)`);
|
||||
logInfo(`PDF text extraction returned empty/minimal result.`, { fileName: file.name, rawLength: extracted.length });
|
||||
}
|
||||
} catch (pdfError: any) {
|
||||
logError(`PDF parsing failed.`, { fileName: file.name, error: pdfError?.message || String(pdfError) });
|
||||
textContents.push(`\n[PDF: ${file.name}]\n(PDF 파싱 오류: ${pdfError?.message || '알 수 없는 오류'})`);
|
||||
}
|
||||
} else if (
|
||||
type.startsWith('text/') ||
|
||||
type === 'application/json' ||
|
||||
/\.(txt|md|csv|json|js|ts|jsx|tsx|html|css|py|java|rs|go|yaml|yml|xml|toml|sql|sh)$/i.test(name)
|
||||
) {
|
||||
// 텍스트 파일: base64 디코딩
|
||||
try {
|
||||
const decoded = Buffer.from(file.data, 'base64').toString('utf-8');
|
||||
textContents.push(`\n[FILE: ${file.name}]\n\`\`\`\n${decoded}\n\`\`\``);
|
||||
} catch (decodeError: any) {
|
||||
logError(`Text file decode failed.`, { fileName: file.name, error: decodeError?.message });
|
||||
textContents.push(`\n[FILE: ${file.name}]\n(디코딩 오류)`);
|
||||
}
|
||||
} else if (type.startsWith('image/')) {
|
||||
// 이미지: 기존 vision 방식 유지
|
||||
images.push(file);
|
||||
} else {
|
||||
// 미지원 타입: 파일명만 기록
|
||||
textContents.push(`\n[ATTACHMENT: ${file.name}]\n(지원하지 않는 파일 형식: ${type || 'unknown'})`);
|
||||
}
|
||||
}
|
||||
|
||||
// 추출된 텍스트를 프롬프트에 주입
|
||||
if (textContents.length > 0) {
|
||||
processedPrompt = `${processedPrompt}\n\n--- 첨부 파일 내용 ---${textContents.join('\n')}`;
|
||||
}
|
||||
imageFiles = images.length > 0 ? images : undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
await this._agent.handlePrompt(value, model, {
|
||||
await this._agent.handlePrompt(processedPrompt, model, {
|
||||
internetEnabled: internet,
|
||||
visionContent: files,
|
||||
visionContent: imageFiles,
|
||||
agentSkillContext,
|
||||
negativePrompt,
|
||||
designerContext,
|
||||
@@ -1894,19 +1973,15 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', defaultModel, vscode.ConfigurationTarget.Global);
|
||||
}
|
||||
|
||||
if (models.length > 0 && (!defaultModel || !models.includes(defaultModel))) {
|
||||
// [State Persistence Fix] 저장된 모델이 목록에 없을 때:
|
||||
// 즉시 강제 리셋하는 대신, 현재 모델 목록의 첫 번째를 '폴백 후보'로만 사용.
|
||||
// 단, defaultModel이 완전히 없는 경우에만 실제로 저장함.
|
||||
if (!defaultModel) {
|
||||
defaultModel = models[0];
|
||||
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', defaultModel, vscode.ConfigurationTarget.Global);
|
||||
} else {
|
||||
// 저장된 모델명은 유지하고, UI에는 첫 번째 모델을 보여주되
|
||||
// 설정은 건드리지 않아 다음 번에 같은 모델이 다시 로드될 경우 복원 가능하도록 함
|
||||
logInfo('Saved model not found in current list, using first available as fallback.', { saved: defaultModel, fallback: models[0] });
|
||||
defaultModel = models[0];
|
||||
}
|
||||
if (models.length > 0 && !defaultModel) {
|
||||
// [State Persistence Fix v2] defaultModel이 완전히 비어있을 때만 첫 번째 모델로 설정
|
||||
defaultModel = models[0];
|
||||
await vscode.workspace.getConfiguration('g1nation').update('defaultModel', defaultModel, vscode.ConfigurationTarget.Global);
|
||||
} else if (models.length > 0 && defaultModel && !models.includes(defaultModel)) {
|
||||
// [State Persistence Fix v2] 저장된 모델이 로컬 엔진 목록에 없는 경우:
|
||||
// 강제 리셋하지 않고, 저장된 모델을 목록 선두에 추가하여 사용자 선택을 보존
|
||||
logInfo('Saved model not in local engine list. Preserving user selection.', { saved: defaultModel, localModels: models.slice(0, 3) });
|
||||
models.unshift(defaultModel);
|
||||
}
|
||||
|
||||
const defaultIdx = models.indexOf(defaultModel);
|
||||
@@ -3309,6 +3384,8 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
agentSel.onchange = () => {
|
||||
if (agentSel.value !== 'none') {
|
||||
vscode.postMessage({ type: 'getAgentContent', path: agentSel.value });
|
||||
// [State Persistence Fix] 에이전트 선택값을 즉시 백엔드에 저장
|
||||
vscode.postMessage({ type: 'saveAgentSelection', path: agentSel.value });
|
||||
if (editMode) agentConfigPanel.style.display = 'flex';
|
||||
} else {
|
||||
agentConfigPanel.style.display = 'none';
|
||||
@@ -3316,6 +3393,8 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
editAgentBtn.classList.remove('active');
|
||||
agentPrompt.value = '';
|
||||
negativePrompt.value = '';
|
||||
// [State Persistence Fix] 에이전트 해제도 즉시 저장
|
||||
vscode.postMessage({ type: 'saveAgentSelection', path: 'none' });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+6
-3
@@ -154,7 +154,7 @@ Never say "upload the source code", "provide the files", or "파일 내용을
|
||||
If access fails after trying, explain the failure and only then ask for an upload.
|
||||
|
||||
[STRICT GLOBAL RULES]
|
||||
1. [NO EMOJIS] Never use emojis, icons, or pictorial symbols. Professional text-only output. Exception: the 💡 icon in the suggestion header only.
|
||||
1. [NO EMOJIS - ABSOLUTE RULE] NEVER use ANY emojis, emoticons, Unicode pictorial symbols (including but not limited to emoji, kaomoji, Unicode icons), or decorative symbols anywhere in your response. NO EXCEPTIONS. Use plain text dashes (-) or asterisks (*) for bullets. Use plain markdown ## for headers. This rule overrides ALL other formatting instructions.
|
||||
2. [UNIQUE HEADINGS] Every markdown heading must be unique and appear exactly once.
|
||||
3. [NO INTERNAL LOGS] Never output <details>, "2nd Brain Trace", or "Debug JSON" blocks.
|
||||
4. [NO SECTION LEAKAGE] Never output sections named "요청 요약", "사용자 의도 추론", "프로젝트 기록 대상 확인", "핵심 확인 질문", or "근거 파일 경로".
|
||||
@@ -170,7 +170,7 @@ For conversational replies, quick facts, or simple updates — answer directly w
|
||||
- Root cause of the problem.
|
||||
- Concrete step-by-step instructions: what to change, which files to edit, which commands to run.
|
||||
|
||||
## 💡 제안 ← Optional. Only include if a meaningfully better alternative exists. Omit otherwise.
|
||||
## 제안 ← Optional. Only include if a meaningfully better alternative exists. Omit otherwise.
|
||||
|
||||
[FOLLOW-UP QUESTION RULES]
|
||||
A follow-up question is a precision tool, not a ritual.
|
||||
@@ -228,7 +228,10 @@ If neither condition is met, give a definitive answer and stop.
|
||||
3. When the user says "분석해줘", "봐줘", "확인해줘", "리뷰해줘" with a path — that IS the confirmation. Access the path immediately and run the full analysis in one continuous response. Do not pause to ask "진행할까요?" or "시작할까요?".`;
|
||||
|
||||
export function getSystemPrompt(): string {
|
||||
return BASE_SYSTEM_PROMPT;
|
||||
const now = new Date();
|
||||
const dateTimeStr = now.toLocaleString('ko-KR', { timeZone: 'Asia/Seoul', year: 'numeric', month: '2-digit', day: '2-digit', weekday: 'long', hour: '2-digit', minute: '2-digit' });
|
||||
const isoDate = now.toISOString().split('T')[0];
|
||||
return `${BASE_SYSTEM_PROMPT}\n\n[CURRENT DATE/TIME]\nToday: ${isoDate} (${dateTimeStr})\nUse this date as the absolute reference for any date-related calculations (e.g., "this week", "today", "yesterday").`;
|
||||
}
|
||||
|
||||
export const SYSTEM_PROMPT = BASE_SYSTEM_PROMPT;
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('local project path preflight', () => {
|
||||
expect(inspected).toContain('Access: succeeded');
|
||||
expect(inspected).toContain('Priority file previews');
|
||||
expect(inspected).toContain('package.json');
|
||||
expect(inspected).toContain('src/features/game/systems/CombatSystem.ts');
|
||||
expect(inspected).toContain(path.join('src', 'features', 'game', 'systems', 'CombatSystem.ts'));
|
||||
expect(inspected).toContain('export class CombatSystem');
|
||||
});
|
||||
|
||||
|
||||
@@ -155,11 +155,11 @@ describe('ProjectChronicleManager', () => {
|
||||
expect(fs.existsSync(result.filePath)).toBe(true);
|
||||
}
|
||||
|
||||
expect(discussion.relativePath).toContain('discussions/');
|
||||
expect(decision.relativePath).toContain('decisions/');
|
||||
expect(development.relativePath).toContain('development/');
|
||||
expect(bug.relativePath).toContain('bugs/');
|
||||
expect(retrospective.relativePath).toContain('retrospectives/');
|
||||
expect(discussion.relativePath).toContain('discussions' + path.sep);
|
||||
expect(decision.relativePath).toContain('decisions' + path.sep);
|
||||
expect(development.relativePath).toContain('development' + path.sep);
|
||||
expect(bug.relativePath).toContain('bugs' + path.sep);
|
||||
expect(retrospective.relativePath).toContain('retrospectives' + path.sep);
|
||||
});
|
||||
|
||||
it('lists chronicle records across sections with relative paths', () => {
|
||||
@@ -191,8 +191,8 @@ describe('ProjectChronicleManager', () => {
|
||||
expect(records.length).toBe(2);
|
||||
expect(records.map(record => record.relativePath)).toEqual(
|
||||
expect.arrayContaining([
|
||||
'planning/2026-05-02_record-list.md',
|
||||
'bugs/BUG-0001-list-bug.md'
|
||||
path.join('planning', '2026-05-02_record-list.md'),
|
||||
path.join('bugs', 'BUG-0001-list-bug.md')
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user