chore: version up to 2.80.38 and package with refined recovery

This commit is contained in:
g1nation
2026-05-13 00:15:45 +09:00
parent 6c4bc3494f
commit eb36cec050
15 changed files with 202 additions and 62 deletions
+32 -18
View File
@@ -45,6 +45,7 @@ import {
extractVisibleFinal,
shouldFinalOnlyRetry,
shouldAutoContinue,
looksCutOff,
mergeContinuationParts,
buildContinuationUserPrompt,
FINAL_ONLY_DIRECTIVE,
@@ -485,27 +486,36 @@ export class AgentExecutor {
let fullSystemPrompt: string;
if (isAgentMode) {
// 1. 기본 시스템 프롬프트에서 에이전트 포맷과 충돌하는 섹션 제거
// The Agent's prompt IS the primary directive (role / persona / tone / output format),
// so it LEADS the system prompt — models anchor on the first persona they see, not the
// last, especially small ones. The Astra base prompt is reduced to neutral scaffolding
// (action tags, current date, anti-leak rules) and follows; a short reminder at the very
// end keeps the model from drifting back to a generic assistant.
const strippedSystemPrompt = this.stripAstraFormattingForAgentMode(systemPrompt);
const agentPromptText = (options.agentSkillContext || '').trim();
if (estimateTokens(agentPromptText) > Math.floor(config.contextLength * 0.5)) {
logInfo('Agent prompt is unusually large relative to the context window.', {
model: actualModel, agentPromptTokens: estimateTokens(agentPromptText), contextLength: config.contextLength,
});
}
// 2. Astra 전용 컨텍스트는 에이전트 모드에서 비활성화
// (astraStanceCtx, thinkingPartnerCtx, v4PolicyCtx → 에이전트 역할과 충돌)
const agentDirective = [
'\n\n[AGENT MODE — ABSOLUTE OVERRIDE]',
'You are NOT operating as Astra for this response.',
'A specialized Agent has been selected by the user.',
'ALL output format, role, persona, and style instructions from the Agent below',
'take ABSOLUTE PRECEDENCE over any previous formatting rules (including ## 요약, ## 상세 설명, ## 제안).',
'You MUST follow the Agent\'s 📄 Output Format exactly. Do NOT fall back to Astra\'s default format.',
const agentBlock = [
'[AGENT MODE — PRIMARY DIRECTIVE]',
'A specialized Agent has been selected by the user. The Agent System Prompt below is your',
'PRIMARY directive: it defines your role, persona, tone, and output format. Follow it exactly.',
'Everything after the Agent block (action-tag reference, date, brain/project context) is technical',
'scaffolding — use it only as the Agent\'s task requires. Do NOT impose a generic assistant',
'format (e.g. ## 요약 / ## 상세 설명 / ## 제안) unless the Agent explicitly asks for one.',
'',
'--- AGENT SYSTEM PROMPT START ---',
options.agentSkillContext,
'--- AGENT SYSTEM PROMPT END ---'
agentPromptText || '(this agent has no instructions yet — fall back to being a concise, direct assistant)',
'--- AGENT SYSTEM PROMPT END ---',
].join('\n');
const agentTailReminder = '\n\n[REMINDER] You are operating as the Agent defined above. Keep its role, persona, and output format. Do not fall back to a default assistant style or section format.';
// 3. 조립: 기본(축소) → 유틸리티 컨텍스트 → 에이전트 프롬프트(최후단)
// [CONTEXT] … [/CONTEXT] 사이만 컨텍스트 초과 시 trim 대상 — agentDirective/negative 는 보호.
fullSystemPrompt = `${strippedSystemPrompt}${internetCtx}${memoryCtx}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}${agentDirective}`;
// [CONTEXT] … [/CONTEXT] 사이만 컨텍스트 초과 시 trim 대상 — agentBlock(앞)·reminder(뒤)·negative 는 보호.
// memoryCtx(RAG/메모리/lessons)도 [CONTEXT] 안에 넣어 토큰이 빡빡할 때 대화 기록보다 먼저 잘리게 한다.
fullSystemPrompt = `${agentBlock}\n\n${strippedSystemPrompt}${internetCtx}${designerCtx}${secondBrainTraceCtx}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}${agentTailReminder}`;
} else {
// 기존 Astra 모드 (에이전트 미선택)
const localProjectKnowledgeCtx = prompt && localPathContext && this.isProjectKnowledgeCreationRequest(prompt)
@@ -530,7 +540,8 @@ export class AgentExecutor {
const casualCtx = isCasualConversation
? '\n\n[CASUAL CONVERSATION MODE]\nThe user sent a greeting, acknowledgement, or light conversational message. Reply naturally and briefly to the message itself. Do not use Second Brain, memory, project records, reports, references, or analysis unless the user explicitly asks for them.'
: '';
fullSystemPrompt = `${systemPrompt}${internetCtx}${memoryCtx}${designerCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${astraStanceCtx}${secondBrainTraceCtx}${v4PolicyCtx}${casualCtx}\n\n[CONTEXT]\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}`;
// memoryCtx(RAG/메모리/lessons)는 [CONTEXT] 안에 — 토큰이 빡빡하면 대화 기록보다 먼저 잘림.
fullSystemPrompt = `${systemPrompt}${internetCtx}${designerCtx}${localProjectKnowledgeCtx}${thinkingPartnerCtx}${astraStanceCtx}${secondBrainTraceCtx}${v4PolicyCtx}${casualCtx}\n\n[CONTEXT]\n${memoryCtx}\n${knowledgeContextForPrompt}\n${contextBlock}\n[/CONTEXT]\n${negativeCtx}`;
}
// ──────────────────────────────────────────────────────────────────
// [Context Limit Manager] context length 는 "답변을 그만큼 길게 써도 된다"
@@ -980,8 +991,11 @@ export class AgentExecutor {
});
}
const outputTokens = estimateTokens(assistantContent);
const notice = shouldShowTruncationNotice(stopKind, outputTokens, maxOutputTokens)
? truncationNotice(stopKind)
// Show the "incomplete" notice when the engine said output-limit/context-overflow/error,
// OR when (after all auto-continuation rounds) the answer still plainly ends mid-sentence.
const notice =
shouldShowTruncationNotice(stopKind, outputTokens, maxOutputTokens) ? truncationNotice(stopKind)
: looksCutOff(assistantContent) ? truncationNotice('output-limit')
: '';
if (notice && assistantContent.trim()) {
assistantContent = assistantContent.trimEnd() + notice;