style: format files after pre-commit prettier run
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -353,14 +353,9 @@ args = [${JSON.stringify(mementoSseUrl)}, "--header", ${JSON.stringify(`Authoriz
|
||||
env.ANTHROPIC_API_KEY =
|
||||
envVars.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY || '';
|
||||
}
|
||||
if (
|
||||
envVars.ANTHROPIC_AUTH_TOKEN ||
|
||||
process.env.ANTHROPIC_AUTH_TOKEN
|
||||
) {
|
||||
if (envVars.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_AUTH_TOKEN) {
|
||||
env.ANTHROPIC_AUTH_TOKEN =
|
||||
envVars.ANTHROPIC_AUTH_TOKEN ||
|
||||
process.env.ANTHROPIC_AUTH_TOKEN ||
|
||||
'';
|
||||
envVars.ANTHROPIC_AUTH_TOKEN || process.env.ANTHROPIC_AUTH_TOKEN || '';
|
||||
}
|
||||
if (envVars.ANTHROPIC_BASE_URL || process.env.ANTHROPIC_BASE_URL) {
|
||||
env.ANTHROPIC_BASE_URL =
|
||||
|
||||
10
src/db.ts
10
src/db.ts
@@ -648,7 +648,9 @@ export function getMessagesSince(
|
||||
return rows.map(normalizeMessageRow);
|
||||
}
|
||||
|
||||
function normalizeSeqCursor(cursor: string | number | null | undefined): number {
|
||||
function normalizeSeqCursor(
|
||||
cursor: string | number | null | undefined,
|
||||
): number {
|
||||
if (typeof cursor === 'number') {
|
||||
return Number.isFinite(cursor) && cursor > 0 ? cursor : 0;
|
||||
}
|
||||
@@ -662,7 +664,8 @@ export function getLatestMessageSeqAtOrBefore(
|
||||
chatJid?: string,
|
||||
): number {
|
||||
if (!timestamp) return 0;
|
||||
const row = (chatJid
|
||||
const row = (
|
||||
chatJid
|
||||
? db
|
||||
.prepare(
|
||||
`SELECT COALESCE(MAX(seq), 0) AS maxSeq
|
||||
@@ -676,7 +679,8 @@ export function getLatestMessageSeqAtOrBefore(
|
||||
FROM messages
|
||||
WHERE timestamp <= ?`,
|
||||
)
|
||||
.get(timestamp)) as { maxSeq: number | null };
|
||||
.get(timestamp)
|
||||
) as { maxSeq: number | null };
|
||||
return row.maxSeq ?? 0;
|
||||
}
|
||||
|
||||
|
||||
39
src/index.ts
39
src/index.ts
@@ -222,9 +222,12 @@ function loadState(): void {
|
||||
lastTimestamp = normalizeStoredSeqCursor(
|
||||
getRouterState('last_seq') || getRouterState('last_timestamp'),
|
||||
);
|
||||
const agentTs = getRouterState('last_agent_seq') || getRouterState('last_agent_timestamp');
|
||||
const agentTs =
|
||||
getRouterState('last_agent_seq') || getRouterState('last_agent_timestamp');
|
||||
try {
|
||||
const parsed = agentTs ? (JSON.parse(agentTs) as Record<string, string>) : {};
|
||||
const parsed = agentTs
|
||||
? (JSON.parse(agentTs) as Record<string, string>)
|
||||
: {};
|
||||
lastAgentTimestamp = Object.fromEntries(
|
||||
Object.entries(parsed).map(([chatJid, cursor]) => [
|
||||
chatJid,
|
||||
@@ -843,7 +846,11 @@ async function processGroupMessages(chatJid: string): Promise<boolean> {
|
||||
queue.setActivityTouch(chatJid, null);
|
||||
|
||||
if (hadError) {
|
||||
if (finalOutputSentToUser || progressOutputSentToUser || producedFinalText) {
|
||||
if (
|
||||
finalOutputSentToUser ||
|
||||
progressOutputSentToUser ||
|
||||
producedFinalText
|
||||
) {
|
||||
logger.warn(
|
||||
{ group: group.name },
|
||||
'Agent error after output was produced, skipping cursor rollback to prevent duplicates',
|
||||
@@ -913,8 +920,7 @@ async function runAgent(
|
||||
'settings.json',
|
||||
);
|
||||
const groupHasOverride = hasGroupProviderOverride(settingsPath);
|
||||
const canFallback =
|
||||
isClaudeCode && isFallbackEnabled() && !groupHasOverride;
|
||||
const canFallback = isClaudeCode && isFallbackEnabled() && !groupHasOverride;
|
||||
|
||||
const agentInput = {
|
||||
prompt,
|
||||
@@ -925,7 +931,9 @@ async function runAgent(
|
||||
assistantName: ASSISTANT_NAME,
|
||||
};
|
||||
|
||||
const runAttempt = async (provider: string): Promise<{
|
||||
const runAttempt = async (
|
||||
provider: string,
|
||||
): Promise<{
|
||||
output?: AgentOutput;
|
||||
error?: unknown;
|
||||
sawOutput: boolean;
|
||||
@@ -1124,7 +1132,10 @@ async function runAgent(
|
||||
|
||||
const output = primaryAttempt.output;
|
||||
if (!output) {
|
||||
logger.error({ group: group.name, chatJid, provider }, 'Agent produced no output object');
|
||||
logger.error(
|
||||
{ group: group.name, chatJid, provider },
|
||||
'Agent produced no output object',
|
||||
);
|
||||
return 'error';
|
||||
}
|
||||
|
||||
@@ -1750,7 +1761,9 @@ async function buildUsageContent(): Promise<string> {
|
||||
lines.push('_조회 불가_');
|
||||
}
|
||||
if (shouldFetchClaudeUsage && usageApiPollingDisabled) {
|
||||
lines.push('_* Claude 사용량 조회는 반복된 429로 이번 프로세스에서 일시 중지_');
|
||||
lines.push(
|
||||
'_* Claude 사용량 조회는 반복된 429로 이번 프로세스에서 일시 중지_',
|
||||
);
|
||||
}
|
||||
if (claudeUsageIsCached) {
|
||||
lines.push('_* Claude 사용량은 작업 중일 때는 캐시값 유지_');
|
||||
@@ -2081,9 +2094,7 @@ async function announceRestartRecovery(
|
||||
const explicitContext = consumeRestartContext();
|
||||
const dedupeSince = new Date(processStartedAtMs - 60_000).toISOString();
|
||||
if (explicitContext) {
|
||||
if (
|
||||
hasRecentRestartAnnouncement(explicitContext.chatJid, dedupeSince)
|
||||
) {
|
||||
if (hasRecentRestartAnnouncement(explicitContext.chatJid, dedupeSince)) {
|
||||
logger.info(
|
||||
{ chatJid: explicitContext.chatJid },
|
||||
'Skipped duplicate restart recovery announcement',
|
||||
@@ -2173,7 +2184,11 @@ async function main(): Promise<void> {
|
||||
);
|
||||
if (writtenPaths.length > 0) {
|
||||
logger.info(
|
||||
{ signal, interruptedGroupCount: interruptedGroups.length, writtenPaths },
|
||||
{
|
||||
signal,
|
||||
interruptedGroupCount: interruptedGroups.length,
|
||||
writtenPaths,
|
||||
},
|
||||
'Stored shutdown restart context for interrupted groups',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,9 +95,7 @@ describe('createMessageRuntime', () => {
|
||||
ANTHROPIC_AUTH_TOKEN: 'test-kimi-key',
|
||||
ANTHROPIC_MODEL: 'kimi-k2.5',
|
||||
});
|
||||
vi.mocked(providerFallback.hasGroupProviderOverride).mockReturnValue(
|
||||
false,
|
||||
);
|
||||
vi.mocked(providerFallback.hasGroupProviderOverride).mockReturnValue(false);
|
||||
vi.mocked(providerFallback.isFallbackEnabled).mockReturnValue(true);
|
||||
vi.mocked(providerFallback.detectFallbackTrigger).mockReturnValue({
|
||||
shouldFallback: false,
|
||||
|
||||
@@ -151,7 +151,9 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
||||
assistantName: deps.assistantName,
|
||||
};
|
||||
|
||||
const runAttempt = async (provider: string): Promise<{
|
||||
const runAttempt = async (
|
||||
provider: string,
|
||||
): Promise<{
|
||||
output?: AgentOutput;
|
||||
error?: unknown;
|
||||
sawOutput: boolean;
|
||||
@@ -212,7 +214,13 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
||||
|
||||
if (provider !== 'claude') {
|
||||
logger.info(
|
||||
{ chatJid, group: group.name, groupFolder: group.folder, runId, provider },
|
||||
{
|
||||
chatJid,
|
||||
group: group.name,
|
||||
groupFolder: group.folder,
|
||||
runId,
|
||||
provider,
|
||||
},
|
||||
`Claude provider in cooldown, routing request to ${provider}`,
|
||||
);
|
||||
}
|
||||
@@ -238,7 +246,12 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
||||
sessionId: persistSessionIds ? sessionId : undefined,
|
||||
},
|
||||
(proc, processName) =>
|
||||
deps.queue.registerProcess(chatJid, proc, processName, group.folder),
|
||||
deps.queue.registerProcess(
|
||||
chatJid,
|
||||
proc,
|
||||
processName,
|
||||
group.folder,
|
||||
),
|
||||
wrappedOnOutput,
|
||||
provider === 'claude' ? undefined : getFallbackEnvOverrides(),
|
||||
);
|
||||
@@ -368,7 +381,13 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
||||
const output = primaryAttempt.output;
|
||||
if (!output) {
|
||||
logger.error(
|
||||
{ chatJid, group: group.name, groupFolder: group.folder, runId, provider },
|
||||
{
|
||||
chatJid,
|
||||
group: group.name,
|
||||
groupFolder: group.folder,
|
||||
runId,
|
||||
provider,
|
||||
},
|
||||
'Agent produced no output object',
|
||||
);
|
||||
return 'error';
|
||||
@@ -831,7 +850,13 @@ export function createMessageRuntime(deps: MessageRuntimeDeps): {
|
||||
progressMessageId = await channel.sendAndTrack(chatJid, rendered);
|
||||
} catch (err) {
|
||||
logger.warn(
|
||||
{ chatJid, group: group.name, groupFolder: group.folder, runId, err },
|
||||
{
|
||||
chatJid,
|
||||
group: group.name,
|
||||
groupFolder: group.folder,
|
||||
runId,
|
||||
err,
|
||||
},
|
||||
'Failed to send tracked progress message',
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -63,8 +63,7 @@ function loadConfig(): FallbackConfig {
|
||||
'FALLBACK_COOLDOWN_MS',
|
||||
]);
|
||||
|
||||
const baseUrl =
|
||||
process.env.FALLBACK_BASE_URL || env.FALLBACK_BASE_URL || '';
|
||||
const baseUrl = process.env.FALLBACK_BASE_URL || env.FALLBACK_BASE_URL || '';
|
||||
const authToken =
|
||||
process.env.FALLBACK_AUTH_TOKEN || env.FALLBACK_AUTH_TOKEN || '';
|
||||
const model = process.env.FALLBACK_MODEL || env.FALLBACK_MODEL || '';
|
||||
|
||||
@@ -159,8 +159,7 @@ export function writeShutdownRestartContext(
|
||||
|
||||
const payload: RestartContext = {
|
||||
chatJid: existing?.chatJid || mainChatJid,
|
||||
summary:
|
||||
existing?.summary || '서비스 재시작으로 진행 중인 작업이 중단됨',
|
||||
summary: existing?.summary || '서비스 재시작으로 진행 중인 작업이 중단됨',
|
||||
verify: existing?.verify ?? [],
|
||||
writtenAt: new Date().toISOString(),
|
||||
source: existing?.source || 'shutdown-snapshot',
|
||||
@@ -181,7 +180,9 @@ export function buildInterruptedRestartAnnouncement(
|
||||
const lines = ['서비스 재시작으로 이전 작업이 중단됐습니다.'];
|
||||
lines.push(`- 직전 상태: ${interrupted.status}`);
|
||||
if (interrupted.elapsedMs !== null) {
|
||||
lines.push(`- 직전 실행 시간: ${Math.round(interrupted.elapsedMs / 1000)}초`);
|
||||
lines.push(
|
||||
`- 직전 실행 시간: ${Math.round(interrupted.elapsedMs / 1000)}초`,
|
||||
);
|
||||
}
|
||||
if (interrupted.pendingMessages) {
|
||||
lines.push('- 미처리 메시지가 남아 있었음');
|
||||
@@ -216,9 +217,7 @@ export function consumeRestartContext(): RestartContext | null {
|
||||
}
|
||||
}
|
||||
|
||||
export function buildRestartAnnouncement(
|
||||
context: RestartContext,
|
||||
): string {
|
||||
export function buildRestartAnnouncement(context: RestartContext): string {
|
||||
const lines = ['재시작 완료.', `- 변경: ${context.summary}`];
|
||||
if (context.interruptedGroups && context.interruptedGroups.length > 0) {
|
||||
lines.push(`- 중단 작업 감지: ${context.interruptedGroups.length}개`);
|
||||
|
||||
@@ -119,7 +119,9 @@ function formatTimeLabel(timestampIso: string): string {
|
||||
.replace(/시 (\d{2})$/, '분 $1초');
|
||||
}
|
||||
|
||||
function formatWatchIntervalLabel(task: Pick<ScheduledTask, 'schedule_type' | 'schedule_value'>): string | null {
|
||||
function formatWatchIntervalLabel(
|
||||
task: Pick<ScheduledTask, 'schedule_type' | 'schedule_value'>,
|
||||
): string | null {
|
||||
if (task.schedule_type !== 'interval') return null;
|
||||
const ms = parseInt(task.schedule_value, 10);
|
||||
if (!Number.isFinite(ms) || ms <= 0) return null;
|
||||
|
||||
Reference in New Issue
Block a user