aiexecode 1.0.111 → 1.0.113
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.
Potentially problematic release.
This version of aiexecode might be problematic. Click here for more details.
- package/index.js +135 -59
- package/mcp-agent-lib/src/mcp_message_logger.js +17 -16
- package/package.json +1 -1
- package/payload_viewer/out/404/index.html +1 -1
- package/payload_viewer/out/404.html +1 -1
- package/payload_viewer/out/index.html +1 -1
- package/payload_viewer/out/index.txt +1 -1
- package/prompts/orchestrator.txt +131 -3
- package/src/ai_based/orchestrator.js +27 -2
- package/src/config/feature_flags.js +6 -7
- package/src/system/code_executer.js +30 -2
- package/src/system/conversation_trimmer.js +132 -0
- package/src/system/file_integrity.js +57 -0
- package/src/system/session.js +82 -14
- package/src/system/session_memory.js +30 -2
- package/src/system/system_info.js +254 -40
- package/src/tools/file_reader.js +17 -0
- package/src/util/prompt_loader.js +23 -0
- /package/payload_viewer/out/_next/static/{BqLAmXZiz76q8SE-Oia_y → CRVqYR5xcqEY3rgzrCh4K}/_buildManifest.js +0 -0
- /package/payload_viewer/out/_next/static/{BqLAmXZiz76q8SE-Oia_y → CRVqYR5xcqEY3rgzrCh4K}/_clientMiddlewareManifest.json +0 -0
- /package/payload_viewer/out/_next/static/{BqLAmXZiz76q8SE-Oia_y → CRVqYR5xcqEY3rgzrCh4K}/_ssgManifest.js +0 -0
package/prompts/orchestrator.txt
CHANGED
|
@@ -379,7 +379,33 @@ Use for: Finding code by content, exploring codebases, locating specific impleme
|
|
|
379
379
|
|
|
380
380
|
### bash
|
|
381
381
|
|
|
382
|
-
Purpose: Execute shell commands
|
|
382
|
+
Purpose: Execute shell commands (for terminal operations ONLY)
|
|
383
|
+
|
|
384
|
+
**CRITICAL - Use Specialized Tools Instead of Bash:**
|
|
385
|
+
|
|
386
|
+
NEVER use bash for these operations - use the dedicated tools:
|
|
387
|
+
|
|
388
|
+
| Operation | WRONG (bash) | CORRECT (dedicated tool) |
|
|
389
|
+
|-----------|--------------|--------------------------|
|
|
390
|
+
| Read files | `cat file.js` | `read_file({ filePath: "file.js" })` |
|
|
391
|
+
| Read file sections | `head -100 file.js` | `read_file_range({ filePath, startLine, endLine })` |
|
|
392
|
+
| Search content | `grep -r "pattern" .` | `ripgrep({ pattern: "pattern" })` |
|
|
393
|
+
| Find files | `find . -name "*.js"` | `glob_search({ pattern: "**/*.js" })` |
|
|
394
|
+
| Edit files | `sed -i 's/old/new/' file` | `edit_file_replace({ file_path, old_string, new_string })` |
|
|
395
|
+
| Write files | `echo "content" > file` | `write_file({ file_path, content })` |
|
|
396
|
+
|
|
397
|
+
**Why dedicated tools are mandatory:**
|
|
398
|
+
- bash output is truncated to 8000 chars - long files get cut off
|
|
399
|
+
- Dedicated tools have proper error handling and formatting
|
|
400
|
+
- Dedicated tools integrate with file integrity tracking
|
|
401
|
+
- Dedicated tools display results properly in UI
|
|
402
|
+
|
|
403
|
+
**When to use bash:**
|
|
404
|
+
- git commands: `git status`, `git commit`, `git push`
|
|
405
|
+
- Package management: `npm install`, `pip install`
|
|
406
|
+
- Running scripts: `npm test`, `python script.py`
|
|
407
|
+
- Directory operations: `mkdir`, `rm -rf`, `mv`, `cp`
|
|
408
|
+
- System commands: `chmod`, `chown`, `which`
|
|
383
409
|
|
|
384
410
|
Usage notes:
|
|
385
411
|
- Output limits: stdout 8000 chars, stderr 4000 chars
|
|
@@ -813,10 +839,43 @@ Match the user's language:
|
|
|
813
839
|
|
|
814
840
|
## Tool usage
|
|
815
841
|
|
|
816
|
-
-
|
|
817
|
-
|
|
842
|
+
**MANDATORY - Specialized Tools Over Bash:**
|
|
843
|
+
|
|
844
|
+
This is NOT optional. You MUST use dedicated tools for these operations:
|
|
845
|
+
|
|
846
|
+
| Task | NEVER Use | ALWAYS Use |
|
|
847
|
+
|------|-----------|------------|
|
|
848
|
+
| Read files | cat, head, tail, less | read_file, read_file_range |
|
|
849
|
+
| Search content | grep, rg, ack | ripgrep |
|
|
850
|
+
| Find files | find, ls -R, locate | glob_search |
|
|
851
|
+
| Edit files | sed, awk, perl -i | edit_file_replace |
|
|
852
|
+
| Create/write files | echo >, cat <<EOF | write_file |
|
|
853
|
+
|
|
854
|
+
**Why this matters:**
|
|
855
|
+
- bash output truncated at 8000 chars → long content gets lost
|
|
856
|
+
- Dedicated tools have built-in limits and error handling
|
|
857
|
+
- File integrity tracking only works with dedicated tools
|
|
858
|
+
- Results display properly in UI with dedicated tools
|
|
859
|
+
|
|
860
|
+
**Correct patterns:**
|
|
861
|
+
```
|
|
862
|
+
# Find files → glob_search
|
|
863
|
+
glob_search({ pattern: "**/*.ts" })
|
|
864
|
+
|
|
865
|
+
# Search content → ripgrep
|
|
866
|
+
ripgrep({ pattern: "TODO", output_mode: "content", head_limit: 20 })
|
|
867
|
+
|
|
868
|
+
# Read file → read_file
|
|
869
|
+
read_file({ filePath: "src/index.js" })
|
|
870
|
+
|
|
871
|
+
# Large file → read_file_range
|
|
872
|
+
read_file_range({ filePath: "big.log", startLine: 1, endLine: 500 })
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
**Other tool usage rules:**
|
|
818
876
|
- Auto-exclusions trusted: node_modules, .git, etc. are automatically excluded
|
|
819
877
|
- Parallel when possible: Execute independent tool calls simultaneously
|
|
878
|
+
- Check output limits: ripgrep has 30KB limit, read_file has 2000 line limit
|
|
820
879
|
|
|
821
880
|
## Error handling
|
|
822
881
|
|
|
@@ -1092,3 +1151,72 @@ ASK USER:
|
|
|
1092
1151
|
|
|
1093
1152
|
DECIDE YOURSELF:
|
|
1094
1153
|
- All implementation details (HOW to implement)
|
|
1154
|
+
|
|
1155
|
+
# Web application development
|
|
1156
|
+
|
|
1157
|
+
## Technology stack
|
|
1158
|
+
|
|
1159
|
+
Build web applications using the following technologies:
|
|
1160
|
+
|
|
1161
|
+
1. **Core**: Use HTML for structure and Javascript for logic
|
|
1162
|
+
2. **Styling (CSS)**: Use Vanilla CSS for maximum flexibility and control. Avoid using TailwindCSS unless the user explicitly requests it; in this case, first confirm which TailwindCSS version to use
|
|
1163
|
+
3. **Web App**: If the user specifies a more complex web app, use a framework like Next.js or Vite. Only do this if the user explicitly requests a web app
|
|
1164
|
+
4. **New Project Creation**: If you need to use a framework for a new app, use `npx` with the appropriate script:
|
|
1165
|
+
- Use `npx -y` to automatically install the script and its dependencies
|
|
1166
|
+
- You MUST run the command with `--help` flag to see all available options first
|
|
1167
|
+
- Initialize the app in the current directory with `./` (example: `npx -y create-vite-app@latest ./`)
|
|
1168
|
+
- Run in non-interactive mode so that the user doesn't need to input anything
|
|
1169
|
+
5. **Running Locally**: When running locally, use `npm run dev` or equivalent dev server. Only build the production bundle if the user explicitly requests it or you are validating the code for correctness
|
|
1170
|
+
|
|
1171
|
+
## Design aesthetics
|
|
1172
|
+
|
|
1173
|
+
**CRITICAL: Visual excellence is mandatory. A basic, simple design is UNACCEPTABLE.**
|
|
1174
|
+
|
|
1175
|
+
1. **Rich Aesthetics**: The user should be impressed at first glance. Use best practices in modern web design (vibrant colors, dark modes, glassmorphism, dynamic animations) to create a stunning first impression
|
|
1176
|
+
2. **Visual Excellence**: Implement designs that feel extremely premium:
|
|
1177
|
+
- Avoid generic colors (plain red, blue, green). Use curated, harmonious color palettes (HSL tailored colors, sleek dark modes)
|
|
1178
|
+
- Use modern typography (Google Fonts like Inter, Roboto, or Outfit) instead of browser defaults
|
|
1179
|
+
- Use smooth gradients
|
|
1180
|
+
- Add subtle micro-animations for enhanced user experience
|
|
1181
|
+
3. **Dynamic Design**: An interface that feels responsive and alive encourages interaction. Achieve this with hover effects and interactive elements. Micro-animations are highly effective for improving user engagement
|
|
1182
|
+
4. **Premium Designs**: Make a design that feels premium and state of the art. Avoid creating simple minimum viable products
|
|
1183
|
+
5. **No placeholders**: If you need an image, create actual working demonstrations
|
|
1184
|
+
|
|
1185
|
+
## Implementation workflow
|
|
1186
|
+
|
|
1187
|
+
Follow this systematic approach when building web applications:
|
|
1188
|
+
|
|
1189
|
+
1. **Plan and Understand**:
|
|
1190
|
+
- Fully understand the user's requirements
|
|
1191
|
+
- Draw inspiration from modern, beautiful, and dynamic web designs
|
|
1192
|
+
- Outline the features needed for the initial version
|
|
1193
|
+
|
|
1194
|
+
2. **Build the Foundation**:
|
|
1195
|
+
- Start by creating/modifying `index.css`
|
|
1196
|
+
- Implement the core design system with all tokens and utilities
|
|
1197
|
+
|
|
1198
|
+
3. **Create Components**:
|
|
1199
|
+
- Build necessary components using your design system
|
|
1200
|
+
- Ensure all components use predefined styles, not ad-hoc utilities
|
|
1201
|
+
- Keep components focused and reusable
|
|
1202
|
+
|
|
1203
|
+
4. **Assemble Pages**:
|
|
1204
|
+
- Update the main application to incorporate your design and components
|
|
1205
|
+
- Ensure proper routing and navigation
|
|
1206
|
+
- Implement responsive layouts
|
|
1207
|
+
|
|
1208
|
+
5. **Polish and Optimize**:
|
|
1209
|
+
- Review the overall user experience
|
|
1210
|
+
- Ensure smooth interactions and transitions
|
|
1211
|
+
- Optimize performance where needed
|
|
1212
|
+
|
|
1213
|
+
## SEO best practices
|
|
1214
|
+
|
|
1215
|
+
Automatically implement SEO best practices on every page:
|
|
1216
|
+
|
|
1217
|
+
- **Title Tags**: Include proper, descriptive title tags for each page
|
|
1218
|
+
- **Meta Descriptions**: Add compelling meta descriptions that accurately summarize page content
|
|
1219
|
+
- **Heading Structure**: Use a single `<h1>` per page with proper heading hierarchy
|
|
1220
|
+
- **Semantic HTML**: Use appropriate HTML5 semantic elements
|
|
1221
|
+
- **Unique IDs**: Ensure all interactive elements have unique, descriptive IDs for browser testing
|
|
1222
|
+
- **Performance**: Ensure fast page load times through optimization
|
|
@@ -2,10 +2,10 @@ import dotenv from "dotenv";
|
|
|
2
2
|
// 이 파일은 계획을 실제 행동으로 옮기기 위해 어떤 도구를 호출할지 결정합니다.
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { truncateWithOmit } from "../util/text_formatter.js";
|
|
5
|
-
import { createSystemMessage, createTodoReminder, createSystemReminder } from "../util/prompt_loader.js";
|
|
5
|
+
import { createSystemMessage, createTodoReminder, createSystemReminder, createTrimmedFileReminder } from "../util/prompt_loader.js";
|
|
6
6
|
import { request, shouldRetryWithTrim, getModelForProvider } from "../system/ai_request.js";
|
|
7
7
|
import { supportsCaching } from "../config/ai_models.js";
|
|
8
|
-
import { cleanupOrphanOutputs, trimConversation } from "../system/conversation_trimmer.js";
|
|
8
|
+
import { cleanupOrphanOutputs, trimConversation, getTrimmedFileReads, clearTrimmedFileReads } from "../system/conversation_trimmer.js";
|
|
9
9
|
import { runPythonCodeSchema, bashSchema } from "../system/code_executer.js";
|
|
10
10
|
import { readFileSchema, readFileRangeSchema } from "../tools/file_reader.js";
|
|
11
11
|
import { writeFileSchema, editFileRangeSchema, editFileReplaceSchema } from "../tools/code_editor.js";
|
|
@@ -99,6 +99,20 @@ async function ensureConversationInitialized() {
|
|
|
99
99
|
debugLog(`[ensureConversationInitialized] Added ${currentTodos.length} todos as separate block (uncached)`);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// Trim된 파일 읽기 알림 추가 (파일 경로 알림 기능)
|
|
103
|
+
const trimmedFiles = getTrimmedFileReads();
|
|
104
|
+
if (trimmedFiles.length > 0) {
|
|
105
|
+
const trimmedFileReminder = createTrimmedFileReminder(trimmedFiles);
|
|
106
|
+
if (trimmedFileReminder) {
|
|
107
|
+
contentBlocks.push({
|
|
108
|
+
type: "input_text",
|
|
109
|
+
text: trimmedFileReminder
|
|
110
|
+
// cache_control 없음 - 동적 데이터이므로
|
|
111
|
+
});
|
|
112
|
+
debugLog(`[ensureConversationInitialized] Added trimmed file reminder for ${trimmedFiles.length} files (uncached)`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
102
116
|
systemMessageEntry = {
|
|
103
117
|
role: "system",
|
|
104
118
|
content: contentBlocks
|
|
@@ -133,6 +147,16 @@ async function ensureConversationInitialized() {
|
|
|
133
147
|
debugLog(`[ensureConversationInitialized] Added ${currentTodos.length} todos to system message`);
|
|
134
148
|
}
|
|
135
149
|
|
|
150
|
+
// Trim된 파일 읽기 알림 추가 (파일 경로 알림 기능)
|
|
151
|
+
const trimmedFiles = getTrimmedFileReads();
|
|
152
|
+
if (trimmedFiles.length > 0) {
|
|
153
|
+
const trimmedFileReminder = createTrimmedFileReminder(trimmedFiles);
|
|
154
|
+
if (trimmedFileReminder) {
|
|
155
|
+
systemMessageText += '\n\n' + trimmedFileReminder;
|
|
156
|
+
debugLog(`[ensureConversationInitialized] Added trimmed file reminder for ${trimmedFiles.length} files`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
136
160
|
systemMessageEntry = {
|
|
137
161
|
role: "system",
|
|
138
162
|
content: [
|
|
@@ -178,6 +202,7 @@ function appendResponseToConversation(response) {
|
|
|
178
202
|
export function resetOrchestratorConversation() {
|
|
179
203
|
orchestratorConversation.length = 0;
|
|
180
204
|
orchestratorRequestOptions = null;
|
|
205
|
+
clearTrimmedFileReads(); // 세션 초기화 시 trim된 파일 목록도 초기화
|
|
181
206
|
}
|
|
182
207
|
|
|
183
208
|
export function getOrchestratorConversation() {
|
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* 에러 메시지 상세도 설정
|
|
7
|
+
* 에러 메시지 상세도 설정 (deprecated)
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* 이 설정은 더 이상 사용되지 않습니다.
|
|
10
|
+
* 에러 상세도는 /debug on|off 명령으로 제어됩니다.
|
|
11
|
+
* - /debug off (기본): 사용자 친화적 에러 메시지
|
|
12
|
+
* - /debug on: 상세 에러 정보 (코드, 스택 트레이스 등)
|
|
11
13
|
*/
|
|
12
|
-
export const ERROR_VERBOSITY = 'verbose';
|
|
13
14
|
|
|
14
|
-
export default {
|
|
15
|
-
ERROR_VERBOSITY
|
|
16
|
-
};
|
|
15
|
+
export default {};
|
|
@@ -581,14 +581,42 @@ export const runPythonCodeSchema = {
|
|
|
581
581
|
|
|
582
582
|
export const bashSchema = {
|
|
583
583
|
name: "bash",
|
|
584
|
-
description:
|
|
584
|
+
description: `Executes bash shell commands with optional timeout.
|
|
585
|
+
|
|
586
|
+
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file reading/searching operations - use specialized tools instead.
|
|
587
|
+
|
|
588
|
+
Output Limits:
|
|
589
|
+
- stdout is truncated to 8000 characters
|
|
590
|
+
- stderr is truncated to 4000 characters
|
|
591
|
+
- Commands timing out after 20 minutes will be terminated
|
|
592
|
+
- If output exceeds limits, only the first 70% and last 30% are shown with an omission notice
|
|
593
|
+
|
|
594
|
+
Avoid These Commands (Use Specialized Tools Instead):
|
|
595
|
+
- File reading: Use read_file or read_file_range instead of cat, head, tail
|
|
596
|
+
- Content search: Use ripgrep instead of grep or rg
|
|
597
|
+
- File search: Use glob_search instead of find
|
|
598
|
+
- File editing: Use edit_file_replace or write_file instead of sed, awk, echo >
|
|
599
|
+
|
|
600
|
+
When Output May Be Large:
|
|
601
|
+
- Limit output with: command | head -50
|
|
602
|
+
- Save to file: command > output.log 2>&1
|
|
603
|
+
- Filter results: command | grep "pattern"
|
|
604
|
+
- Use quiet/minimal flags when available
|
|
605
|
+
|
|
606
|
+
Best Practices:
|
|
607
|
+
- Use auto-confirm flags: -y, -f, --yes, --quiet
|
|
608
|
+
- Chain commands with && for sequential execution
|
|
609
|
+
- Avoid interactive commands that require user input
|
|
610
|
+
- For calculations, use non-interactive bc or Python (never mental arithmetic)
|
|
611
|
+
|
|
612
|
+
This tool handles: file system operations (mkdir, rm, mv, cp, chmod), git commands, package management (npm, pip), and CLI tools.`,
|
|
585
613
|
parameters: {
|
|
586
614
|
type: "object",
|
|
587
615
|
required: ["script"],
|
|
588
616
|
properties: {
|
|
589
617
|
script: {
|
|
590
618
|
type: "string",
|
|
591
|
-
description: "Bash script to execute. Will be saved to a temporary file and run with bash.
|
|
619
|
+
description: "Bash script to execute. Will be saved to a temporary file and run with bash. Keep scripts concise and output-limited to avoid truncation."
|
|
592
620
|
}
|
|
593
621
|
},
|
|
594
622
|
additionalProperties: false
|
|
@@ -6,9 +6,100 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { createDebugLogger } from "../util/debug_log.js";
|
|
9
|
+
import { clearFileContentHash } from "./file_integrity.js";
|
|
9
10
|
|
|
10
11
|
const debugLog = createDebugLogger('conversation_trimmer.log', 'conversation_trimmer');
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Trim 과정에서 삭제된 파일 읽기 정보를 추적합니다.
|
|
15
|
+
* Claude Code 스타일의 "파일 경로 알림" 기능을 위해 사용됩니다.
|
|
16
|
+
*
|
|
17
|
+
* 예: "Note: /path/to/file was read before trimming, but contents are too large to include."
|
|
18
|
+
*/
|
|
19
|
+
const trimmedFileReads = new Set();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* trimmedFileReads의 최대 개수 제한
|
|
23
|
+
* 너무 많은 파일이 추적되면 system-reminder가 길어져 토큰 낭비 발생
|
|
24
|
+
*/
|
|
25
|
+
const MAX_TRIMMED_FILE_READS = 50;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Trim된 파일 읽기 목록을 반환합니다.
|
|
29
|
+
* @returns {Array<string>} 삭제된 파일 경로 배열
|
|
30
|
+
*/
|
|
31
|
+
export function getTrimmedFileReads() {
|
|
32
|
+
return Array.from(trimmedFileReads);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Trim된 파일 읽기 목록을 초기화합니다.
|
|
37
|
+
*/
|
|
38
|
+
export function clearTrimmedFileReads() {
|
|
39
|
+
trimmedFileReads.clear();
|
|
40
|
+
debugLog(`[clearTrimmedFileReads] Cleared trimmed file reads`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Trim된 파일 읽기 목록을 설정합니다 (세션 복원용).
|
|
45
|
+
* 최대 개수 제한을 적용합니다.
|
|
46
|
+
* @param {Array<string>} paths - 복원할 파일 경로 배열
|
|
47
|
+
*/
|
|
48
|
+
export function setTrimmedFileReads(paths) {
|
|
49
|
+
trimmedFileReads.clear();
|
|
50
|
+
if (Array.isArray(paths)) {
|
|
51
|
+
// 최대 개수만큼만 추가 (최근 것 우선)
|
|
52
|
+
const pathsToAdd = paths.slice(-MAX_TRIMMED_FILE_READS);
|
|
53
|
+
pathsToAdd.forEach(path => trimmedFileReads.add(path));
|
|
54
|
+
debugLog(`[setTrimmedFileReads] Restored ${trimmedFileReads.size} trimmed file reads`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 파일이 다시 읽혔을 때 trimmedFileReads에서 제거합니다.
|
|
60
|
+
* 파일을 다시 읽으면 대화에 내용이 있으므로 알림이 필요 없습니다.
|
|
61
|
+
* @param {string} filePath - 다시 읽은 파일 경로
|
|
62
|
+
*/
|
|
63
|
+
export function markFileAsReRead(filePath) {
|
|
64
|
+
if (trimmedFileReads.has(filePath)) {
|
|
65
|
+
trimmedFileReads.delete(filePath);
|
|
66
|
+
debugLog(`[markFileAsReRead] Removed from trimmed file reads: ${filePath}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* 대화 항목에서 파일 읽기 정보를 추출합니다.
|
|
72
|
+
* @param {Object} entry - 대화 항목
|
|
73
|
+
* @returns {Array<string>} 추출된 파일 경로 배열
|
|
74
|
+
*/
|
|
75
|
+
function extractFilePathsFromEntry(entry) {
|
|
76
|
+
const filePaths = [];
|
|
77
|
+
|
|
78
|
+
if (!entry) return filePaths;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// function_call_output에서 파일 읽기 결과 추출
|
|
82
|
+
if (entry.type === 'function_call_output' && entry.output) {
|
|
83
|
+
const output = typeof entry.output === 'string' ? JSON.parse(entry.output) : entry.output;
|
|
84
|
+
|
|
85
|
+
// read_file, read_file_range 도구의 결과인지 확인
|
|
86
|
+
if (output.tool === 'read_file' || output.tool === 'read_file_range') {
|
|
87
|
+
const result = output.original_result || output;
|
|
88
|
+
// 성공적으로 읽은 파일만 추적 (실패한 파일은 알림 불필요)
|
|
89
|
+
if (result.target_file_path && result.operation_successful === true) {
|
|
90
|
+
filePaths.push(result.target_file_path);
|
|
91
|
+
debugLog(`[extractFilePathsFromEntry] Found file path: ${result.target_file_path}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} catch (e) {
|
|
96
|
+
// JSON 파싱 실패 등은 무시
|
|
97
|
+
debugLog(`[extractFilePathsFromEntry] Failed to parse entry: ${e.message}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return filePaths;
|
|
101
|
+
}
|
|
102
|
+
|
|
12
103
|
/**
|
|
13
104
|
* 대화에서 특정 call_id와 관련된 모든 항목을 제거합니다.
|
|
14
105
|
*
|
|
@@ -103,6 +194,9 @@ export function cleanupOrphanOutputs(conversation) {
|
|
|
103
194
|
* 컨텍스트 윈도우 초과 시 대화를 줄입니다.
|
|
104
195
|
* 시스템 프롬프트(인덱스 0)를 제외한 가장 오래된 항목(인덱스 1)을 제거합니다.
|
|
105
196
|
*
|
|
197
|
+
* 삭제되는 항목에서 파일 읽기 정보를 추출하여 trimmedFileReads에 저장합니다.
|
|
198
|
+
* 이 정보는 나중에 system-reminder로 에이전트에게 알려줄 때 사용됩니다.
|
|
199
|
+
*
|
|
106
200
|
* @param {Array} conversation - 대화 배열
|
|
107
201
|
* @returns {boolean} 제거 성공 여부
|
|
108
202
|
*/
|
|
@@ -119,15 +213,53 @@ export function trimConversation(conversation) {
|
|
|
119
213
|
|
|
120
214
|
debugLog(`[trimConversation] Target entry at index 1: type=${targetEntry?.type}, call_id=${targetCallId}`);
|
|
121
215
|
|
|
216
|
+
// 삭제 전에 파일 경로 추출
|
|
217
|
+
const filePaths = extractFilePathsFromEntry(targetEntry);
|
|
218
|
+
filePaths.forEach(path => {
|
|
219
|
+
// 최대 개수 초과 시 가장 오래된 항목 제거
|
|
220
|
+
if (trimmedFileReads.size >= MAX_TRIMMED_FILE_READS) {
|
|
221
|
+
const oldest = trimmedFileReads.values().next().value;
|
|
222
|
+
trimmedFileReads.delete(oldest);
|
|
223
|
+
debugLog(`[trimConversation] Removed oldest from trimmed file reads: ${oldest}`);
|
|
224
|
+
}
|
|
225
|
+
trimmedFileReads.add(path);
|
|
226
|
+
debugLog(`[trimConversation] Added to trimmed file reads: ${path}`);
|
|
227
|
+
|
|
228
|
+
// file_integrity에서 해시도 삭제 (에이전트가 파일 내용을 모르므로 편집 불가하게)
|
|
229
|
+
const hashCleared = clearFileContentHash(path);
|
|
230
|
+
debugLog(`[trimConversation] Cleared content hash for ${path}: ${hashCleared}`);
|
|
231
|
+
});
|
|
232
|
+
|
|
122
233
|
// 먼저 인덱스 1 항목 제거
|
|
123
234
|
conversation.splice(1, 1);
|
|
124
235
|
debugLog(`[trimConversation] Removed entry at index 1`);
|
|
125
236
|
|
|
126
237
|
// call_id가 있으면 같은 call_id를 가진 다른 항목들도 제거
|
|
127
238
|
if (targetCallId) {
|
|
239
|
+
// 삭제 전에 관련 항목들에서 파일 경로 추출
|
|
240
|
+
for (const entry of conversation) {
|
|
241
|
+
if (entry && entry.call_id === targetCallId) {
|
|
242
|
+
const paths = extractFilePathsFromEntry(entry);
|
|
243
|
+
paths.forEach(path => {
|
|
244
|
+
// 최대 개수 초과 시 가장 오래된 항목 제거
|
|
245
|
+
if (trimmedFileReads.size >= MAX_TRIMMED_FILE_READS) {
|
|
246
|
+
const oldest = trimmedFileReads.values().next().value;
|
|
247
|
+
trimmedFileReads.delete(oldest);
|
|
248
|
+
debugLog(`[trimConversation] Removed oldest from trimmed file reads: ${oldest}`);
|
|
249
|
+
}
|
|
250
|
+
trimmedFileReads.add(path);
|
|
251
|
+
debugLog(`[trimConversation] Added related file to trimmed reads: ${path}`);
|
|
252
|
+
|
|
253
|
+
// file_integrity에서 해시도 삭제 (에이전트가 파일 내용을 모르므로 편집 불가하게)
|
|
254
|
+
const hashCleared = clearFileContentHash(path);
|
|
255
|
+
debugLog(`[trimConversation] Cleared content hash for ${path}: ${hashCleared}`);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
128
259
|
removeEntriesWithCallId(conversation, targetCallId);
|
|
129
260
|
}
|
|
130
261
|
|
|
131
262
|
debugLog(`[trimConversation] Trim completed. New conversation length: ${conversation.length}`);
|
|
263
|
+
debugLog(`[trimConversation] Total trimmed file reads: ${trimmedFileReads.size}`);
|
|
132
264
|
return true;
|
|
133
265
|
}
|
|
@@ -112,6 +112,38 @@ class FileIntegrityTracker {
|
|
|
112
112
|
return sessionFiles.get(filePath) || null;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/**
|
|
116
|
+
* 파일 콘텐츠 해시를 삭제합니다
|
|
117
|
+
* 대화가 trim되어 에이전트가 파일 내용을 알 수 없게 되었을 때 호출됩니다.
|
|
118
|
+
* 이렇게 하면 에이전트가 파일을 다시 읽기 전까지 편집할 수 없습니다.
|
|
119
|
+
* @param {string} sessionID - 세션 ID
|
|
120
|
+
* @param {string} filePath - 파일 경로
|
|
121
|
+
* @returns {boolean} 삭제 성공 여부
|
|
122
|
+
*/
|
|
123
|
+
clearContentHash(sessionID, filePath) {
|
|
124
|
+
debugLog(`========== clearContentHash START ==========`);
|
|
125
|
+
debugLog(`sessionID: ${sessionID}`);
|
|
126
|
+
debugLog(`filePath: ${filePath}`);
|
|
127
|
+
|
|
128
|
+
const sessionFiles = this.contentHashes.get(sessionID);
|
|
129
|
+
if (!sessionFiles) {
|
|
130
|
+
debugLog(`No session map found for session: ${sessionID}`);
|
|
131
|
+
debugLog(`========== clearContentHash END (NO SESSION) ==========`);
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const existed = sessionFiles.has(filePath);
|
|
136
|
+
if (existed) {
|
|
137
|
+
sessionFiles.delete(filePath);
|
|
138
|
+
debugLog(`Hash deleted for file: ${filePath}`);
|
|
139
|
+
} else {
|
|
140
|
+
debugLog(`No hash found for file: ${filePath}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
debugLog(`========== clearContentHash END ==========`);
|
|
144
|
+
return existed;
|
|
145
|
+
}
|
|
146
|
+
|
|
115
147
|
/**
|
|
116
148
|
* 파일 편집 전 무결성을 검증합니다
|
|
117
149
|
* @param {string} sessionID - 세션 ID
|
|
@@ -347,6 +379,31 @@ export async function assertFileIntegrity(filePath) {
|
|
|
347
379
|
debugLog('========== assertFileIntegrity (export wrapper) END ==========');
|
|
348
380
|
}
|
|
349
381
|
|
|
382
|
+
/**
|
|
383
|
+
* 파일 콘텐츠 해시를 삭제합니다 (현재 세션 기준)
|
|
384
|
+
* 대화가 trim되어 에이전트가 파일 내용을 알 수 없게 되었을 때 호출됩니다.
|
|
385
|
+
* @param {string} filePath - 파일 경로
|
|
386
|
+
* @returns {boolean} 삭제 성공 여부
|
|
387
|
+
*/
|
|
388
|
+
export function clearFileContentHash(filePath) {
|
|
389
|
+
debugLog(`========== clearFileContentHash (export wrapper) START ==========`);
|
|
390
|
+
debugLog(`filePath: ${filePath}`);
|
|
391
|
+
|
|
392
|
+
const sessionID = fileIntegrityTracker.getCurrentSession();
|
|
393
|
+
debugLog(`Current session ID: ${sessionID || 'NULL'}`);
|
|
394
|
+
|
|
395
|
+
if (!sessionID) {
|
|
396
|
+
debugLog(`ERROR: No current session set, cannot clear hash`);
|
|
397
|
+
debugLog('========== clearFileContentHash (export wrapper) END ==========');
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const result = fileIntegrityTracker.clearContentHash(sessionID, filePath);
|
|
402
|
+
debugLog(`Hash clear result: ${result}`);
|
|
403
|
+
debugLog('========== clearFileContentHash (export wrapper) END ==========');
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
|
|
350
407
|
/**
|
|
351
408
|
* 파일 스냅샷을 저장합니다 (현재 세션 기준)
|
|
352
409
|
* @param {string} filePath - 파일 경로
|