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:
20
src/ipc.ts
20
src/ipc.ts
@@ -9,6 +9,7 @@ import {
|
||||
SERVICE_AGENT_TYPE,
|
||||
TIMEZONE,
|
||||
} from './config.js';
|
||||
import { readJsonFile } from './utils.js';
|
||||
import { AvailableGroup } from './agent-runner.js';
|
||||
import { createTask, deleteTask, getTaskById, updateTask } from './db.js';
|
||||
import { isValidGroupFolder } from './group-folder.js';
|
||||
@@ -78,22 +79,24 @@ export function startIpcWatcher(deps: IpcDeps): void {
|
||||
for (const file of messageFiles) {
|
||||
const filePath = path.join(messagesDir, file);
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
||||
if (data.type === 'message' && data.chatJid && data.text) {
|
||||
const data = readJsonFile(filePath);
|
||||
if (!data || typeof data !== 'object') throw new Error('Invalid JSON');
|
||||
const msg = data as { type?: string; chatJid?: string; text?: string };
|
||||
if (msg.type === 'message' && msg.chatJid && msg.text) {
|
||||
// Authorization: verify this group can send to this chatJid
|
||||
const targetGroup = registeredGroups[data.chatJid];
|
||||
const targetGroup = registeredGroups[msg.chatJid];
|
||||
if (
|
||||
isMain ||
|
||||
(targetGroup && targetGroup.folder === sourceGroup)
|
||||
) {
|
||||
await deps.sendMessage(data.chatJid, data.text);
|
||||
await deps.sendMessage(msg.chatJid, msg.text);
|
||||
logger.info(
|
||||
{ chatJid: data.chatJid, sourceGroup },
|
||||
{ chatJid: msg.chatJid, sourceGroup },
|
||||
'IPC message sent',
|
||||
);
|
||||
} else {
|
||||
logger.warn(
|
||||
{ chatJid: data.chatJid, sourceGroup },
|
||||
{ chatJid: msg.chatJid, sourceGroup },
|
||||
'Unauthorized IPC message attempt blocked',
|
||||
);
|
||||
}
|
||||
@@ -129,9 +132,10 @@ export function startIpcWatcher(deps: IpcDeps): void {
|
||||
for (const file of taskFiles) {
|
||||
const filePath = path.join(tasksDir, file);
|
||||
try {
|
||||
const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
||||
const data = readJsonFile(filePath);
|
||||
if (!data || typeof data !== 'object') throw new Error('Invalid JSON');
|
||||
// Pass source group identity to processTaskIpc for authorization
|
||||
await processTaskIpc(data, sourceGroup, isMain, deps);
|
||||
await processTaskIpc(data as Parameters<typeof processTaskIpc>[0], sourceGroup, isMain, deps);
|
||||
fs.unlinkSync(filePath);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
|
||||
Reference in New Issue
Block a user