feat: update codex live automation and plan flows

This commit is contained in:
2026-04-24 08:06:36 +09:00
parent 916107dbe5
commit f2d6310efa
47 changed files with 2767 additions and 507 deletions

View File

@@ -60,7 +60,6 @@ type ChatContext = {
chatTypeId?: string | null;
chatTypeLabel?: string;
chatTypeDescription?: string;
chatTypeIsTemplate?: boolean;
};
type ChatInboundMessage =
@@ -89,7 +88,6 @@ type ChatInboundMessage =
chatTypeId?: string | null;
chatTypeLabel?: string;
chatTypeDescription?: string;
chatTypeIsTemplate?: boolean;
};
}
| {
@@ -875,45 +873,10 @@ export function shouldUseAgenticCodexReply(input: string) {
);
}
function extractTemplateKeywords(context: ChatContext | null) {
const raw = `${context?.chatTypeLabel ?? ''} ${context?.chatTypeDescription ?? ''}`;
return Array.from(
new Set(
raw
.split(/[^0-9A-Za-z가-힣]+/)
.map((keyword) => keyword.trim())
.filter((keyword) => keyword.length >= 2)
.filter(
(keyword) =>
!['템플릿', 'template', 'chat', 'codex', 'live', '요청', '일반', '기본', '유형'].includes(keyword.toLowerCase()),
),
),
);
}
export function shouldUseTemplateMacroReply(context: ChatContext | null, input: string) {
if (context?.chatTypeIsTemplate !== true) {
return false;
}
const normalized = input.toLowerCase();
if (
input.includes('템플릿') ||
input.includes('양식') ||
input.includes('포맷') ||
input.includes('형식') ||
input.includes('예시') ||
input.includes('샘플') ||
normalized.includes('template') ||
normalized.includes('format') ||
normalized.includes('sample')
) {
return true;
}
return extractTemplateKeywords(context).some((keyword) => normalized.includes(keyword.toLowerCase()));
void context;
void input;
return false;
}
function summarizeCodexOutput(output: string) {
@@ -1466,7 +1429,6 @@ function buildAgenticCodexPrompt(
const chatSessionUploadDir = `${chatSessionResourceDir}/uploads`;
const recentHistoryLines = promptContext?.recentHistoryLines ?? [];
const omittedHistoryCount = Math.max(0, promptContext?.omittedHistoryCount ?? 0);
const isTemplateRequest = context?.chatTypeIsTemplate === true;
return [
'당신은 이 저장소에서 Codex Live 요청을 처리하는 실제 Codex 실행기입니다.',
@@ -1477,7 +1439,7 @@ function buildAgenticCodexPrompt(
'- 필요 시 DB 직접 조회',
'- 필요 시 로컬 API 응답 확인',
'- 사용자가 요청했거나 해결에 필요하면 소스 코드 수정',
'- Codex Live에서 소스 수정이 필요하면 현재 프로젝트 환경의 main_project 저장소 루트에서 바로 수정하세요. 단, AGENTS.md의 브랜치 전략을 먼저 확인하고 그 규칙 안에서만 작업하세요.',
'- Codex Live에서 소스 수정이 필요하면 현재 프로젝트 환경의 main_project 저장소 루트에서 바로 수정하세요. 단, AGENTS.md 먼저 확인하고 그 규칙 안에서만 작업하세요.',
`- 현재 채팅 세션 리소스 기본 경로: ${chatSessionResourceDir}/`,
`- 현재 채팅 첨부 업로드 경로: ${chatSessionUploadDir}/`,
'- 채팅에서 파일/문서/이미지/코드 리소스를 제공할 때는 반드시 위 세션 전용 경로를 우선 사용하세요.',
@@ -1494,7 +1456,6 @@ function buildAgenticCodexPrompt(
'채팅 유형 문맥(우선 적용):',
`- chatTypeLabel: ${context?.chatTypeLabel ?? '없음'}`,
`- chatTypeDescription: ${context?.chatTypeDescription ?? '없음'}`,
`- chatTypeIsTemplate: ${isTemplateRequest ? 'true' : 'false'}`,
'- 답변 스타일과 기본 문맥은 반드시 채팅 유형 정보만 기준으로 적용하세요.',
'',
'참고 화면 정보:',
@@ -1503,20 +1464,15 @@ function buildAgenticCodexPrompt(
`- focusedComponentId: ${context?.focusedComponentId ?? '없음'}`,
`- pageUrl: ${context?.pageUrl ?? '없음'}`,
'',
isTemplateRequest ? '템플릿 요청 규칙:' : '최근 대화 문맥:',
...(isTemplateRequest
'최근 대화 문맥:',
...(recentHistoryLines.length > 0
? [
'- 이 요청은 템플릿 유형입니다.',
'- 이전 채팅방 내용은 참조하지 말고, 현재 화면 문맥/유형 설명/사용자 요청만 기준으로 처리하세요.',
...recentHistoryLines.map((line) => `- ${line}`),
...(omittedHistoryCount > 0
? [`- 최근 문맥 일부만 포함했습니다. 이전 ${omittedHistoryCount}개 메시지는 제외되었습니다.`]
: []),
]
: recentHistoryLines.length > 0
? [
...recentHistoryLines.map((line) => `- ${line}`),
...(omittedHistoryCount > 0
? [`- 최근 문맥 일부만 포함했습니다. 이전 ${omittedHistoryCount}개 메시지는 제외되었습니다.`]
: []),
]
: ['- 참조할 최근 대화가 없습니다.']),
: ['- 참조할 최근 대화가 없습니다.']),
'',
'사용자 요청:',
input,
@@ -1669,13 +1625,10 @@ async function runAgenticCodexReply(
const repoPath = env.SERVER_COMMAND_MAIN_PROJECT_ROOT || env.PLAN_MAIN_PROJECT_REPO_PATH || env.PLAN_GIT_REPO_PATH;
await validateAgenticCodexRuntime(repoPath, env.PLAN_CODEX_BIN);
const appConfig = await getAppConfigSnapshot();
const recentHistory =
context?.chatTypeIsTemplate === true
? { items: [] as string[], omittedCount: 0 }
: await buildRecentChatPromptHistory(sessionId, requestId, {
maxMessages: appConfig.chat?.maxContextMessages,
maxChars: appConfig.chat?.maxContextChars,
});
const recentHistory = await buildRecentChatPromptHistory(sessionId, requestId, {
maxMessages: appConfig.chat?.maxContextMessages,
maxChars: appConfig.chat?.maxContextChars,
});
const prompt = buildAgenticCodexPrompt(context, input, sessionId, {
recentHistoryLines: recentHistory.items,
omittedHistoryCount: recentHistory.omittedCount,
@@ -2980,7 +2933,6 @@ export class ChatService {
chatTypeId: message.payload.chatTypeId ?? null,
chatTypeLabel: message.payload.chatTypeLabel,
chatTypeDescription: message.payload.chatTypeDescription,
chatTypeIsTemplate: message.payload.chatTypeIsTemplate,
},
).catch((error: unknown) => {
this.logger.error(error, 'chat reply build failed');