style: 完成所有文件的lint

This commit is contained in:
claude-code-best
2026-05-01 21:39:30 +08:00
parent d136872cc9
commit 6182015005
1333 changed files with 68255 additions and 77882 deletions

View File

@@ -1,22 +1,22 @@
import chalk from 'chalk'
import type { UUID } from 'crypto'
import figures from 'figures'
import * as React from 'react'
import { getOriginalCwd, getSessionId } from '../../bootstrap/state.js'
import type { CommandResultDisplay, ResumeEntrypoint } from '../../commands.js'
import { LogSelector } from '../../components/LogSelector.js'
import { MessageResponse } from '../../components/MessageResponse.js'
import { Spinner } from '../../components/Spinner.js'
import { useIsInsideModal } from '../../context/modalContext.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import { setClipboard } from '@anthropic/ink'
import { Box, Text } from '@anthropic/ink'
import type { LocalJSXCommandCall } from '../../types/command.js'
import type { LogOption } from '../../types/logs.js'
import { agenticSessionSearch } from '../../utils/agenticSessionSearch.js'
import { checkCrossProjectResume } from '../../utils/crossProjectResume.js'
import { getWorktreePaths } from '../../utils/getWorktreePaths.js'
import { logError } from '../../utils/log.js'
import chalk from 'chalk';
import type { UUID } from 'crypto';
import figures from 'figures';
import * as React from 'react';
import { getOriginalCwd, getSessionId } from '../../bootstrap/state.js';
import type { CommandResultDisplay, ResumeEntrypoint } from '../../commands.js';
import { LogSelector } from '../../components/LogSelector.js';
import { MessageResponse } from '../../components/MessageResponse.js';
import { Spinner } from '../../components/Spinner.js';
import { useIsInsideModal } from '../../context/modalContext.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { setClipboard } from '@anthropic/ink';
import { Box, Text } from '@anthropic/ink';
import type { LocalJSXCommandCall } from '../../types/command.js';
import type { LogOption } from '../../types/logs.js';
import { agenticSessionSearch } from '../../utils/agenticSessionSearch.js';
import { checkCrossProjectResume } from '../../utils/crossProjectResume.js';
import { getWorktreePaths } from '../../utils/getWorktreePaths.js';
import { logError } from '../../utils/log.js';
import {
getLastSessionLog,
getSessionIdFromLog,
@@ -26,19 +26,19 @@ import {
loadFullLog,
loadSameRepoMessageLogs,
searchSessionsByCustomTitle,
} from '../../utils/sessionStorage.js'
import { validateUuid } from '../../utils/uuid.js'
} from '../../utils/sessionStorage.js';
import { validateUuid } from '../../utils/uuid.js';
type ResumeResult =
| { resultType: 'sessionNotFound'; arg: string }
| { resultType: 'multipleMatches'; arg: string; count: number }
| { resultType: 'multipleMatches'; arg: string; count: number };
function resumeHelpMessage(result: ResumeResult): string {
switch (result.resultType) {
case 'sessionNotFound':
return `Session ${chalk.bold(result.arg)} was not found.`
return `Session ${chalk.bold(result.arg)} was not found.`;
case 'multipleMatches':
return `Found ${result.count} sessions matching ${chalk.bold(result.arg)}. Please use /resume to pick a specific session.`
return `Found ${result.count} sessions matching ${chalk.bold(result.arg)}. Please use /resume to pick a specific session.`;
}
}
@@ -47,14 +47,14 @@ function ResumeError({
args,
onDone,
}: {
message: string
args: string
onDone: () => void
message: string;
args: string;
onDone: () => void;
}): React.ReactNode {
React.useEffect(() => {
const timer = setTimeout(onDone, 0)
return () => clearTimeout(timer)
}, [onDone])
const timer = setTimeout(onDone, 0);
return () => clearTimeout(timer);
}, [onDone]);
return (
<Box flexDirection="column">
@@ -65,95 +65,82 @@ function ResumeError({
<Text>{message}</Text>
</MessageResponse>
</Box>
)
);
}
function ResumeCommand({
onDone,
onResume,
}: {
onDone: (
result?: string,
options?: { display?: CommandResultDisplay },
) => void
onResume: (
sessionId: UUID,
log: LogOption,
entrypoint: ResumeEntrypoint,
) => Promise<void>
onDone: (result?: string, options?: { display?: CommandResultDisplay }) => void;
onResume: (sessionId: UUID, log: LogOption, entrypoint: ResumeEntrypoint) => Promise<void>;
}): React.ReactNode {
const [logs, setLogs] = React.useState<LogOption[]>([])
const [worktreePaths, setWorktreePaths] = React.useState<string[]>([])
const [loading, setLoading] = React.useState(true)
const [resuming, setResuming] = React.useState(false)
const [showAllProjects, setShowAllProjects] = React.useState(false)
const { rows } = useTerminalSize()
const insideModal = useIsInsideModal()
const [logs, setLogs] = React.useState<LogOption[]>([]);
const [worktreePaths, setWorktreePaths] = React.useState<string[]>([]);
const [loading, setLoading] = React.useState(true);
const [resuming, setResuming] = React.useState(false);
const [showAllProjects, setShowAllProjects] = React.useState(false);
const { rows } = useTerminalSize();
const insideModal = useIsInsideModal();
const loadLogs = React.useCallback(
async (allProjects: boolean, paths: string[]) => {
setLoading(true)
setLoading(true);
try {
const allLogs = allProjects
? await loadAllProjectsMessageLogs()
: await loadSameRepoMessageLogs(paths)
const resumable = filterResumableSessions(allLogs, getSessionId())
const allLogs = allProjects ? await loadAllProjectsMessageLogs() : await loadSameRepoMessageLogs(paths);
const resumable = filterResumableSessions(allLogs, getSessionId());
if (resumable.length === 0) {
onDone('No conversations found to resume')
return
onDone('No conversations found to resume');
return;
}
setLogs(resumable)
setLogs(resumable);
} catch (_err) {
onDone('Failed to load conversations')
onDone('Failed to load conversations');
} finally {
setLoading(false)
setLoading(false);
}
},
[onDone],
)
);
React.useEffect(() => {
async function init() {
const paths = await getWorktreePaths(getOriginalCwd())
setWorktreePaths(paths)
void loadLogs(false, paths)
const paths = await getWorktreePaths(getOriginalCwd());
setWorktreePaths(paths);
void loadLogs(false, paths);
}
void init()
}, [loadLogs])
void init();
}, [loadLogs]);
const handleToggleAllProjects = React.useCallback(() => {
const newValue = !showAllProjects
setShowAllProjects(newValue)
void loadLogs(newValue, worktreePaths)
}, [showAllProjects, loadLogs, worktreePaths])
const newValue = !showAllProjects;
setShowAllProjects(newValue);
void loadLogs(newValue, worktreePaths);
}, [showAllProjects, loadLogs, worktreePaths]);
async function handleSelect(log: LogOption) {
const sessionId = validateUuid(getSessionIdFromLog(log))
const sessionId = validateUuid(getSessionIdFromLog(log));
if (!sessionId) {
onDone('Failed to resume conversation')
return
onDone('Failed to resume conversation');
return;
}
// Load full messages for lite logs
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log;
// Check if this conversation is from a different directory
const crossProjectCheck = checkCrossProjectResume(
fullLog,
showAllProjects,
worktreePaths,
)
const crossProjectCheck = checkCrossProjectResume(fullLog, showAllProjects, worktreePaths);
if (crossProjectCheck.isCrossProject) {
if (crossProjectCheck.isSameRepoWorktree) {
// Same repo worktree - can resume directly
setResuming(true)
void onResume(sessionId, fullLog, 'slash_command_picker')
return
setResuming(true);
void onResume(sessionId, fullLog, 'slash_command_picker');
return;
}
// Different project - show command instead of resuming
const raw = await setClipboard((crossProjectCheck as { command: string }).command)
if (raw) process.stdout.write(raw)
const raw = await setClipboard((crossProjectCheck as { command: string }).command);
if (raw) process.stdout.write(raw);
// Format the output message
const message = [
@@ -165,19 +152,19 @@ function ResumeCommand({
'',
'(Command copied to clipboard)',
'',
].join('\n')
].join('\n');
onDone(message, { display: 'user' })
return
onDone(message, { display: 'user' });
return;
}
// Same directory - proceed with resume
setResuming(true)
void onResume(sessionId, fullLog, 'slash_command_picker')
setResuming(true);
void onResume(sessionId, fullLog, 'slash_command_picker');
}
function handleCancel() {
onDone('Resume cancelled', { display: 'system' })
onDone('Resume cancelled', { display: 'system' });
}
if (loading) {
@@ -186,7 +173,7 @@ function ResumeCommand({
<Spinner />
<Text> Loading conversations</Text>
</Box>
)
);
}
if (resuming) {
@@ -195,7 +182,7 @@ function ResumeCommand({
<Spinner />
<Text> Resuming conversation</Text>
</Box>
)
);
}
return (
@@ -209,77 +196,60 @@ function ResumeCommand({
onToggleAllProjects={handleToggleAllProjects}
onAgenticSearch={agenticSessionSearch}
/>
)
);
}
export function filterResumableSessions(
logs: LogOption[],
currentSessionId: string,
): LogOption[] {
return logs.filter(
l => !l.isSidechain && getSessionIdFromLog(l) !== currentSessionId,
)
export function filterResumableSessions(logs: LogOption[], currentSessionId: string): LogOption[] {
return logs.filter(l => !l.isSidechain && getSessionIdFromLog(l) !== currentSessionId);
}
export const call: LocalJSXCommandCall = async (onDone, context, args) => {
const onResume = async (
sessionId: UUID,
log: LogOption,
entrypoint: ResumeEntrypoint,
) => {
const onResume = async (sessionId: UUID, log: LogOption, entrypoint: ResumeEntrypoint) => {
try {
await context.resume?.(sessionId, log, entrypoint)
onDone(undefined, { display: 'skip' })
await context.resume?.(sessionId, log, entrypoint);
onDone(undefined, { display: 'skip' });
} catch (error) {
logError(error as Error)
onDone(`Failed to resume: ${(error as Error).message}`)
logError(error as Error);
onDone(`Failed to resume: ${(error as Error).message}`);
}
}
};
const arg = args?.trim()
const arg = args?.trim();
// No argument provided - show picker
if (!arg) {
return (
<ResumeCommand key={Date.now()} onDone={onDone} onResume={onResume} />
)
return <ResumeCommand key={Date.now()} onDone={onDone} onResume={onResume} />;
}
// Load logs to search (includes same-repo worktrees)
const worktreePaths = await getWorktreePaths(getOriginalCwd())
const logs = await loadSameRepoMessageLogs(worktreePaths)
const worktreePaths = await getWorktreePaths(getOriginalCwd());
const logs = await loadSameRepoMessageLogs(worktreePaths);
if (logs.length === 0) {
const message = 'No conversations found to resume.'
return (
<ResumeError
message={message}
args={arg}
onDone={() => onDone(message)}
/>
)
const message = 'No conversations found to resume.';
return <ResumeError message={message} args={arg} onDone={() => onDone(message)} />;
}
// First, check if arg is a valid UUID
const maybeSessionId = validateUuid(arg)
const maybeSessionId = validateUuid(arg);
if (maybeSessionId) {
const matchingLogs = logs
.filter(l => getSessionIdFromLog(l) === maybeSessionId)
.sort((a, b) => b.modified.getTime() - a.modified.getTime())
.sort((a, b) => b.modified.getTime() - a.modified.getTime());
if (matchingLogs.length > 0) {
const log = matchingLogs[0]!
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log
void onResume(maybeSessionId, fullLog, 'slash_command_session_id')
return null
const log = matchingLogs[0]!;
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log;
void onResume(maybeSessionId, fullLog, 'slash_command_session_id');
return null;
}
// Enriched logs didn't find it — try direct file lookup. This handles
// sessions filtered out by enrichLogs (e.g., first message >16KB makes
// firstPrompt extraction fail, causing the session to be dropped).
const directLog = await getLastSessionLog(maybeSessionId)
const directLog = await getLastSessionLog(maybeSessionId);
if (directLog) {
void onResume(maybeSessionId, directLog, 'slash_command_session_id')
return null
void onResume(maybeSessionId, directLog, 'slash_command_session_id');
return null;
}
}
@@ -287,14 +257,14 @@ export const call: LocalJSXCommandCall = async (onDone, context, args) => {
if (isCustomTitleEnabled()) {
const titleMatches = await searchSessionsByCustomTitle(arg, {
exact: true,
})
});
if (titleMatches.length === 1) {
const log = titleMatches[0]!
const sessionId = getSessionIdFromLog(log)
const log = titleMatches[0]!;
const sessionId = getSessionIdFromLog(log);
if (sessionId) {
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log
void onResume(sessionId, fullLog, 'slash_command_title')
return null
const fullLog = isLiteLog(log) ? await loadFullLog(log) : log;
void onResume(sessionId, fullLog, 'slash_command_title');
return null;
}
}
@@ -304,20 +274,12 @@ export const call: LocalJSXCommandCall = async (onDone, context, args) => {
resultType: 'multipleMatches',
arg,
count: titleMatches.length,
})
return (
<ResumeError
message={message}
args={arg}
onDone={() => onDone(message)}
/>
)
});
return <ResumeError message={message} args={arg} onDone={() => onDone(message)} />;
}
}
// No match found - show error
const message = resumeHelpMessage({ resultType: 'sessionNotFound', arg })
return (
<ResumeError message={message} args={arg} onDone={() => onDone(message)} />
)
}
const message = resumeHelpMessage({ resultType: 'sessionNotFound', arg });
return <ResumeError message={message} args={arg} onDone={() => onDone(message)} />;
};