重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/epicenterhq/epicenter --skill control-flow在重构复杂控制流时,应反映自然的人类推理模式:
相关技能:关于包含分支合并和调用者计数的系统化代码审查方法,请参见
refactoring。
在以下情况时使用此模式:
将嵌套的条件语句重构为线性的卫语句控制流。
用可读的提前返回替换混合的 throw/return try-catch 逻辑。
为布尔值和分支命名,使其读起来像自然的人类推理。
重构处理程序,使失败路径在成功路径之前明确显示。
isUsingNavigator、isUsingLocalTranscription、:像思维过程一样的命名广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
needsOldFileCleanup将此:带有重复逻辑的嵌套条件语句 转变为此:反映人类决策过程的线性流程
// From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
export async function checkFfmpegRecordingMethodCompatibility() {
if (!window.__TAURI_INTERNALS__) return;
// 仅当选择了 FFmpeg 录制方法时才检查
if (settings.value['recording.method'] !== 'ffmpeg') return;
const { data: ffmpegInstalled } =
await rpc.ffmpeg.checkFfmpegInstalled.ensure();
if (ffmpegInstalled) return; // FFmpeg 已安装,一切正常
// 选择了 FFmpeg 录制方法但未安装 FFmpeg
toast.warning('FFmpeg Required for FFmpeg Recording Method', {
// ... toast 内容
});
}
// From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
const isUsingNavigator = settings.value['recording.method'] === 'navigator';
const isUsingLocalTranscription =
settings.value['transcription.selectedTranscriptionService'] ===
'whispercpp' ||
settings.value['transcription.selectedTranscriptionService'] === 'parakeet';
return isUsingNavigator && isUsingLocalTranscription && !isFFmpegInstalled;
// From packages/epicenter/src/indexes/markdown/markdown-index.ts
/**
* 这里检查是否存在旧文件名 AND 它是否与新的不同。
* 本质上是在检查:"文件名改变了吗?" 和 "我们需要清理旧文件吗?"
*/
const needsOldFileCleanup = oldFilename && oldFilename !== filename;
if (needsOldFileCleanup) {
const oldFilePath = path.join(tableConfig.directory, oldFilename);
await deleteMarkdownFile({ filePath: oldFilePath });
tracking[table.name]!.deleteByFilename({ filename: oldFilename });
}
try-catch 块创建了一个嵌套的双分支结构:try 主体和 catch 主体。当 try 内部只有一个调用可能实际抛出异常时,用带守卫的调用 + 提前返回来替换 try-catch,使代码可以自上而下阅读。
重构前(嵌套,混合 throw/return):
async ({ body, status }) => {
const adapter = createAdapter(body.provider);
try {
const stream = chat({ adapter, messages: body.messages });
return toServerSentEventsResponse(stream);
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
throw status(499, 'Client closed request');
}
const message = error instanceof Error ? error.message : 'Unknown error';
throw status('Bad Gateway', `Provider error: ${message}`);
}
};
重构后(线性,一致的返回):
async ({ body, status }) => {
const adapter = createAdapter(body.provider);
const { data: stream, error: chatError } = trySync({
try: () => chat({ adapter, messages: body.messages }),
catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
});
if (chatError) {
if (chatError.name === 'AbortError') {
return status(499, 'Client closed request');
}
return status('Bad Gateway', `Provider error: ${chatError.message}`);
}
return toServerSentEventsResponse(stream);
};
这种转变遵循相同的人类推理模式:
这消除了嵌套,使 return 与 throw 保持一致,并将错误边界与后续的安全代码分离开来。
当一个处理程序有多个失败点时,每个卫语句都遵循相同的模式:执行操作,检查结果,提前返回或继续。
async ({ body, status }) => {
// 卫语句 1:验证输入
if (!isSupportedProvider(body.provider)) {
return status('Bad Request', `Unsupported provider: ${body.provider}`);
}
// 卫语句 2:解析依赖项
const apiKey = resolveApiKey(body.provider, headers['x-api-key']);
if (!apiKey) {
return status('Unauthorized', 'Missing API key');
}
// 卫语句 3:有风险的操作
const { data: stream, error } = trySync({
try: () => chat({ adapter: createAdapter(body.provider, apiKey) }),
catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
});
if (error) return status('Bad Gateway', error.message);
// 成功路径 —— 所有卫语句都通过了
return toServerSentEventsResponse(stream);
};
每个卫语句都具有相同的形态:检查 → 失败时提前返回。成功路径在底部累积。自上而下阅读时,在看到成功情况之前,你会看到函数可能失败的每一种方式。
每周安装量
60
代码仓库
GitHub 星标数
4.3K
首次出现
2026年1月20日
安全审计
已安装于
gemini-cli52
claude-code51
codex50
cursor50
opencode50
github-copilot47
When refactoring complex control flow, mirror natural human reasoning patterns:
Related Skills : See
refactoringfor systematic code audit methodology including branch collapsing and caller counting.
Use this pattern when you need to:
throw/return try-catch logic with readable early returns.isUsingNavigator, isUsingLocalTranscription, needsOldFileCleanup: names that read like thoughtsTransform this: nested conditionals with duplicated logic Into this: linear flow that mirrors human decision-making
// From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
export async function checkFfmpegRecordingMethodCompatibility() {
if (!window.__TAURI_INTERNALS__) return;
// Only check if FFmpeg recording method is selected
if (settings.value['recording.method'] !== 'ffmpeg') return;
const { data: ffmpegInstalled } =
await rpc.ffmpeg.checkFfmpegInstalled.ensure();
if (ffmpegInstalled) return; // FFmpeg is installed, all good
// FFmpeg recording method selected but not installed
toast.warning('FFmpeg Required for FFmpeg Recording Method', {
// ... toast content
});
}
// From apps/whispering/src/routes/(app)/_layout-utils/check-ffmpeg.ts
const isUsingNavigator = settings.value['recording.method'] === 'navigator';
const isUsingLocalTranscription =
settings.value['transcription.selectedTranscriptionService'] ===
'whispercpp' ||
settings.value['transcription.selectedTranscriptionService'] === 'parakeet';
return isUsingNavigator && isUsingLocalTranscription && !isFFmpegInstalled;
// From packages/epicenter/src/indexes/markdown/markdown-index.ts
/**
* This is checking if there's an old filename AND if it's different
* from the new one. It's essentially checking: "has the filename
* changed?" and "do we need to clean up the old file?"
*/
const needsOldFileCleanup = oldFilename && oldFilename !== filename;
if (needsOldFileCleanup) {
const oldFilePath = path.join(tableConfig.directory, oldFilename);
await deleteMarkdownFile({ filePath: oldFilePath });
tracking[table.name]!.deleteByFilename({ filename: oldFilename });
}
try-catch blocks create a nested, two-branch structure: the try body and the catch body. When only one call inside the try can actually throw, replace the try-catch with a guarded call + early return so the code reads top-to-bottom.
Before (nested, mixed throw/return):
async ({ body, status }) => {
const adapter = createAdapter(body.provider);
try {
const stream = chat({ adapter, messages: body.messages });
return toServerSentEventsResponse(stream);
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
throw status(499, 'Client closed request');
}
const message = error instanceof Error ? error.message : 'Unknown error';
throw status('Bad Gateway', `Provider error: ${message}`);
}
};
After (linear, consistent returns):
async ({ body, status }) => {
const adapter = createAdapter(body.provider);
const { data: stream, error: chatError } = trySync({
try: () => chat({ adapter, messages: body.messages }),
catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
});
if (chatError) {
if (chatError.name === 'AbortError') {
return status(499, 'Client closed request');
}
return status('Bad Gateway', `Provider error: ${chatError.message}`);
}
return toServerSentEventsResponse(stream);
};
The transformation follows the same human reasoning pattern:
This eliminates the nesting, makes return vs throw consistent, and separates the error boundary from the safe code that follows it.
When a handler has multiple failure points, each guard follows the same pattern: do the thing, check the result, return early or continue.
async ({ body, status }) => {
// Guard 1: validate input
if (!isSupportedProvider(body.provider)) {
return status('Bad Request', `Unsupported provider: ${body.provider}`);
}
// Guard 2: resolve dependency
const apiKey = resolveApiKey(body.provider, headers['x-api-key']);
if (!apiKey) {
return status('Unauthorized', 'Missing API key');
}
// Guard 3: risky operation
const { data: stream, error } = trySync({
try: () => chat({ adapter: createAdapter(body.provider, apiKey) }),
catch: (e) => Err(e instanceof Error ? e : new Error(String(e))),
});
if (error) return status('Bad Gateway', error.message);
// Happy path — all guards passed
return toServerSentEventsResponse(stream);
};
Every guard has the same shape: check → return early on failure. The happy path accumulates at the bottom. Reading top-to-bottom, you see every way the function can fail before you see the success case.
Weekly Installs
60
Repository
GitHub Stars
4.3K
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli52
claude-code51
codex50
cursor50
opencode50
github-copilot47
Next.js 15+ 最佳实践指南:文件约定、RSC边界、异步模式与性能优化
1,400 周安装