aiexecode 1.0.126 → 1.0.127

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,35 +1,70 @@
1
1
  /**
2
2
  * Output Helper - UI 이벤트 발생
3
+ * Pipe mode에서는 stderr로 출력하거나 무시
3
4
  */
4
5
 
5
6
  import { uiEvents } from './ui_events.js';
6
7
 
8
+ // Pipe mode 감지
9
+ const isPipeMode = () => process.app_custom?.pipeMode === true;
10
+
7
11
  export function logSystem(message) {
8
- uiEvents.addSystemMessage(message);
12
+ if (isPipeMode()) {
13
+ console.error(`[SYSTEM] ${message}`);
14
+ } else {
15
+ uiEvents.addSystemMessage(message);
16
+ }
9
17
  }
10
18
 
11
19
  export function logError(message) {
12
- uiEvents.addErrorMessage(message);
20
+ if (isPipeMode()) {
21
+ console.error(`[ERROR] ${message}`);
22
+ } else {
23
+ uiEvents.addErrorMessage(message);
24
+ }
13
25
  }
14
26
 
15
27
  export function logAssistantMessage(message) {
16
- uiEvents.addAssistantMessage(message);
28
+ if (isPipeMode()) {
29
+ console.error(`[ASSISTANT] ${message}`);
30
+ } else {
31
+ uiEvents.addAssistantMessage(message);
32
+ }
17
33
  }
18
34
 
19
35
  export function logToolCall(toolName, args) {
20
- uiEvents.startToolExecution(toolName, args);
36
+ if (isPipeMode()) {
37
+ console.error(`[TOOL] ${toolName}`);
38
+ } else {
39
+ uiEvents.startToolExecution(toolName, args);
40
+ }
21
41
  }
22
42
 
23
43
  export function logToolResult(toolName, stdout, originalResult = null, toolInput = null, fileSnapshot = null) {
24
- uiEvents.addToolResult(toolName, { stdout, originalResult, fileSnapshot }, toolInput);
44
+ if (isPipeMode()) {
45
+ // Pipe mode에서는 도구 결과를 간략하게 stderr로
46
+ const preview = stdout?.substring(0, 200) || '';
47
+ console.error(`[TOOL_RESULT] ${toolName}: ${preview}${stdout?.length > 200 ? '...' : ''}`);
48
+ } else {
49
+ uiEvents.addToolResult(toolName, { stdout, originalResult, fileSnapshot }, toolInput);
50
+ }
25
51
  }
26
52
 
27
53
  export function logCodeExecution(language, code) {
28
- uiEvents.startCodeExecution(language, code);
54
+ if (isPipeMode()) {
55
+ console.error(`[CODE] ${language}`);
56
+ } else {
57
+ uiEvents.startCodeExecution(language, code);
58
+ }
29
59
  }
30
60
 
31
61
  export function logCodeResult(stdout, stderr, exitCode) {
32
- uiEvents.addCodeResult(stdout, stderr, exitCode);
62
+ if (isPipeMode()) {
63
+ if (stdout) console.error(`[CODE_STDOUT] ${stdout.substring(0, 200)}${stdout.length > 200 ? '...' : ''}`);
64
+ if (stderr) console.error(`[CODE_STDERR] ${stderr.substring(0, 200)}${stderr.length > 200 ? '...' : ''}`);
65
+ } else {
66
+ uiEvents.addCodeResult(stdout, stderr, exitCode);
67
+ }
33
68
  }
34
69
 
35
70
  export function logIteration(iterationNumber) {
@@ -38,9 +73,17 @@ export function logIteration(iterationNumber) {
38
73
  }
39
74
 
40
75
  export function logMissionComplete() {
41
- uiEvents.missionCompleted(0);
76
+ if (isPipeMode()) {
77
+ console.error('[COMPLETE] Mission completed');
78
+ } else {
79
+ uiEvents.missionCompleted(0);
80
+ }
42
81
  }
43
82
 
44
83
  export function logConversationRestored(count) {
45
- uiEvents.conversationRestored(count);
84
+ if (isPipeMode()) {
85
+ console.error(`[RESTORED] ${count} conversation(s) restored`);
86
+ } else {
87
+ uiEvents.conversationRestored(count);
88
+ }
46
89
  }
@@ -1,7 +1,8 @@
1
1
  // Agent Loop: 계획·실행·검증 사이클을 수행하는 핵심 모듈
2
2
  import { orchestrateMission, continueOrchestratorConversation, resetOrchestratorConversation, recordOrchestratorToolResult, getOrchestratorConversation, restoreOrchestratorConversation } from "../ai_based/orchestrator.js";
3
3
  import { judgeMissionCompletion } from "../ai_based/completion_judge.js";
4
- import { execPythonCode, execShellScript } from "./code_executer.js";
4
+ import { execPythonCode, execShellScript, resetShellCwd } from "./code_executer.js";
5
+ import { runInBackground, getBackgroundProcess } from "./background_process.js";
5
6
  import { FILE_READER_FUNCTIONS } from "../tools/file_reader.js";
6
7
  import { RIPGREP_FUNCTIONS } from "../tools/ripgrep.js";
7
8
  import { GLOB_FUNCTIONS } from "../tools/glob.js";
@@ -30,6 +31,47 @@ import {
30
31
 
31
32
  const debugLog = createDebugLogger('session.log', 'session');
32
33
 
34
+ // Pipe mode helper: UI 이벤트를 조건부로 처리
35
+ const isPipeMode = () => process.app_custom?.pipeMode === true;
36
+
37
+ // Pipe mode에서는 stderr로 출력, 일반 모드에서는 uiEvents 사용
38
+ const safeUiEvents = {
39
+ addSystemMessage: (msg) => {
40
+ if (isPipeMode()) {
41
+ console.error(`[SYSTEM] ${msg}`);
42
+ } else {
43
+ uiEvents.addSystemMessage(msg);
44
+ }
45
+ },
46
+ addErrorMessage: (msg) => {
47
+ if (isPipeMode()) {
48
+ console.error(`[ERROR] ${msg}`);
49
+ } else {
50
+ uiEvents.addErrorMessage(msg);
51
+ }
52
+ },
53
+ sessionStart: (msg) => {
54
+ if (!isPipeMode()) {
55
+ uiEvents.sessionStart(msg);
56
+ }
57
+ },
58
+ sessionEnd: () => {
59
+ if (!isPipeMode()) {
60
+ uiEvents.sessionEnd();
61
+ }
62
+ },
63
+ on: (event, handler) => {
64
+ if (!isPipeMode()) {
65
+ uiEvents.on(event, handler);
66
+ }
67
+ },
68
+ off: (event, handler) => {
69
+ if (!isPipeMode()) {
70
+ uiEvents.off(event, handler);
71
+ }
72
+ }
73
+ };
74
+
33
75
 
34
76
  /**
35
77
  * 서브미션 이름을 추론하는 헬퍼 함수
@@ -397,7 +439,7 @@ async function processOrchestratorResponses(params) {
397
439
  debugLog(`No processable output, reasoningOnlyResponses: ${reasoningOnlyResponses}`);
398
440
  if (reasoningOnlyResponses >= MAX_REASONING_ONLY_RESPONSES) {
399
441
  debugLog(`Reached MAX_REASONING_ONLY_RESPONSES (${MAX_REASONING_ONLY_RESPONSES}), treating as stall`);
400
- uiEvents.addSystemMessage('⚠ Orchestrator stalled (reasoning only) - treating as completion');
442
+ safeUiEvents.addSystemMessage('⚠ Orchestrator stalled (reasoning only) - treating as completion');
401
443
  stallDetected = true;
402
444
  break;
403
445
  }
@@ -816,14 +858,14 @@ export async function runSession(options) {
816
858
  if (!sessionInterrupted) {
817
859
  sessionInterrupted = true;
818
860
  abortCurrentRequest(); // API 요청 즉시 중단
819
- uiEvents.addErrorMessage('Session interrupted by user');
861
+ safeUiEvents.addErrorMessage('Session interrupted by user');
820
862
  debugLog('[runSession] Session interrupted by user');
821
863
  }
822
864
  };
823
- uiEvents.on('session:interrupt', handleInterrupt);
865
+ safeUiEvents.on('session:interrupt', handleInterrupt);
824
866
 
825
867
  // 세션 시작 알림
826
- uiEvents.sessionStart('Running agent session...');
868
+ safeUiEvents.sessionStart('Running agent session...');
827
869
 
828
870
  // catch 블록에서도 접근 가능하도록 try 블록 밖에서 선언
829
871
  let currentSessionData = null;
@@ -917,6 +959,11 @@ export async function runSession(options) {
917
959
  updateCurrentTodos([]);
918
960
  debugLog(`[runSession] Starting fresh session - no todos in memory`);
919
961
  }
962
+
963
+ // 새 세션 시작 시 쉘의 작업 디렉토리를 프로젝트 루트로 리셋
964
+ // (이전 미션에서 cd한 디렉토리가 남아있지 않도록)
965
+ await resetShellCwd();
966
+ debugLog(`[runSession] Shell cwd reset to: ${process.cwd()}`);
920
967
  }
921
968
 
922
969
  // Python 사용 가능 여부 확인
@@ -932,7 +979,23 @@ export async function runSession(options) {
932
979
  ...TODO_WRITE_FUNCTIONS,
933
980
  ...SKILL_FUNCTIONS, // 스킬 호출 도구
934
981
  ...mcpToolFunctions,
935
- "bash": async (args) => execShellScript(args.script)
982
+ "bash": async (args) => {
983
+ if (args.background) {
984
+ // 백그라운드 실행
985
+ const result = await runInBackground(args.script);
986
+ return {
987
+ stdout: `Background process started: ${result.id} (pid: ${result.pid})`,
988
+ stderr: '',
989
+ code: 0,
990
+ background: true,
991
+ processId: result.id,
992
+ pid: result.pid
993
+ };
994
+ } else {
995
+ // 일반 실행
996
+ return execShellScript(args.script);
997
+ }
998
+ }
936
999
  };
937
1000
 
938
1001
  // Python이 있는 경우에만 Python 관련 도구 추가
@@ -1132,7 +1195,7 @@ export async function runSession(options) {
1132
1195
  const message = stallDetected
1133
1196
  ? '⚠ Session ended due to orchestrator stall'
1134
1197
  : '✅ No function calls detected - mission complete';
1135
- uiEvents.addSystemMessage(message);
1198
+ safeUiEvents.addSystemMessage(message);
1136
1199
  debugLog(`[ITERATION ${iteration_count}] ${message}`);
1137
1200
 
1138
1201
  // completion_judge 없이 종료되는 경우에도 Todos와 TrimmedFileReads 저장
@@ -1252,7 +1315,7 @@ export async function runSession(options) {
1252
1315
  consolidatedErrorMessage = `[Session] ${userFriendlyMessage}`;
1253
1316
  }
1254
1317
 
1255
- uiEvents.addErrorMessage(consolidatedErrorMessage);
1318
+ safeUiEvents.addErrorMessage(consolidatedErrorMessage);
1256
1319
 
1257
1320
  // 에러 발생 시에도 Todos와 TrimmedFileReads 저장 시도
1258
1321
  if (currentSessionData) {
@@ -1270,9 +1333,9 @@ export async function runSession(options) {
1270
1333
  return null;
1271
1334
  } finally {
1272
1335
  // 세션 중단 이벤트 리스너 제거
1273
- uiEvents.off('session:interrupt', handleInterrupt);
1336
+ safeUiEvents.off('session:interrupt', handleInterrupt);
1274
1337
 
1275
1338
  // 세션 종료 알림
1276
- uiEvents.sessionEnd();
1339
+ safeUiEvents.sessionEnd();
1277
1340
  }
1278
1341
  }
@@ -1,4 +1,6 @@
1
1
  import { uiEvents } from '../system/ui_events.js';
2
+ import { closePersistentShell } from '../system/code_executer.js';
3
+ import { killAllBackgroundProcesses } from '../system/background_process.js';
2
4
 
3
5
  /**
4
6
  * Unified exit handler for the application
@@ -17,6 +19,12 @@ export async function performExit(options = {}) {
17
19
  uiEvents.addSystemMessage(`Goodbye! Session ID: ${sessionID}`);
18
20
  }
19
21
 
22
+ // 백그라운드 프로세스 정리
23
+ await killAllBackgroundProcesses();
24
+
25
+ // PersistentShell 정리
26
+ await closePersistentShell();
27
+
20
28
  // MCP Integration 정리
21
29
  if (mcpIntegration) {
22
30
  await mcpIntegration.cleanup();