refactor: extract shared utilities, protocol constants, and retry loop

Phase 3: provider-retry.ts — shared Claude rotation loop (SSOT)
  - retryClaudeWithRotation extracted from message-agent-executor + task-scheduler
  - ~200 lines of duplicated retry logic removed

Phase 4: types.ts — AgentOutputPhase + VisiblePhase unified
Phase 5: types.ts — AgentConfig extended with claudeThinking/claudeThinkingBudget

Utilities (utils.ts):
  - getErrorMessage: 14 occurrences of instanceof Error pattern → 1 function
  - readJsonFile/writeJsonFile: 19 occurrences of JSON+fs pattern → 2 functions
  - fetchWithTimeout: 3 occurrences of AbortController pattern → 1 function
  - formatElapsedKorean: deduplicated from task-watch-status + message-turn-controller

Protocol (agent-protocol.ts):
  - OUTPUT_START/END_MARKER centralized (runners keep local copies with SSOT reference)
  - IMAGE_TAG_RE, IPC constants documented

Runner: show "대화 요약 중..." progress message during auto-compact

Net: -137 lines, 354/354 tests passing
This commit is contained in:
Eyejoker
2026-03-25 04:59:49 +09:00
parent b9f98fcc19
commit 5ea3439c5f
24 changed files with 562 additions and 442 deletions

View File

@@ -6,6 +6,7 @@ import { ChildProcess, spawn } from 'child_process';
import fs from 'fs';
import path from 'path';
import { getErrorMessage } from './utils.js';
import {
AGENT_MAX_OUTPUT_SIZE,
AGENT_TIMEOUT,
@@ -18,11 +19,8 @@ export {
writeTasksSnapshot,
} from './agent-runner-snapshot.js';
import { logger } from './logger.js';
import { AgentType, RegisteredGroup } from './types.js';
// Sentinel markers for robust output parsing (must match agent-runner)
const OUTPUT_START_MARKER = '---EJCLAW_OUTPUT_START---';
const OUTPUT_END_MARKER = '---EJCLAW_OUTPUT_END---';
import { OUTPUT_END_MARKER, OUTPUT_START_MARKER } from './agent-protocol.js';
import { AgentOutputPhase, AgentType, RegisteredGroup } from './types.js';
export interface AgentInput {
prompt: string;
@@ -42,7 +40,7 @@ export interface AgentInput {
export interface AgentOutput {
status: 'success' | 'error';
result: string | null;
phase?: 'progress' | 'final' | 'tool-activity' | 'intermediate';
phase?: AgentOutputPhase;
agentId?: string;
agentLabel?: string;
agentDone?: boolean;
@@ -441,7 +439,7 @@ export async function runAgentProcess(
resolve({
status: 'error',
result: null,
error: `Failed to parse agent output: ${err instanceof Error ? err.message : String(err)}`,
error: `Failed to parse agent output: ${getErrorMessage(err)}`,
});
}
});