aiexecode 1.0.57 → 1.0.58

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.

@@ -673,7 +673,7 @@ export async function edit_file_range({ file_path, start_line, end_line, new_con
673
673
  // edit_file_replace 스키마
674
674
  export const editFileReplaceSchema = {
675
675
  "name": "edit_file_replace",
676
- "description": "Performs exact string replacements in files (Claude Code style).\n\nUSAGE:\n- You must have read the file at least once before editing. This tool will error if you attempt an edit without reading the file.\n- When editing text from file reader output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. Never include any part of the line number prefix in the old_string or new_string.\n- The edit will FAIL if old_string is not unique in the file. Provide a larger string with more surrounding context to make it unique.\n\nCONTENT PURITY - CRITICAL: old_string and new_string must be EXACT file content. Include ONLY the actual code - NO explanatory text, NO markdown blocks, NO instructions.\n\nWRONG: \"Here's the code:\\nfunction foo() {}\" or \"```javascript\\ncode\\n```\"\nCORRECT: \"function foo() {\\n return true;\\n}\"",
676
+ "description": "Performs exact string replacements in files (Claude Code style).\n\nUSAGE:\n- You must have read the file at least once before editing. This tool will error if you attempt an edit without reading the file.\n- When editing text from file reader output, ensure you preserve the exact indentation (tabs/spaces) as it appears AFTER the line number prefix. Never include any part of the line number prefix in the old_string or new_string.\n- The edit will FAIL if old_string is not unique in the file. Provide a larger string with more surrounding context to make it unique.\n\nTOKEN EFFICIENCY - CRITICAL: MINIMIZE old_string length.\n- Include ONLY the minimum code needed to uniquely identify the change location\n- Start with just the line(s) you want to modify\n- If rejected with 'not unique' error, incrementally add surrounding context\n- Strategy: (1) Try minimal old_string first (2) If rejected, add 1-2 lines context (3) Repeat until unique\n- Balance: Too short = not unique, Too long = wastes tokens\n- Example WASTEFUL: Including 30 lines when 1 line would be unique\n- Example EFFICIENT: \"const tax = 0.1;\" (if unique)\n- Example EFFICIENT: \"function calc() {\\n const tax = 0.1;\\n}\" (when context needed)\n\nCONTENT PURITY - CRITICAL: old_string and new_string must be EXACT file content. Include ONLY the actual code - NO explanatory text, NO markdown blocks, NO instructions.\n\nWRONG: \"Here's the code:\\nfunction foo() {}\" or \"```javascript\\ncode\\n```\"\nCORRECT: \"function foo() {\\n return true;\\n}\"",
677
677
  "strict": false,
678
678
  "parameters": {
679
679
  "type": "object",
@@ -684,7 +684,7 @@ export const editFileReplaceSchema = {
684
684
  },
685
685
  "old_string": {
686
686
  "type": "string",
687
- "description": "The exact text to replace (must be unique in file). Must match file content exactly including all whitespace and indentation."
687
+ "description": "The exact text to replace (must be unique in file). Must match file content exactly including all whitespace and indentation. MINIMIZE length: start with just the line to change, add context only if rejected for not being unique."
688
688
  },
689
689
  "new_string": {
690
690
  "type": "string",
@@ -6,14 +6,14 @@ export async function response_message({ message = "" }) {
6
6
 
7
7
  export const responseMessageSchema = {
8
8
  "name": "response_message",
9
- "description": "사용자에게 메시지를 전달할 사용합니다. 도구는 다른 도구와 함께 사용해야 하며, 단독으로 사용해서는 됩니다. 작업을 수행하는 다른 도구들과 병렬로 호출하여 진행 상황을 알려주는 용도입니다.",
9
+ "description": "CORE PRINCIPLE: This tool reports completed or ongoing actions to the user. ZERO TOLERANCE FOR INTERROGATIVES: Never use interrogative form. Never seek user input or decisions. Content must be purely declarative statements about what was done or what is being done. Also forbidden: code explanations, implementation details, technical descriptions.",
10
10
  "strict": true,
11
11
  "parameters": {
12
12
  "type": "object",
13
13
  "properties": {
14
14
  "message": {
15
15
  "type": "string",
16
- "description": "사용자에게 전달할 메시지"
16
+ "description": "FUNDAMENTAL RULE: Use only declarative mood to report actions performed or in progress. ABSOLUTE PROHIBITION: Interrogative mood in any form. Never request, ask, or seek. State what happened or what is happening. Never explain code or implementation. Keep concise and action-focused."
17
17
  }
18
18
  },
19
19
  "required": ["message"],
@@ -18,7 +18,6 @@ function buildRipgrepArgs({
18
18
  contextBefore = 0,
19
19
  contextAfter = 0,
20
20
  context = 0,
21
- showLineNumbers = false,
22
21
  multiline = false,
23
22
  maxCount = DEFAULT_MAX_COUNT,
24
23
  includeHidden = false
@@ -32,9 +31,6 @@ function buildRipgrepArgs({
32
31
  args.push('--count');
33
32
  } else if (outputMode === 'content') {
34
33
  args.push('--json');
35
- if (showLineNumbers) {
36
- args.push('--line-number');
37
- }
38
34
  } else {
39
35
  args.push('--json');
40
36
  }
@@ -222,7 +218,6 @@ function parseJsonOutput(buffer) {
222
218
  if (!data || !data.path || !data.lines) return;
223
219
 
224
220
  const filePath = data.path.text;
225
- const lineNumber = data.line_number;
226
221
  const lineContent = data.lines.text;
227
222
 
228
223
  // 파일별로 그룹화
@@ -230,22 +225,7 @@ function parseJsonOutput(buffer) {
230
225
  fileResults[filePath] = [];
231
226
  }
232
227
 
233
- const matchInfo = {
234
- lineNumber: lineNumber,
235
- lineContent: lineContent
236
- };
237
-
238
- // submatch 정보가 있으면 추가
239
- if (data.submatches && data.submatches.length > 0) {
240
- const submatch = data.submatches[0];
241
- matchInfo.match = {
242
- text: submatch.match.text,
243
- startColumn: submatch.start,
244
- endColumn: submatch.end
245
- };
246
- }
247
-
248
- fileResults[filePath].push(matchInfo);
228
+ fileResults[filePath].push(lineContent);
249
229
  }
250
230
  } catch (_) {
251
231
  // JSON 파싱 실패 시 무시
@@ -259,7 +239,7 @@ function parseJsonOutput(buffer) {
259
239
  * 파일 목록 출력을 파싱합니다
260
240
  */
261
241
  function parseFileListOutput(buffer) {
262
- return buffer.split('\n').filter(Boolean).map(file => ({ file_path: file }));
242
+ return buffer.split('\n').filter(Boolean);
263
243
  }
264
244
 
265
245
  /**
@@ -267,15 +247,14 @@ function parseFileListOutput(buffer) {
267
247
  */
268
248
  function parseCountOutput(buffer) {
269
249
  const lines = buffer.split('\n').filter(Boolean);
270
- const counts = [];
250
+ const counts = {};
271
251
 
272
252
  lines.forEach((line) => {
273
253
  const match = line.match(/^(.+):(\d+)$/);
274
254
  if (match) {
275
- counts.push({
276
- file_path: match[1],
277
- match_count: parseInt(match[2], 10)
278
- });
255
+ const filePath = match[1];
256
+ const count = parseInt(match[2], 10);
257
+ counts[filePath] = count;
279
258
  }
280
259
  });
281
260
 
@@ -295,7 +274,6 @@ export async function ripgrep({
295
274
  contextBefore = 0,
296
275
  contextAfter = 0,
297
276
  context = 0,
298
- showLineNumbers = false,
299
277
  multiline = false,
300
278
  maxCount = DEFAULT_MAX_COUNT,
301
279
  includeHidden = false,
@@ -326,7 +304,6 @@ export async function ripgrep({
326
304
  contextBefore,
327
305
  contextAfter,
328
306
  context,
329
- showLineNumbers,
330
307
  multiline,
331
308
  maxCount,
332
309
  includeHidden
@@ -343,22 +320,22 @@ export async function ripgrep({
343
320
  totalMatches = results.length;
344
321
  } else if (outputMode === 'count') {
345
322
  results = parseCountOutput(stdout);
346
- totalMatches = results.reduce((sum, r) => sum + r.match_count, 0);
323
+ totalMatches = Object.values(results).reduce((sum, count) => sum + count, 0);
347
324
  } else {
348
325
  results = parseJsonOutput(stdout);
349
326
  // 파일별 그룹화된 결과에서 총 매치 수 계산
350
327
  totalMatches = Object.values(results).reduce((sum, matches) => sum + matches.length, 0);
351
328
  }
352
329
 
353
- // headLimit 적용 (content 모드에서는 적용 안함 - 이미 파일별로 그룹화됨)
354
- if (headLimit && headLimit > 0 && outputMode !== 'content') {
330
+ // headLimit 적용 (files_with_matches 모드에서만 적용)
331
+ if (headLimit && headLimit > 0 && outputMode === 'files_with_matches') {
355
332
  results = results.slice(0, headLimit);
356
333
  }
357
334
 
358
335
  const noResult = !timeout && code === 1 && (
359
- outputMode === 'content'
360
- ? Object.keys(results).length === 0
361
- : results.length === 0
336
+ outputMode === 'files_with_matches'
337
+ ? results.length === 0
338
+ : Object.keys(results).length === 0
362
339
  );
363
340
  const success = !timeout && (code === 0 || noResult);
364
341
 
@@ -431,10 +408,6 @@ export const ripgrepSchema = {
431
408
  type: 'number',
432
409
  description: '매칭 전후 N줄 표시 (선택 사항, content 모드에서만)',
433
410
  },
434
- showLineNumbers: {
435
- type: 'boolean',
436
- description: '라인 번호 표시 (선택 사항, content 모드에서만)',
437
- },
438
411
  multiline: {
439
412
  type: 'boolean',
440
413
  description: '멀티라인 검색 활성화 (선택 사항, 여러 줄에 걸친 패턴 매칭)',
@@ -391,8 +391,7 @@ function StandardDisplay({ item, isPending, hasFollowingResult, nextItem, isLast
391
391
  contextAroundPrefix: contextAroundPrefix,
392
392
  resultArgs: {
393
393
  operation_successful: originalResult?.operation_successful,
394
- hasFileSnapshot: !!originalResult?.fileSnapshot,
395
- replace_all: effectiveArgs.replace_all
394
+ hasFileSnapshot: !!originalResult?.fileSnapshot
396
395
  }
397
396
  };
398
397
 
@@ -411,7 +410,7 @@ function StandardDisplay({ item, isPending, hasFollowingResult, nextItem, isLast
411
410
  effectiveArgs.old_string || '',
412
411
  effectiveArgs.new_string || '',
413
412
  content,
414
- effectiveArgs.replace_all || true
413
+ false
415
414
  );
416
415
 
417
416
  if (result.error) {
@@ -403,7 +403,7 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
403
403
  args.old_string || '',
404
404
  args.new_string || '',
405
405
  content,
406
- args.replace_all || true
406
+ false
407
407
  );
408
408
 
409
409
  setDiffData(result);
@@ -417,9 +417,6 @@ function renderToolArgs(toolName, args, mcpToolInfo = null) {
417
417
  React.createElement(Text, { bold: true, color: 'cyan' }, 'File '),
418
418
  React.createElement(Text, { color: 'white' }, toDisplayPath(args.file_path))
419
419
  ),
420
- args.replace_all && React.createElement(Box, { marginBottom: 0 },
421
- React.createElement(Text, { color: 'yellow' }, 'replace_all: true (will replace ALL occurrences)')
422
- ),
423
420
  diffData ? (
424
421
  diffData.error ?
425
422
  React.createElement(Text, { color: 'red' }, `Error: ${diffData.error}`) :
@@ -1,216 +0,0 @@
1
- 당신은 AIEXE AI 에이전트 멤버 중 하나인 Verifier로서, 작업 결과를 검증하는 역할을 담당합니다.
2
- 실행된 작업 결과에 대한 철저한 분석을 수행하여 정확하고 신뢰할 수 있는 검증을 실시하세요.
3
-
4
- **중요: 당신은 사용자의 목표 달성 여부를 판단하는 실용적인 검증 전문가입니다.**
5
-
6
- ---
7
-
8
- ### <최상위 원칙: 실용적 목표 달성주의>
9
- **가장 중요한 단 하나의 원칙은 "사용자의 명시적 요구사항이 해결되었는가?" 입니다.** 코드 품질, 잠재적 개선점, 스타일 등 다른 모든 요소는 이 최상위 원칙에 종속됩니다.
10
-
11
- - **핵심 목표 달성이 유일한 기준:** 설령 사소한 개선점(예: 코드 스타일, 주석 부족)이 보이더라도, 사용자가 요청한 핵심 기능이나 결과가 성공적으로 구현되었다면 **`MISSION_COMPLETE`**로 판단해야 합니다.
12
- - **개선점 제시는 미완료 과업을 위함:** 개선점 지적은 `IN_PROGRESS`나 `REPLAN_NEEDED` 상태의 작업을 올바른 방향으로 이끌기 위한 것입니다.
13
- - **완료된 미션에 대한 개선 제안 금지:** 요구사항이 충족되었다면, 어떠한 개선점도 제시해서는 안 됩니다. **이는 최상위 원칙에 정면으로 위배되는 행동입니다.**
14
-
15
- ---
16
-
17
- ### <절대 준수 규칙>
18
- 1. **`MISSION_COMPLETE` 시 `improvement_points`는 반드시 빈 문자열("")이어야 합니다.**
19
- 2. 이 규칙은 **예외 없이 적용**되며, 여기에 사소한 의견이나 제안이라도 포함하는 것은 **엄격히 금지됩니다.**
20
- 3. 완료된 미션에 대해 개선점을 제시하는 것은 **검증 실패**로 간주합니다.
21
-
22
- ---
23
-
24
- <what_user_requests>
25
- 사용자의 요구사항:
26
- {{what_user_requests}}
27
- </what_user_requests>
28
-
29
- <verification_philosophy>
30
- 검증 에이전트 시스템의 목적은 오직 **사용자의 요구사항이 달성되었는지를 판단하기 위함**입니다. 객관적이고 체계적인 기준을 통해 작업 완료도를 정확하게 평가하고 다음 단계로의 진행 여부를 합리적으로 결정합니다. 완벽함보다는 **요구사항의 완전한 충족**을 목표로 합니다.
31
- </verification_philosophy>
32
-
33
- <verification_scope>
34
- 다음 관점에서 코드 편집 작업 결과를 종합적으로 검증:
35
- - **요구사항 완전성 (최우선)**: README나 사용자 지시의 모든 항목이 완료되었는지 확인
36
- - 구현 정확성: 요청된 변경사항이 올바르게 구현되었는지 확인
37
- - 기능 보존: 수정 후 기존 기능이 그대로 유지되는지 확인
38
- - 코드 정확성: 편집된 코드가 구문적으로 올바르고 논리적으로 건전한지 여부
39
- - 코드 통합: 새로운/수정된 코드가 기존 코드베이스와 적절히 통합되는지 확인
40
- - 파일 의존성 검증: require/import하는 파일들이 모두 존재하는지 확인
41
- - 코드 품질: 가독성, 구조, 코딩 규칙 준수 평가 (요구사항 달성에 영향을 주지 않는다면 부차적 요소로 간주)
42
- </verification_scope>
43
-
44
- <decision_criteria>
45
- 검증 결과 결정 기준:
46
-
47
- **MISSION_COMPLETE (전체 미션 완료):**
48
- - **사용자의 명시적 요구사항(`what_user_requests`)이 완전히 해결됨.**
49
- - 사소한 코드 스타일 문제나 잠재적 개선점이 남아있더라도, 요청의 핵심 목표가 달성되었다면 미션은 완료된 것입니다.
50
- - 추가 작업 없이 사용자가 만족할 수 있는 최종 산출물이 나옴.
51
- - **`improvement_points`는 <절대 준수 규칙>에 따라 반드시 빈 문자열("")이어야 합니다.**
52
-
53
- **SUBMISSION_COMPLETE (현재 서브 미션 완료):**
54
- - 현재 서브 미션 목표가 성공적으로 달성됨.
55
- - 다음 단계로 진행하기에 충분한 산출물 확보.
56
- - 오류나 중대한 결함이 없음.
57
-
58
- **IN_PROGRESS (서브 미션 진행 중):**
59
- - 현재 서브 미션이 부분적으로만 완료됨.
60
- - 사용자의 최종 목표 달성을 위해 추가 작업이나 수정이 필요함.
61
-
62
- **REPLAN_NEEDED (계획 수정 필요):**
63
- - 현재 계획이 사용자의 목표 달성에 부적절함.
64
- - 근본적인 접근법 변경이 필요함.
65
-
66
- </decision_criteria>
67
-
68
- <improvement_guidance>
69
- ## 효과적인 개선 지침 작성
70
-
71
- **지침 작성의 목적:**
72
- - 개선 지침의 유일한 목적은 **미완료된 작업(`SUBMISSION_COMPLETE`, `IN_PROGRESS`)을 완료로 이끌기 위함**입니다.
73
- - **<절대 준수 규칙>에 따라, `MISSION_COMPLETE`로 판정된 작업에 대해서는 어떠한 개선점도 제시해서는 안 됩니다.**
74
-
75
- **지침 작성 원칙:**
76
- - `MISSION_COMPLETE` 결정 시 `improvement_points`는 빈 문자열("")로 설정합니다.
77
- - (미완료 작업에 대해) 구체적이고 실행 가능한 개선사항을 명확하게 제시합니다.
78
- - 왜 그 개선이 '사용자의 요구사항 달성'을 위해 필요한지 간단한 근거를 포함합니다.
79
- </improvement_guidance>
80
-
81
- <verification_process>
82
- ## 체계적 검증 프로세스
83
-
84
- **검증 수행 단계:**
85
-
86
- ### 1. 초기 이해 및 맥락 파악
87
- - 원래 요청사항과 목표를 명확히 재확인
88
- - 수행된 작업의 범위와 내용을 정확히 파악
89
- - 예상되었던 결과와 실제 결과 비교를 위한 기준 설정
90
- - 관련 제약사항이나 특수 요구사항 고려
91
-
92
- ### 2. 심층 분석 및 검토
93
- - 코드 변경사항을 줄별로 세밀하게 검토
94
- - 구문 오류, 논리 오류, 의미적 오류가 없는지 확인
95
- - 기존 코드와의 일관성 및 통합성 점검
96
- - 잠재적 부작용이나 예상치 못한 영향 탐지
97
-
98
- ### 3. 기능적 검증
99
- - 구현된 기능이 요구사항을 정확히 충족하는지 확인
100
- - 다양한 시나리오와 입력값에서의 동작 검증
101
- - 경계 조건 및 예외 상황 처리 적절성 평가
102
- - 성능 및 효율성 측면 고려
103
-
104
- ### 4. 품질 및 유지보수성 평가
105
- - 코드 가독성, 구조, 명명 규칙 준수 평가
106
- - 문서화 및 주석의 적절성 검토
107
- - 향후 확장성 및 수정 용이성 고려
108
- - 보안 및 안정성 측면 검토
109
-
110
- ### 5. 최종 종합 판단
111
- - 모든 검증 결과를 종합하여 객관적 결론 도출
112
- - 미완성 부분이나 개선이 필요한 영역 명확히 식별
113
- - 다음 단계 진행 여부에 대한 명확한 권고사항 제시
114
- - 발견된 문제의 우선순위와 긴급도 평가
115
-
116
- **검증 시 주의사항:**
117
- - 성급한 결론보다는 신중하고 철저한 분석을 우선시
118
- - 추측이나 가정에 의존하지 말고 명확한 증거에 기반하여 판단
119
- - 작은 문제라도 놓치지 않고 누적되면 큰 문제가 될 수 있음을 인식
120
- - 근본 원인을 파악하여 일시적 해결이 아닌 본질적 해결 방향 제시
121
- </verification_process>
122
-
123
- <evaluation_framework>
124
- 코드 편집을 위한 구조화된 평가 프레임워크:
125
-
126
- 1. 코드 수정 분석:
127
-    - 편집된 코드가 구문적으로 올바른지 확인
128
-    - 결과의 논리적 일관성 검토
129
-    - 의도된 변경사항이 정확하게 반영되었는지 확인
130
-    - 편집 과정에서 도입된 오류나 누락 확인
131
-
132
- 2. 요구사항 충족:
133
-    - 요청된 기능 변경이 올바르게 구현되었는지 확인
134
-    - 편집 목표가 얼마나 잘 달성되었는지 측정
135
-    - 지정된 동작이 예상대로 작동하는지 검증
136
-    - 사용자 요구사항과의 일치성 확인
137
-
138
- 3. 코드 품질 및 스타일:
139
-    - 기존 코드 스타일과의 일관성 유지
140
-    - 가독성 및 구조적 명확성 평가
141
-    - 명명 규칙 및 코딩 규칙 준수 확인
142
-    - 중복 줄이기 및 실용적인 효율성 개선
143
-
144
- 4. 기능 호환성:
145
-    - 기존 기능이 계속 작동하는지 확인
146
-    - 다른 모듈과의 인터페이스 호환성 확인
147
-    - 종속성이 적절히 처리되는지 확인
148
-    - 하위 호환성 보존
149
-
150
- 5. 통합 및 안정성:
151
-    - 변경사항이 전체 시스템 내에서 어떻게 통합되는지 평가
152
-    - 예상치 못한 부작용이나 버그 감시
153
-    - 경계 조건 및 예외 처리 검토
154
-    - 변경사항이 시스템에 미치는 영향 평가
155
-
156
- 6. 완전성 및 유지보수성:
157
-    - 편집 작업의 전반적인 완전성 확인
158
-    - 주석 및 설명의 적절성 검토
159
-    - 향후 수정 및 확장의 용이성 고려
160
-    - 코드가 이해하기 쉽고 잘 문서화되어 있는지 확인
161
- </evaluation_framework>
162
-
163
- <response_style>
164
- ## 명확하고 효과적인 검증 응답
165
-
166
- **응답 구성 원칙:**
167
- - 결론을 먼저 명시하고, 필요한 경우에만 간단한 근거 제시
168
- - what_it_did는 실제로 수행된 작업의 핵심만 한 문장으로 요약
169
- - improvement_points는 구체적이고 실행 가능한 행동 중심으로 작성
170
- - 불필요한 맥락 반복이나 장식적 표현 배제
171
-
172
- **효과적인 응답 스타일:**
173
- - 간결하면서도 필요한 정보는 누락 없이 포함
174
- - 기술적 용어 사용 시 명확하고 정확한 표현 선택
175
- - 비판적이지만 건설적인 톤 유지
176
- - 문제점 지적 시에는 반드시 해결 방향도 함께 제시
177
-
178
- **피해야 할 응답 패턴:**
179
- - 과도하게 장황한 설명이나 정당화
180
- - 추상적이거나 모호한 표현
181
- - 부정적 평가만 하고 개선 방향이 없는 응답
182
- - 원래 요청사항이나 맥락을 불필요하게 반복하는 것
183
-
184
- **응답 품질 자체 점검:**
185
- - 이 응답을 받는 Orchestrator가 즉시 다음 행동을 취할 수 있는가?
186
- - 문제의 우선순위와 중요도가 명확히 전달되었는가?
187
- - 근거가 객관적이고 검증 가능한가?
188
- - 전체적으로 건설적이고 도움이 되는 내용인가?
189
- </response_style>
190
-
191
- <verification_consistency>
192
- ## 일관되고 신뢰할 수 있는 검증
193
-
194
- **검증 일관성 원칙:**
195
- - 모든 검증에서 동일한 기준과 프로세스를 균일하게 적용
196
- - 이전 검증 결과와의 연속성과 학습 효과 고려
197
- - 미션의 복잡성, 중요도, 위험도에 따른 적절한 엄격도 조정
198
- - 검증자의 주관이나 선호가 아닌 객관적 사실과 증거에만 의존
199
-
200
- **엄격도 조정 기준:**
201
- - **높은 엄격도**: 핵심 시스템 변경, 보안 관련, 데이터 무결성 영향
202
- - **보통 엄격도**: 일반적인 기능 추가나 수정, 성능 개선
203
- - **기본 엄격도**: 문서 업데이트, 코드 정리, 스타일 개선
204
-
205
- **지속적인 품질 향상:**
206
- - 검증 과정에서 발견한 패턴이나 반복되는 문제점 기록
207
- - 효과적이었던 검증 방법이나 놓친 부분에 대한 학습
208
- - 검증 기준의 적절성과 완전성을 지속적으로 개선
209
- - 프로젝트 특성에 맞는 검증 포인트 발굴 및 적용
210
-
211
- **검증 품질 보장:**
212
- - 성급한 승인이나 과도한 거부 모두 지양
213
- - 기능적 완전성을 최우선으로 하되, 코드 품질도 균형있게 고려
214
- - 완벽주의로 인한 지연보다는 실용적이고 점진적인 개선 추구
215
- - 검증 결과에 대한 자신의 확신도와 근거의 강도를 항상 점검
216
- </verification_consistency>
@@ -1,210 +0,0 @@
1
- import dotenv from "dotenv";
2
- import { request, isContextWindowError, getModelForProvider } from "../system/ai_request.js";
3
- import { getOrchestratorConversation } from "./orchestrator.js";
4
- import { createSystemMessage } from "../util/prompt_loader.js";
5
-
6
- dotenv.config({ quiet: true });
7
-
8
- const verificationSchema = {
9
- name: "verification_result",
10
- schema: {
11
- type: "object",
12
- properties: {
13
- decision: {
14
- type: "string",
15
- description: "Verification verdict (MISSION_COMPLETE: full mission accomplished, SUBMISSION_COMPLETE: sub-mission completed, IN_PROGRESS: sub-mission still in progress, REPLAN_NEEDED: plan must be revised)",
16
- enum: ["MISSION_COMPLETE", "SUBMISSION_COMPLETE", "IN_PROGRESS", "REPLAN_NEEDED"]
17
- },
18
- what_it_did: {
19
- type: "string",
20
- description: "Short summary in one sentence of what it did"
21
- },
22
- improvement_points: {
23
- type: "string",
24
- description: "Concise list of required improvements",
25
- minLength: 1
26
- },
27
- replan_needed: {
28
- type: "boolean",
29
- description: "Whether the current plan must be rebuilt"
30
- }
31
- },
32
- required: ["decision", "what_it_did", "improvement_points", "replan_needed"],
33
- additionalProperties: false
34
- },
35
- strict: true
36
- };
37
-
38
- // systemMessage는 verifyResult 호출 시 동적으로 생성됨
39
-
40
- const verifierConversation = [];
41
- let lastOrchestratorSnapshotLength = 0;
42
-
43
- function cloneMessage(message) {
44
- return JSON.parse(JSON.stringify(message));
45
- }
46
-
47
-
48
- async function createVerifierRequestOptions() {
49
- const model = await getModelForProvider();
50
- return {
51
- taskName: 'verifier',
52
- model,
53
- isGpt5Model: model.startsWith("gpt-5")
54
- };
55
- }
56
-
57
- /**
58
- * Verifier conversation을 초기화하거나 시스템 프롬프트를 업데이트합니다.
59
- * 매 요청마다 프롬프트 파일을 새로 읽어서 변경사항을 즉시 반영합니다.
60
- */
61
- async function ensureVerifierConversationInitialized(templateVars = {}) {
62
- // 매번 최신 시스템 프롬프트를 로드
63
- const systemMessage = await createSystemMessage("verifier.txt", templateVars);
64
-
65
- const systemMessageEntry = {
66
- role: "system",
67
- content: [
68
- {
69
- type: "input_text",
70
- text: systemMessage.content
71
- }
72
- ]
73
- };
74
-
75
- // conversation이 비어있으면 새로 추가
76
- if (!verifierConversation.length) {
77
- verifierConversation.push(systemMessageEntry);
78
- } else {
79
- // conversation이 있으면 첫 번째 system 메시지를 업데이트
80
- if (verifierConversation[0]?.role === "system") {
81
- verifierConversation[0] = systemMessageEntry;
82
- } else {
83
- // system 메시지가 맨 앞에 없으면 추가
84
- verifierConversation.unshift(systemMessageEntry);
85
- }
86
- }
87
- }
88
-
89
- function appendResponseToConversation(response) {
90
- if (!response?.output || !Array.isArray(response.output)) {
91
- return;
92
- }
93
-
94
- for (const item of response.output) {
95
- if (!item) continue;
96
- verifierConversation.push(cloneMessage(item));
97
- }
98
- }
99
-
100
- function syncOrchestratorConversation() {
101
- const sourceConversation = getOrchestratorConversation();
102
- if (!Array.isArray(sourceConversation) || !sourceConversation.length) {
103
- return;
104
- }
105
-
106
- for (let i = lastOrchestratorSnapshotLength; i < sourceConversation.length; i++) {
107
- const entry = sourceConversation[i];
108
- if (!entry) continue;
109
-
110
- // Verifier는 자체 system 메시지를 유지하므로, Orchestrator의 system 메시지는 제외
111
- if (entry.role === "system") continue;
112
-
113
- // reasoning과 message를 모두 그대로 복사
114
- // ai_request.js에서 이미 reasoning-message 쌍이 유지되고 있음
115
- verifierConversation.push(cloneMessage(entry));
116
- }
117
-
118
- lastOrchestratorSnapshotLength = sourceConversation.length;
119
- }
120
-
121
- function trimVerifierConversation() {
122
- for (let i = 1; i < verifierConversation.length - 1; i++) {
123
- const candidate = verifierConversation[i];
124
- if (candidate?.role !== "system") {
125
- verifierConversation.splice(i, 1);
126
- return true;
127
- }
128
- }
129
- return false;
130
- }
131
-
132
- async function dispatchVerifierRequest(options) {
133
- if (!options) {
134
- throw new Error('Verifier request options not initialized.');
135
- }
136
-
137
- while (true) {
138
- const { model, isGpt5Model, taskName } = options;
139
- const requestPayload = {
140
- model,
141
- input: verifierConversation,
142
- text: {
143
- format: {
144
- type: "json_schema",
145
- name: verificationSchema.name,
146
- strict: verificationSchema.strict,
147
- schema: verificationSchema.schema
148
- }
149
- },
150
- reasoning: {},
151
- tool_choice: "none",
152
- tools: [],
153
- top_p: 1,
154
- store: true
155
- };
156
-
157
- if (!isGpt5Model) {
158
- requestPayload.temperature = 0;
159
- }
160
-
161
- try {
162
- return await request(taskName, requestPayload);
163
- } catch (error) {
164
- if (!isContextWindowError(error)) {
165
- throw error;
166
- }
167
-
168
- const trimmed = trimVerifierConversation();
169
- if (!trimmed) {
170
- throw error;
171
- }
172
- }
173
- }
174
- }
175
-
176
- export function resetVerifierConversation() {
177
- verifierConversation.length = 0;
178
- lastOrchestratorSnapshotLength = 0;
179
- }
180
-
181
- export function getVerifierConversation() {
182
- return verifierConversation;
183
- }
184
-
185
- export function restoreVerifierConversation(savedConversation, savedSnapshotLength = 0) {
186
- verifierConversation.length = 0;
187
- if (Array.isArray(savedConversation)) {
188
- verifierConversation.push(...savedConversation);
189
- }
190
- lastOrchestratorSnapshotLength = savedSnapshotLength;
191
- }
192
-
193
- export async function verifyResult(templateVars = {}) {
194
- const requestOptions = await createVerifierRequestOptions();
195
-
196
- // Verifier 자체 system 메시지 초기화 (템플릿 변수 전달)
197
- await ensureVerifierConversationInitialized(templateVars);
198
- // Orchestrator의 대화 내용 동기화 (system 메시지 제외)
199
- syncOrchestratorConversation();
200
-
201
- const response = await dispatchVerifierRequest(requestOptions);
202
- // Verifier 자신의 응답은 히스토리에 추가하지 않음 (Orchestrator와 동일한 히스토리 유지)
203
- // appendResponseToConversation(response);
204
-
205
- try {
206
- return JSON.parse(response.output_text);
207
- } catch (error) {
208
- throw new Error('Verifier response did not include valid JSON output_text.');
209
- }
210
- }