aiexecode 1.0.56 → 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.

@@ -1,6 +1,6 @@
1
1
  // Agent Loop: 계획·실행·검증 사이클을 수행하는 핵심 모듈
2
2
  import { orchestrateMission, continueOrchestratorConversation, resetOrchestratorConversation, recordOrchestratorToolResult, getOrchestratorConversation, restoreOrchestratorConversation } from "../ai_based/orchestrator.js";
3
- import { verifyResult, resetVerifierConversation, getVerifierConversation, restoreVerifierConversation } from "../ai_based/verifier.js";
3
+ import { judgeMissionCompletion } from "../ai_based/completion_judge.js";
4
4
  import { execPythonCode, execShellScript } from "./code_executer.js";
5
5
  import { FILE_READER_FUNCTIONS } from "../tools/file_reader.js";
6
6
  import { RIPGREP_FUNCTIONS } from "../tools/ripgrep.js";
@@ -12,7 +12,7 @@ import { clampOutput, formatToolStdout } from "../util/output_formatter.js";
12
12
  import { buildToolHistoryEntry } from "../util/rag_helper.js";
13
13
  import { createSessionData, getLastConversationState, loadPreviousSessions, saveSessionToHistory } from "./session_memory.js";
14
14
  import { uiEvents } from "./ui_events.js";
15
- import { logSystem, logInfo, logSuccess, logWarning, logError, logAssistantMessage, logToolCall, logToolResult, logCodeExecution, logCodeResult, logIteration, logVerificationResult, logMissionComplete, logConversationRestored } from "./output_helper.js";
15
+ import { logSystem, logInfo, logSuccess, logWarning, logError, logAssistantMessage, logToolCall, logToolResult, logCodeExecution, logCodeResult, logIteration, logMissionComplete, logConversationRestored } from "./output_helper.js";
16
16
  import { requiresApproval, requestApproval } from "./tool_approval.js";
17
17
  import { setCurrentSession, saveFileSnapshot, getFileSnapshot } from "./file_integrity.js";
18
18
  import { abortCurrentRequest } from "./ai_request.js";
@@ -23,18 +23,10 @@ import { ERROR_VERBOSITY } from '../config/feature_flags.js';
23
23
 
24
24
  const debugLog = createDebugLogger('session.log', 'session');
25
25
 
26
- /**
27
- * Verifier 사용 여부를 제어하는 상수
28
- * true: Verifier를 통한 검증 사이클 활성화
29
- * false: Verifier 없이 Orchestrator만 실행 (각 iteration마다 자동으로 다음 단계 진행)
30
- */
31
- const ENABLE_VERIFIER = false;
32
-
33
26
  /**
34
27
  * 상수 정의
35
28
  */
36
29
  const MAX_REASONING_ONLY_RESPONSES = 5;
37
- const MAX_WHAT_IT_DID_HISTORY = 12;
38
30
  const DEFAULT_MAX_ITERATIONS = 50;
39
31
  const SUB_MISSION_MAX_LENGTH = 120;
40
32
 
@@ -96,13 +88,15 @@ function cleanupExecutionResult(exeResult, rawStdout, rawStderr) {
96
88
 
97
89
  /**
98
90
  * 메시지 타입 출력을 처리하는 함수
91
+ * @param {Object} output - 메시지 출력 객체
92
+ * @param {boolean} shouldOutput - 메시지를 출력할지 여부 (기본값: false, completion_judge 판단 후 결정)
99
93
  */
100
- function processMessageOutput(output) {
94
+ function processMessageOutput(output, shouldOutput = false) {
101
95
  const rawMessage = output.content?.[0]?.text ?? '';
102
96
  const truncatedMessage = clampOutput(rawMessage);
103
97
 
104
- // 빈 메시지가 아닐 때만 로그 출력 (세션 종료 신호는 출력하지 않음)
105
- if (rawMessage.trim()) {
98
+ // shouldOutput이 true이고 빈 메시지가 아닐 때만 로그 출력
99
+ if (shouldOutput && rawMessage.trim()) {
106
100
  logAssistantMessage(truncatedMessage);
107
101
  }
108
102
 
@@ -309,23 +303,6 @@ async function processCodeExecution(name, argument, toolMap) {
309
303
  }
310
304
 
311
305
 
312
- /**
313
- * 검증 결과 상태 맵
314
- */
315
- const VERIFICATION_DECISION_STATUS = {
316
- 'MISSION_COMPLETE': '✅ Complete',
317
- 'SUBMISSION_COMPLETE': '✅ Subtask Complete',
318
- 'IN_PROGRESS': '⏳ In Progress',
319
- 'REPLAN_NEEDED': '🔄 Needs Replanning'
320
- };
321
-
322
- /**
323
- * 루프 제어 결과 타입 정의
324
- */
325
- const LOOP_CONTROL = {
326
- CONTINUE: 'continue',
327
- BREAK: 'break'
328
- };
329
306
 
330
307
  /**
331
308
  * Orchestrator 응답을 처리하는 함수
@@ -359,6 +336,8 @@ async function processOrchestratorResponses(params) {
359
336
  let hadAnyFunctionCall = false;
360
337
  let stallDetected = false;
361
338
  let missionSolved = false;
339
+ let improvementPoints = '';
340
+ let improvementPointsIsAutoGenerated = false;
362
341
 
363
342
  debugLog(`Starting response processing loop...`);
364
343
  let loopIteration = 0;
@@ -416,6 +395,7 @@ async function processOrchestratorResponses(params) {
416
395
  reasoningOnlyResponses = 0;
417
396
  let executedFunctionCall = false;
418
397
  let lastOutputType = null;
398
+ let pendingMessageOutput = null; // 출력 대기 중인 MESSAGE 저장
419
399
 
420
400
  // 각 출력 처리
421
401
  for (let outputIndex = 0; outputIndex < outputs.length; outputIndex++) {
@@ -445,11 +425,13 @@ async function processOrchestratorResponses(params) {
445
425
  let content;
446
426
 
447
427
  if (MESSAGE) {
448
- debugLog(` Processing MESSAGE output...`);
449
- const { exeResult, content: msgContent } = processMessageOutput(output);
428
+ debugLog(` Processing MESSAGE output (without displaying)...`);
429
+ // 출력하지 않고 저장만 (shouldOutput = false)
430
+ const { exeResult, content: msgContent } = processMessageOutput(output, false);
450
431
  exe_result = exeResult;
451
432
  content = msgContent;
452
- debugLog(` MESSAGE processed: content length ${msgContent?.length || 0}`);
433
+ pendingMessageOutput = output; // 나중에 출력할 수 있도록 저장
434
+ debugLog(` MESSAGE processed (pending): content length ${msgContent?.length || 0}`);
453
435
  }
454
436
 
455
437
  if (FUNCTION_CALL) {
@@ -593,13 +575,101 @@ async function processOrchestratorResponses(params) {
593
575
  // 완료 조건 체크
594
576
  debugLog(`Checking completion conditions...`);
595
577
  if (!executedFunctionCall && lastOutputType === 'message') {
596
- debugLog(`COMPLETION: No function call + message type = mission solved`);
597
- missionSolved = true;
598
- break;
578
+ debugLog(`COMPLETION: No function call + message type - judging if mission is truly complete`);
579
+
580
+ // 세션 중단 확인 (completion_judge 호출 전)
581
+ if (sessionInterrupted) {
582
+ debugLog(`Session interrupted before judgeMissionCompletion, breaking loop`);
583
+ break;
584
+ }
585
+
586
+ // LLM을 통해 실제 완료 여부 판단
587
+ let judgement;
588
+ try {
589
+ judgement = await judgeMissionCompletion({
590
+ what_user_requests: mission
591
+ });
592
+ } catch (err) {
593
+ if (err.name === 'AbortError' || sessionInterrupted) {
594
+ debugLog(`judgeMissionCompletion aborted or interrupted: ${err.name}`);
595
+ break;
596
+ }
597
+ throw err;
598
+ }
599
+
600
+ // 세션 중단 확인 (completion_judge 호출 후)
601
+ if (sessionInterrupted) {
602
+ debugLog(`Session interrupted after judgeMissionCompletion, breaking loop`);
603
+ break;
604
+ }
605
+
606
+ debugLog(`Completion judgement: shouldComplete=${judgement.shouldComplete}, reason=${judgement.reason}, whatUserShouldSay=${judgement.whatUserShouldSay}`);
607
+
608
+ missionSolved = judgement.shouldComplete;
609
+
610
+ if (missionSolved) {
611
+ // 미션이 완료되었다고 판단되면 대기 중인 메시지 출력 후 종료
612
+ debugLog(`Mission judged as complete, displaying pending message and breaking loop`);
613
+ if (pendingMessageOutput) {
614
+ processMessageOutput(pendingMessageOutput, true); // 이제 출력
615
+ }
616
+ break;
617
+ } else {
618
+ // 미션이 완료되지 않았다고 판단되면 메시지를 출력하지 않고 계속 진행
619
+ debugLog(`Mission not complete, continuing without displaying message`);
620
+
621
+ // orchestratorConversation에서 방금 추가된 assistant message에 _internal_only 플래그 추가
622
+ const conversation = getOrchestratorConversation();
623
+ for (let i = conversation.length - 1; i >= 0; i--) {
624
+ const entry = conversation[i];
625
+ if (entry.type === 'message' && entry.role === 'assistant') {
626
+ entry._internal_only = true;
627
+ debugLog(`[_internal_only] Marked assistant message at index ${i} as internal-only (not for display)`);
628
+ break;
629
+ }
630
+ }
631
+
632
+ // whatUserShouldSay를 새로운 사용자 요구사항으로 처리
633
+ if (judgement.whatUserShouldSay && judgement.whatUserShouldSay.trim().length > 0) {
634
+ debugLog(`Treating whatUserShouldSay as new user request: ${judgement.whatUserShouldSay}`);
635
+ // 💬 Auto-continuing 메시지 제거
636
+
637
+ // whatUserShouldSay를 새로운 mission으로 설정하여 루프를 빠져나감
638
+ // 상위 runSession 루프에서 다시 orchestrateMission이 호출될 것임
639
+ improvementPoints = judgement.whatUserShouldSay;
640
+ improvementPointsIsAutoGenerated = true; // auto-generated 플래그 설정
641
+ debugLog(`[_internal_only] Set improvementPointsIsAutoGenerated=true for whatUserShouldSay`);
642
+ missionSolved = false; // 완료되지 않았으므로 상위 루프 계속
643
+ break; // processOrchestratorResponses 루프 종료
644
+ } else {
645
+ // whatUserShouldSay가 없으면 reason을 사용하여 계속 진행
646
+ improvementPoints = judgement.reason;
647
+ debugLog(`Continuing mission with reason: ${judgement.reason}`);
648
+
649
+ // 세션 중단 확인 (continueOrchestratorConversation 호출 전)
650
+ if (sessionInterrupted) {
651
+ debugLog(`Session interrupted before continueOrchestratorConversation, breaking loop`);
652
+ break;
653
+ }
654
+
655
+ try {
656
+ orchestratedResponse = await continueOrchestratorConversation();
657
+ debugLog(`Received response with ${orchestratedResponse?.output?.length || 0} outputs`);
658
+ continue; // 루프 처음으로 돌아가서 새 응답 처리
659
+ } catch (err) {
660
+ if (err.name === 'AbortError' || sessionInterrupted) {
661
+ debugLog(`Conversation aborted or interrupted: ${err.name}`);
662
+ break;
663
+ }
664
+ debugLog(`ERROR in continueOrchestratorConversation: ${err.message}`);
665
+ throw err;
666
+ }
667
+ }
668
+ }
599
669
  }
600
670
 
601
671
  if (!executedFunctionCall) {
602
- debugLog(`COMPLETION: No function call executed, breaking loop`);
672
+ debugLog(`COMPLETION: No function call executed (other cases), breaking loop`);
603
673
  break;
604
674
  }
605
675
 
@@ -623,76 +693,20 @@ async function processOrchestratorResponses(params) {
623
693
  debugLog(` hadAnyFunctionCall: ${hadAnyFunctionCall}`);
624
694
  debugLog(` stallDetected: ${stallDetected}`);
625
695
  debugLog(` missionSolved: ${missionSolved}`);
696
+ debugLog(` improvementPoints: ${improvementPoints}`);
697
+ debugLog(` improvementPointsIsAutoGenerated: ${improvementPointsIsAutoGenerated}`);
626
698
  debugLog(` Total loop iterations: ${loopIteration}`);
627
699
  debugLog(` Final toolUsageHistory: ${toolUsageHistory.length} items`);
628
700
 
629
701
  return {
630
702
  hadAnyFunctionCall,
631
703
  stallDetected,
632
- missionSolved
704
+ missionSolved,
705
+ improvementPoints,
706
+ improvementPointsIsAutoGenerated
633
707
  };
634
708
  }
635
709
 
636
- /**
637
- * 검증 결과에 따라 다음 동작을 결정하는 함수
638
- * @returns {{ loopControl: string, improvementPoints: string, missionSolved: boolean }}
639
- */
640
- function handleVerificationResult(verificationResult) {
641
- const decision = verificationResult.decision;
642
-
643
- switch (decision) {
644
- case 'MISSION_COMPLETE':
645
- return {
646
- loopControl: LOOP_CONTROL.BREAK,
647
- improvementPoints: '',
648
- missionSolved: true
649
- };
650
-
651
- case 'SUBMISSION_COMPLETE':
652
- uiEvents.addSystemMessage('✅ Sub-mission complete; continuing towards full mission completion.');
653
- return {
654
- loopControl: LOOP_CONTROL.CONTINUE,
655
- improvementPoints: verificationResult.improvement_points || '',
656
- missionSolved: false
657
- };
658
-
659
- case 'IN_PROGRESS':
660
- return {
661
- loopControl: LOOP_CONTROL.CONTINUE,
662
- improvementPoints: verificationResult.improvement_points || '',
663
- missionSolved: false
664
- };
665
-
666
- case 'REPLAN_NEEDED':
667
- uiEvents.addSystemMessage('🔄 Revisit approach required - will try a different angle next iteration.');
668
- return {
669
- loopControl: LOOP_CONTROL.CONTINUE,
670
- improvementPoints: verificationResult.improvement_points || '',
671
- missionSolved: false
672
- };
673
-
674
- default:
675
- return {
676
- loopControl: LOOP_CONTROL.CONTINUE,
677
- improvementPoints: '',
678
- missionSolved: false
679
- };
680
- }
681
- }
682
-
683
- /**
684
- * 실행 요약을 생성하는 헬퍼 함수
685
- */
686
- function buildExecutionSummary(executionOutputList) {
687
- return executionOutputList.map((exec_result, index) => {
688
- const toolName = exec_result.more_info?.name || 'unknown';
689
- const operationType = exec_result.more_info?.type || 'unknown';
690
- const stdoutBlock = exec_result.stdout ? `\n\`\`\`\n${exec_result.stdout}\n\`\`\`` : '\n(empty)';
691
- const stderrBlock = exec_result.stderr ? `\n\`\`\`\n${exec_result.stderr}\n\`\`\`` : '\n(empty)';
692
- const ragRefLine = exec_result.rag_reference ? `- RAG Reference: ${exec_result.rag_reference}\n` : '';
693
- return `### Step ${index + 1}\n- Function: \`${toolName}\`\n- Operation Type: \`${operationType}\`\n- Exit Code: ${typeof exec_result.code === 'number' ? exec_result.code : '?'}\n${ragRefLine}- STDOUT:${stdoutBlock}\n- STDERR:${stderrBlock}`;
694
- }).join('\n\n');
695
- }
696
710
 
697
711
 
698
712
  /**
@@ -710,8 +724,6 @@ function buildExecutionSummary(executionOutputList) {
710
724
  * @typedef {Object} AgentLoopResult
711
725
  * @property {boolean} mission_solved - 미션 완료 여부
712
726
  * @property {number} iteration_count - 실행된 반복 횟수
713
- * @property {Array} verification_memory - 검증 메모리
714
- * @property {Array} whatItDidHistory - 수행 작업 히스토리
715
727
  * @property {Array} toolUsageHistory - 도구 사용 히스토리
716
728
  */
717
729
 
@@ -781,13 +793,12 @@ export async function runSession(options) {
781
793
  }
782
794
 
783
795
  // 메모리 초기화
784
- const verification_memory = [];
785
- const whatItDidHistory = [];
786
796
  const toolUsageHistory = [];
787
797
 
788
798
  let mission_solved = false;
789
799
  let iteration_count = 0;
790
800
  let improvement_points = '';
801
+ let improvement_points_is_auto_generated = false; // whatUserShouldSay에서 온 것인지 표시
791
802
 
792
803
  // 대화 상태 복원 또는 리셋
793
804
  const conversationState = getLastConversationState(sessionsToUse);
@@ -797,19 +808,10 @@ export async function runSession(options) {
797
808
  conversationState.orchestratorConversation,
798
809
  conversationState.orchestratorRequestOptions
799
810
  );
800
- if (ENABLE_VERIFIER) {
801
- restoreVerifierConversation(
802
- conversationState.verifierConversation,
803
- conversationState.lastOrchestratorSnapshotLength
804
- );
805
- }
806
811
  // logSuccess('✓ Conversation state restored');
807
812
  } else {
808
813
  // logSystem('ℹ Starting with fresh conversation state');
809
814
  resetOrchestratorConversation();
810
- if (ENABLE_VERIFIER) {
811
- resetVerifierConversation();
812
- }
813
815
  }
814
816
 
815
817
  // Python 사용 가능 여부 확인
@@ -837,40 +839,68 @@ export async function runSession(options) {
837
839
  iteration_count++;
838
840
  logIteration(iteration_count);
839
841
 
840
- // 세션 중단 확인
841
- if (sessionInterrupted) {
842
- break;
843
- }
844
-
845
-
846
- // 세션 중단 확인
847
- if (sessionInterrupted) {
848
- break;
849
- }
850
-
851
842
  // 첫 반복에서 improvement_points 설정
843
+ // (이후 반복에서는 processOrchestratorResponses에서 설정된 값 유지)
852
844
  if (iteration_count === 1) {
853
845
  improvement_points = `${mission}`;
846
+ improvement_points_is_auto_generated = false; // 첫 번째는 실제 사용자 입력
847
+ debugLog(`[ITERATION ${iteration_count}] Setting initial improvement_points: ${improvement_points.substring(0, 100)}`);
848
+ } else if (!improvement_points) {
849
+ // improvementPoints가 설정되지 않았으면 빈 문자열
850
+ improvement_points = '';
851
+ improvement_points_is_auto_generated = false;
852
+ debugLog(`[ITERATION ${iteration_count}] No improvement_points, setting to empty string`);
853
+ } else {
854
+ debugLog(`[ITERATION ${iteration_count}] Using existing improvement_points: ${improvement_points.substring(0, 100)}, isAutoGenerated: ${improvement_points_is_auto_generated}`);
854
855
  }
855
856
 
856
857
  // Orchestrator 실행
858
+ debugLog(`[ITERATION ${iteration_count}] Calling orchestrateMission with improvement_points: "${improvement_points.substring(0, 100)}", isAutoGenerated: ${improvement_points_is_auto_generated}`);
857
859
  let orchestratedMission;
858
860
  try {
859
861
  orchestratedMission = await orchestrateMission({
860
862
  improvement_points: improvement_points,
861
- mcpToolSchemas: mcpToolSchemas
863
+ mcpToolSchemas: mcpToolSchemas,
864
+ isAutoGenerated: improvement_points_is_auto_generated
862
865
  });
863
866
  } catch (err) {
864
867
  // AbortError는 중단으로 처리
865
868
  if (err.name === 'AbortError' || sessionInterrupted) {
869
+ // 중단 시에도 현재까지의 상태를 저장
870
+ currentSessionData.completed_at = new Date().toISOString();
871
+ currentSessionData.mission_solved = false;
872
+ currentSessionData.iteration_count = iteration_count;
873
+ currentSessionData.toolUsageHistory = toolUsageHistory;
874
+ currentSessionData.orchestratorConversation = getOrchestratorConversation();
875
+ currentSessionData.orchestratorRequestOptions = null;
876
+
877
+ debugLog(`[ITERATION ${iteration_count}] Session aborted during orchestration - saving session to history`);
878
+ await saveSessionToHistory(currentSessionData).catch(saveErr => {
879
+ debugLog(`[ITERATION ${iteration_count}] Failed to save session: ${saveErr.message}`);
880
+ });
866
881
  break;
867
882
  }
868
883
  throw err;
869
884
  }
870
- improvement_points = '';
885
+ // improvement_points_is_auto_generated 플래그 리셋 (다음 iteration을 위해)
886
+ improvement_points_is_auto_generated = false;
887
+ // improvement_points는 여기서 리셋하지 않음 (processOrchestratorResponses에서 설정될 수 있음)
888
+ debugLog(`[ITERATION ${iteration_count}] orchestrateMission completed`)
871
889
 
872
890
  // 세션 중단 확인
873
891
  if (sessionInterrupted) {
892
+ // 중단 시에도 현재까지의 상태를 저장
893
+ currentSessionData.completed_at = new Date().toISOString();
894
+ currentSessionData.mission_solved = false;
895
+ currentSessionData.iteration_count = iteration_count;
896
+ currentSessionData.toolUsageHistory = toolUsageHistory;
897
+ currentSessionData.orchestratorConversation = getOrchestratorConversation();
898
+ currentSessionData.orchestratorRequestOptions = null;
899
+
900
+ debugLog(`[ITERATION ${iteration_count}] Session interrupted after orchestration - saving session to history`);
901
+ await saveSessionToHistory(currentSessionData).catch(err => {
902
+ debugLog(`[ITERATION ${iteration_count}] Failed to save session: ${err.message}`);
903
+ });
874
904
  break;
875
905
  }
876
906
 
@@ -905,11 +935,50 @@ export async function runSession(options) {
905
935
  stallDetected = orchestratorResult.stallDetected;
906
936
  mission_solved = orchestratorResult.missionSolved;
907
937
 
938
+ debugLog(`[ITERATION ${iteration_count}] orchestratorResult.improvementPoints: "${orchestratorResult.improvementPoints || '(empty)'}", isAutoGenerated: ${orchestratorResult.improvementPointsIsAutoGenerated}`);
939
+
940
+ // improvementPoints가 반환된 경우 다음 iteration에 사용
941
+ // 반환되지 않은 경우 리셋
942
+ if (orchestratorResult.improvementPoints) {
943
+ improvement_points = orchestratorResult.improvementPoints;
944
+ improvement_points_is_auto_generated = orchestratorResult.improvementPointsIsAutoGenerated || false;
945
+ debugLog(`[ITERATION ${iteration_count}] Setting improvement_points from orchestratorResult: "${improvement_points.substring(0, 100)}", isAutoGenerated: ${improvement_points_is_auto_generated}`);
946
+ } else {
947
+ improvement_points = '';
948
+ improvement_points_is_auto_generated = false;
949
+ debugLog(`[ITERATION ${iteration_count}] No improvementPoints from orchestratorResult, resetting to empty`);
950
+ }
951
+
908
952
  // 세션 중단 확인
909
953
  if (sessionInterrupted) {
954
+ // 중단 시에도 현재까지의 상태를 저장
955
+ currentSessionData.completed_at = new Date().toISOString();
956
+ currentSessionData.mission_solved = false;
957
+ currentSessionData.iteration_count = iteration_count;
958
+ currentSessionData.toolUsageHistory = toolUsageHistory;
959
+ currentSessionData.orchestratorConversation = getOrchestratorConversation();
960
+ currentSessionData.orchestratorRequestOptions = null;
961
+
962
+ debugLog(`[ITERATION ${iteration_count}] Session interrupted - saving session to history`);
963
+ await saveSessionToHistory(currentSessionData).catch(err => {
964
+ debugLog(`[ITERATION ${iteration_count}] Failed to save session: ${err.message}`);
965
+ });
910
966
  break;
911
967
  }
912
968
 
969
+ // 매 iteration마다 세션 히스토리 저장 (실시간 저장)
970
+ currentSessionData.completed_at = new Date().toISOString();
971
+ currentSessionData.mission_solved = mission_solved;
972
+ currentSessionData.iteration_count = iteration_count;
973
+ currentSessionData.toolUsageHistory = toolUsageHistory;
974
+ currentSessionData.orchestratorConversation = getOrchestratorConversation();
975
+ currentSessionData.orchestratorRequestOptions = null;
976
+
977
+ debugLog(`[ITERATION ${iteration_count}] Saving session to history (real-time save)`);
978
+ await saveSessionToHistory(currentSessionData).catch(err => {
979
+ debugLog(`[ITERATION ${iteration_count}] Failed to save session: ${err.message}`);
980
+ });
981
+
913
982
  // 미션 완료 처리
914
983
  if (mission_solved) {
915
984
  break;
@@ -925,63 +994,21 @@ export async function runSession(options) {
925
994
  break;
926
995
  }
927
996
 
928
- // Verifier비활성화된 경우 계속 진행
929
- if (!ENABLE_VERIFIER) {
930
- uiEvents.addSystemMessage('ℹ Verifier disabled - orchestrator continues');
931
- improvement_points = '';
932
- continue;
933
- }
934
-
935
-
936
- // Verifier 실행
937
- const verification_result = await verifyResult({ what_user_requests: mission });
938
- uiEvents.addSystemMessage(`${verification_result.decision}`);
939
- if (false) uiEvents.addSystemMessage(`Verified ${verification_result.improvement_points}`);
940
- if (verification_result.replan_needed) uiEvents.addSystemMessage(`Verified Re-Plan Required`);
941
- if (verification_result.what_it_did) {
942
- whatItDidHistory.push(verification_result.what_it_did);
943
- if (whatItDidHistory.length > MAX_WHAT_IT_DID_HISTORY) {
944
- whatItDidHistory.shift();
945
- }
946
- }
947
-
948
- // Verification memory에 추가
949
- const memoryEntry = {
950
- timestamp: new Date().toISOString(),
951
- mission: mission,
952
- iteration: iteration_count,
953
- what_it_did: verification_result.what_it_did || '',
954
- result: verification_result,
955
- what_it_did_history: [...whatItDidHistory],
956
- tool_history: [...iterationToolHistory]
957
- };
958
-
959
- verification_memory.push(memoryEntry);
960
-
961
- // 미션 상태에 따른 처리
962
- const nextAction = handleVerificationResult(verification_result);
963
- improvement_points = nextAction.improvementPoints;
964
- mission_solved = nextAction.missionSolved;
965
-
966
- if (nextAction.loopControl === LOOP_CONTROL.BREAK) {
967
- break;
968
- }
997
+ // improvement_points설정되어 있으면 다음 iteration 계속 진행
998
+ debugLog(`[ITERATION ${iteration_count}] Continuing with improvement_points: "${improvement_points?.substring(0, 100) || '(empty)'}"`);
999
+ continue;
969
1000
  }
970
1001
 
971
1002
  // 대화 상태 저장
972
1003
  const finalOrchestratorConversation = getOrchestratorConversation();
973
- const finalVerifierConversation = ENABLE_VERIFIER ? getVerifierConversation() : [];
974
1004
 
975
1005
  // 결과 반환
976
1006
  const result = {
977
1007
  mission_solved,
978
1008
  iteration_count,
979
- verification_memory,
980
- whatItDidHistory,
981
1009
  toolUsageHistory,
982
1010
  // 대화 상태도 반환하여 저장할 수 있도록 함
983
1011
  orchestratorConversation: finalOrchestratorConversation,
984
- verifierConversation: finalVerifierConversation,
985
1012
 
986
1013
  previousSessions: sessionsToUse
987
1014
  };
@@ -989,21 +1016,17 @@ export async function runSession(options) {
989
1016
  currentSessionData.completed_at = new Date().toISOString();
990
1017
  currentSessionData.mission_solved = result.mission_solved;
991
1018
  currentSessionData.iteration_count = result.iteration_count;
992
- currentSessionData.verification_memory = result.verification_memory;
993
- currentSessionData.whatItDidHistory = result.whatItDidHistory;
994
1019
  currentSessionData.toolUsageHistory = result.toolUsageHistory;
995
1020
  // previousSessions는 saveSessionToHistory에서 파일로부터 로드하므로 저장하지 않음 (메모리 누적 방지)
996
1021
  // currentSessionData.previousSessions = result.previousSessions;
997
1022
  debugLog('[runSession] previousSessions NOT saved to currentSessionData to prevent exponential growth');
998
1023
  // 대화 상태 저장
999
1024
  currentSessionData.orchestratorConversation = result.orchestratorConversation;
1000
- currentSessionData.verifierConversation = result.verifierConversation;
1001
- currentSessionData.lastOrchestratorSnapshotLength = result.orchestratorConversation?.length || 0;
1002
1025
  currentSessionData.orchestratorRequestOptions = null; // 필요시 orchestrator에서 가져올 수 있음
1003
1026
 
1004
- debugLog(`[runSession] Saving session to history - sessionID: ${currentSessionData.sessionID}`);
1027
+ debugLog(`[runSession] Saving final session to history - sessionID: ${currentSessionData.sessionID}`);
1005
1028
  debugLog(`[runSession] Session data size: ${JSON.stringify(currentSessionData).length} bytes`);
1006
- // 세션 히스토리에 저장
1029
+ // 최종 세션 히스토리에 저장 (중복 저장이지만 최신 상태 보장)
1007
1030
  await saveSessionToHistory(currentSessionData);
1008
1031
 
1009
1032
  return currentSessionData;
@@ -177,14 +177,6 @@ export function buildHistoricalContext(sessions, currentMission) {
177
177
  contextParts.push(`**Status**: ${session.mission_solved ? '✅ Completed' : '❌ Not completed'}`);
178
178
  contextParts.push(`**Iterations**: ${session.iteration_count || 0}`);
179
179
 
180
- // 주요 수행 내역
181
- if (session.whatItDidHistory && session.whatItDidHistory.length > 0) {
182
- contextParts.push(`**Actions Taken**:`);
183
- session.whatItDidHistory.slice(-3).forEach(action => {
184
- contextParts.push(` - ${action}`);
185
- });
186
- }
187
-
188
180
  // 도구 사용 통계
189
181
  if (session.toolUsageHistory && session.toolUsageHistory.length > 0) {
190
182
  const toolCounts = {};
@@ -194,17 +186,6 @@ export function buildHistoricalContext(sessions, currentMission) {
194
186
  contextParts.push(`**Tools Used**: ${Object.entries(toolCounts).map(([name, count]) => `${name}(${count})`).join(', ')}`);
195
187
  }
196
188
 
197
- // 마지막 검증 결과
198
- if (session.verification_memory && session.verification_memory.length > 0) {
199
- const lastVerification = session.verification_memory[session.verification_memory.length - 1];
200
- if (lastVerification.result) {
201
- contextParts.push(`**Final Decision**: ${lastVerification.result.decision}`);
202
- if (lastVerification.result.improvement_points) {
203
- contextParts.push(`**Lessons**: ${lastVerification.result.improvement_points.slice(0, 200)}...`);
204
- }
205
- }
206
- }
207
-
208
189
  contextParts.push('');
209
190
  });
210
191
 
@@ -225,13 +206,9 @@ export function createSessionData(sessionID, mission) {
225
206
  completed_at: null,
226
207
  mission_solved: false,
227
208
  iteration_count: 0,
228
- verification_memory: [],
229
- whatItDidHistory: [],
230
209
  toolUsageHistory: [],
231
210
  // 대화 상태 저장
232
211
  orchestratorConversation: [],
233
- verifierConversation: [],
234
- lastOrchestratorSnapshotLength: 0,
235
212
  orchestratorRequestOptions: null
236
213
  };
237
214
  }
@@ -250,8 +227,6 @@ export function getLastConversationState(sessions) {
250
227
 
251
228
  return {
252
229
  orchestratorConversation: lastSession.orchestratorConversation || [],
253
- verifierConversation: lastSession.verifierConversation || [],
254
- lastOrchestratorSnapshotLength: lastSession.lastOrchestratorSnapshotLength || 0,
255
230
  orchestratorRequestOptions: lastSession.orchestratorRequestOptions || null
256
231
  };
257
232
  }
@@ -290,16 +265,12 @@ export function reconstructUIHistory(sessions) {
290
265
  const conversation = session.orchestratorConversation;
291
266
  debugLog(`orchestratorConversation length: ${conversation.length}`);
292
267
 
293
- // 현재 세션의 시작 지점: 이전 세션의 = 이전 세션의 lastOrchestratorSnapshotLength
268
+ // 현재 세션의 시작 지점: 항상 0부터 시작 (각 세션은 독립적)
294
269
  let startIndex = 0;
295
- if (sessionIndex > 0) {
296
- startIndex = sessions[sessionIndex - 1].lastOrchestratorSnapshotLength || 0;
297
- debugLog(`Previous session lastOrchestratorSnapshotLength: ${startIndex}`);
298
- }
299
270
 
300
- // 현재 세션의 끝 지점: 현재 세션의 lastOrchestratorSnapshotLength
301
- const endIndex = session.lastOrchestratorSnapshotLength || conversation.length;
302
- debugLog(`Current session lastOrchestratorSnapshotLength: ${endIndex}`);
271
+ // 현재 세션의 끝 지점: conversation 전체 길이 사용
272
+ const endIndex = conversation.length;
273
+ debugLog(`Current session conversation length: ${endIndex}`);
303
274
  debugLog(`Processing conversation slice [${startIndex}, ${endIndex}]`);
304
275
 
305
276
  // 현재 세션에서 새로 추가된 대화만 추출
@@ -467,6 +438,12 @@ export function reconstructUIHistory(sessions) {
467
438
 
468
439
  // message 타입 처리 (assistant 응답)
469
440
  if (item.type === 'message' && item.role === 'assistant' && item.content) {
441
+ // _internal_only 플래그가 있으면 건너뛰기
442
+ if (item._internal_only) {
443
+ debugLog(`[reconstructUIHistory] Skipping assistant message with _internal_only flag`);
444
+ continue;
445
+ }
446
+
470
447
  const text = item.content[0]?.text || '';
471
448
  if (text) {
472
449
  uiHistory.push({
@@ -479,6 +456,12 @@ export function reconstructUIHistory(sessions) {
479
456
 
480
457
  // user 메시지 타입 처리
481
458
  if (item.role === 'user' && item.content) {
459
+ // _internal_only 플래그가 있으면 건너뛰기
460
+ if (item._internal_only) {
461
+ debugLog(`[reconstructUIHistory] Skipping user message with _internal_only flag`);
462
+ continue;
463
+ }
464
+
482
465
  const textContent = item.content.find(c => c.type === 'input_text');
483
466
  if (textContent && textContent.text) {
484
467
  uiHistory.push({
@@ -491,10 +474,6 @@ export function reconstructUIHistory(sessions) {
491
474
  }
492
475
  }
493
476
 
494
- // whatItDidHistory와 verification_memory는 orchestratorConversation에
495
- // 이미 포함되어 있으므로 중복 추가하지 않음
496
-
497
- // mission_completed는 UI에서 필터링되므로 추가하지 않음
498
477
  });
499
478
 
500
479
  return uiHistory;