Files
codewhale/web/app/[locale]/faq/page.tsx
T
2026-05-31 17:43:46 -07:00

721 lines
33 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Link from "next/link";
import { Seal } from "@/components/seal";
export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
return {
title: isZh ? "常见问题 · CodeWhale" : "FAQ · CodeWhale",
description: isZh
? "CodeWhale 常见问题:安装、配置、提供商、模型、模式、安全与隐私。答案来自实际代码、文档和 GitHub 议题。"
: "CodeWhale frequently asked questions: install, config, providers, models, modes, security, and privacy. Answers sourced from real code, docs, and GitHub issues.",
};
}
interface FaqItem {
q: string;
a: React.ReactNode;
sources?: string[];
}
const faqEn: FaqItem[] = [
{
q: "What is CodeWhale?",
a: (
<>
CodeWhale is a terminal-native coding agent for open-source and open-weight models. It runs from the <code className="inline">codewhale</code> command, streams reasoning blocks, edits local workspaces with approval gates, and can auto-route each turn to the right model and thinking level. DeepSeek V4 is the first-class model path; OpenRouter is ready. Hugging Face, self-hosted, and other open-model surfaces are on the roadmap.
</>
),
sources: ["README.md", "docs/ARCHITECTURE.md"],
},
{
q: "How do I install CodeWhale?",
a: (
<>
<p className="mb-2">Four paths, same result:</p>
<pre className="code-block mb-2">
{`# npm (recommended — no Rust toolchain needed)
npm install -g codewhale
# Cargo (needs Rust 1.88+)
cargo install codewhale-cli --locked
cargo install codewhale-tui --locked
# Homebrew (macOS)
brew tap Hmbown/deepseek-tui && brew install deepseek-tui
# Direct download
# https://github.com/Hmbown/CodeWhale/releases`}
</pre>
<p>
Run <code className="inline">codewhale</code> to start. First run creates <code className="inline">~/.codewhale/</code> automatically. Legacy <code className="inline">~/.deepseek/</code> is still read as a compatibility fallback.
See the <Link href="/install" className="body-link">full install guide</Link> for China mirrors, Docker, and troubleshooting.
</p>
</>
),
sources: ["README.md", "#1860", "#1914"],
},
{
q: "What's the difference between codewhale and codewhale-tui?",
a: (
<>
<code className="inline">codewhale</code> is the dispatcher CLI it manages config, auth, updates, and launches the TUI.
<code className="inline">codewhale-tui</code> is the terminal UI binary that runs the agent loop.
When you type <code className="inline">codewhale</code>, the dispatcher spawns <code className="inline">codewhale-tui</code> for you.
Both are installed together; you rarely need to think about the split.
</>
),
sources: ["README.md"],
},
{
q: "Is CodeWhale the same as DeepSeek TUI? What about the rename?",
a: (
<>
Yes. CodeWhale is the new name for what was previously called DeepSeek TUI.
The canonical command is now <code className="inline">codewhale</code>. Legacy <code className="inline">deepseek</code> and <code className="inline">deepseek-tui</code> commands remain as compatibility shims they still work.
Config lives at <code className="inline">~/.codewhale/</code>. Legacy <code className="inline">~/.deepseek/</code> config is still read as a compatibility fallback, and <code className="inline">DEEPSEEK_*</code> env vars continue to work.
DeepSeek is not deprecated. The rename reflects CodeWhale's broader mission as the agentic terminal for open models across providers, not a narrowing away from DeepSeek.
</>
),
sources: ["docs/REBRAND.md", "README.md"],
},
{
q: "How do I set my API key?",
a: (
<>
<pre className="code-block mb-2">
{`# Method 1: Environment variable
export DEEPSEEK_API_KEY=sk-...
# Method 2: Saved config (recommended — survives shell restarts)
codewhale auth set --provider deepseek --api-key sk-...
# Method 3: config.toml
# Add to ~/.codewhale/config.toml:
api_key = "sk-..."
# Check what's active:
codewhale auth status # shows config, keyring, and env-var state
codewhale doctor # full connectivity check`}
</pre>
<p>
Saved config keys take precedence over environment variables.
Use <code className="inline">codewhale auth clear --provider deepseek</code> to remove a saved key.
</p>
</>
),
sources: ["#907", "#1545", "docs/CONFIGURATION.md"],
},
{
q: "Which providers does CodeWhale support?",
a: (
<>
<p className="mb-2">CodeWhale ships with these built-in providers:</p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> — first-class, native API. Reasoning streaming, cache metrics, thinking effort control.</li>
<li><strong>OpenRouter</strong> — unified API for DeepSeek models and more.</li>
<li><strong>OpenAI</strong>, <strong>NVIDIA NIM</strong>, <strong>Volcengine Ark</strong>, <strong>Xiaomi MiMo</strong>, <strong>SiliconFlow</strong>, <strong>Novita</strong>, <strong>Fireworks</strong>, <strong>sglang</strong>, <strong>vLLM</strong>, <strong>Ollama</strong></li>
</ul>
<p>
Set the corresponding env var (e.g. <code className="inline">OPENROUTER_API_KEY</code>) and your provider in <code className="inline">~/.codewhale/config.toml</code>.
Self-hosted OpenAI-compatible endpoints are supported through the provider config.
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978", "#1710"],
},
{
q: "How do I use OpenRouter with CodeWhale?",
a: (
<>
<pre className="code-block mb-2">
{`# 1. Set your OpenRouter key
export OPENROUTER_API_KEY=sk-or-v1-...
# 2. In ~/.codewhale/config.toml:
[providers.openrouter]
api_key = "sk-or-v1-..."
# 3. Run with an OpenRouter model:
codewhale --model openrouter/deepseek/deepseek-v4-pro
# Or set it as default in config.toml:
default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
</pre>
<p>
OpenRouter uses the same reasoning/cache parser as the native DeepSeek provider.
Model IDs follow the <code className="inline">provider/model-id</code> pattern (e.g. <code className="inline">openrouter/deepseek/deepseek-v4-flash</code>).
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978"],
},
{
q: "Can I use self-hosted or local models (vLLM, Ollama, llama.cpp)?",
a: (
<>
Yes. Use the <code className="inline">vllm</code>, <code className="inline">sglang</code>, or <code className="inline">ollama</code> providers with your local endpoint.
For OpenAI-compatible endpoints (llama.cpp server, text-generation-webui, Aphrodite, etc.), you can use the <code className="inline">openai</code> provider with a custom <code className="inline">base_url</code>.
CodeWhale also respects <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> for local HTTP endpoints.
Full Hugging Face TGI/vLLM integration is on the roadmap.
</>
),
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
},
{
q: "What are Plan, Agent, and YOLO modes?",
a: (
<>
<ul className="list-disc pl-5 space-y-2 text-sm text-ink-soft">
<li><strong>Plan</strong> — Read-only investigation. Can grep, read files, list directories, fetch URLs. Cannot write or execute shell.</li>
<li><strong>Agent</strong> — Default mode. Multi-step tool calling. Shell and side-effect tools require approval based on your approval_mode setting.</li>
<li><strong>YOLO</strong> — Auto-approves all operations and enables trust mode. Workspace boundaries lift. Use carefully.</li>
</ul>
<p className="mt-2">
Press <kbd className="font-mono text-xs px-1.5 py-0.5 hairline-t hairline-b hairline-l hairline-r">Tab</kbd> to cycle modes.
Approval mode (suggest / auto / never) is orthogonal — you can be in Agent mode with auto-approval, for example.
</p>
</>
),
sources: ["docs/MODES.md"],
},
{
q: "What is model auto-routing? What is Fin?",
a: (
<>
<p className="mb-2">
Use <code className="inline">codewhale --model auto</code> or <code className="inline">/model auto</code> to let CodeWhale decide how much model power each turn needs.
</p>
<p className="mb-2">
<strong>Fin</strong> is the fast non-thinking path (<code className="inline">deepseek-v4-flash</code> with thinking off) used for routing decisions, summaries, RLM children, context maintenance, and other coordination work. Before the real turn is sent, Fin makes a small routing call to pick the concrete model and thinking level.
</p>
<p>
Short/simple turns can stay on Flash with thinking off. Coding, debugging, release work, architecture, or security review can move up to Pro and/or higher thinking. Fin is local to CodeWhale — the upstream API never receives <code className="inline">model: "auto"</code>.
</p>
</>
),
sources: ["README.md", "#1207"],
},
{
q: "What does /goal do?",
a: (
<>
<code className="inline">/goal</code> is a simple goal-setter for the current session.
It does not add another app mode; the mode switcher remains Plan, Agent, and YOLO.
Track progress in <a href="https://github.com/Hmbown/CodeWhale/issues/891" className="body-link">#891</a>.
</>
),
sources: ["#891"],
},
{
q: "Is my code safe? What sandboxing does CodeWhale use?",
a: (
<>
CodeWhale runs entirely on your machine. No telemetry, no cloud processing of your code.
Sandbox backends: <strong>seatbelt</strong> (macOS), <strong>landlock</strong> (Linux), restricted tokens (Windows).
Workspace boundaries default to <code className="inline">--workspace</code>. <code className="inline">/trust</code> lifts them.
Approval mode is configurable per session. All credential/approval/elevation events are written to <code className="inline">~/.codewhale/audit.log</code>.
</>
),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
},
{
q: "How do MCP servers work?",
a: (
<>
CodeWhale is a bidirectional MCP client and server. Define servers in <code className="inline">~/.codewhale/mcp.json</code>.
Tools appear as <code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code>. You can also expose CodeWhale as an MCP server with <code className="inline">codewhale mcp</code>.
See the <Link href="/docs#mcp" className="body-link">docs page</Link> for configuration examples.
</>
),
sources: ["docs/MCP.md"],
},
{
q: "How do I contribute?",
a: (
<>
No CLA required. Fork, branch with conventional commits (<code className="inline">feat:</code>, <code className="inline">fix:</code>, etc.), run the local checks, open a PR.
The maintainer reads everything personally. Start with issues labeled <code className="inline">good first issue</code>.
See the <Link href="/contribute" className="body-link">contribute page</Link> and <a href="https://github.com/Hmbown/CodeWhale/blob/main/CONTRIBUTING.md" className="body-link">CONTRIBUTING.md</a>.
</>
),
sources: ["CONTRIBUTING.md"],
},
{
q: "I'm in China — how do I install? Downloads are slow.",
a: (
<>
Use mirror registries:
<pre className="code-block my-2">
{`# npm mirror
npm config set registry https://registry.npmmirror.com
npm install -g codewhale
# Cargo mirror (Tsinghua TUNA)
# Add to ~/.cargo/config.toml:
[source.crates-io]
replace-with = "tuna"
[source.tuna]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
</pre>
<p>
Prebuilt binaries are also available from <a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>.
The Gitee mirror and CNB mirror may also be available.
</p>
</>
),
sources: ["README.md", "#1914", "docs/CNB_MIRROR.md"],
},
{
q: "My API key was rejected or I get auth errors on first run.",
a: (
<>
<p className="mb-2">Run <code className="inline">codewhale doctor</code> — it checks API key, network, sandbox, and MCP servers. Full report is written to <code className="inline">~/.codewhale/doctor.log</code>.</p>
<p className="mb-2">Common causes:</p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Stale <code className="inline">DEEPSEEK_API_KEY</code> in shell startup file — open a fresh shell or use <code className="inline">codewhale auth set</code></li>
<li>Key from wrong provider — make sure the key matches the provider you're using</li>
<li>Network connectivity — check <code className="inline">curl https://api.deepseek.com/v1/models</code></li>
</ul>
</>
),
sources: ["#907", "#1545"],
},
{
q: "What is Model Lab? When will Hugging Face integration be available?",
a: (
<>
Model Lab is the planned open-model infrastructure layer: Hugging Face Hub API for model discovery, model cards, datasets, safetensors adapters, inference providers, and Jobs.
It is NOT fully implemented. Track progress in <a href="https://github.com/Hmbown/CodeWhale/issues/1977" className="body-link">#1977</a>.
Currently, you can use Hugging Face models through the OpenRouter provider or self-hosted endpoints.
</>
),
sources: ["#1977", "docs/MODEL_LAB.md"],
},
{
q: "Why is token consumption so high? / Why is cache hit rate low?",
a: (
<>
CodeWhale sends substantial context (system prompt, project instructions, tool definitions) with each turn.
DeepSeek's prefix cache is used aggressively — the system prompt is layered to maximize cache hits.
If you see high token usage, check: are you using <code className="inline">deepseek-v4-pro</code> for simple queries better suited to Flash?
Model auto-routing (Fin) can help pick the right model per turn.
Cache hit rate depends on prompt stability — modifying the system prompt or switching models resets the cache.
</>
),
sources: ["#1177", "#1818", "#743"],
},
{
q: "How do I update CodeWhale?",
a: (
<>
<pre className="code-block mb-2">
{`# Release-binary updater (works for npm/release-binary installs)
codewhale update
# npm
npm install -g codewhale@latest
# Cargo
cargo install codewhale-cli --locked --force
# Homebrew
brew update && brew upgrade deepseek-tui`}
</pre>
<p>
If you installed via npm, <code className="inline">codewhale update</code> downloads the latest release binaries.
If a mirror is lagging, download directly from <a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>.
</p>
</>
),
sources: ["README.md", "#1869", "#1914"],
},
];
const faqZh: FaqItem[] = [
{
q: "CodeWhale 是什么?",
a: (
<>
CodeWhale 是一个面向开源模型的终端原生编程智能体。通过 <code className="inline">codewhale</code> 命令启动,流式输出推理块,在有审批门槛的情况下编辑本地工作区,并可为每个回合自动选择最合适的模型和推理深度。DeepSeek V4 是一级模型路径;OpenRouter 已就绪。Hugging Face、自托管等开放模型接口已在路线图中。
</>
),
sources: ["README.md", "docs/ARCHITECTURE.md"],
},
{
q: "如何安装 CodeWhale",
a: (
<>
<p className="mb-2">四种方式,殊途同归:</p>
<pre className="code-block mb-2">
{`# npm Rust
npm install -g codewhale
# Cargo Rust 1.88+
cargo install codewhale-cli --locked
cargo install codewhale-tui --locked
# HomebrewmacOS
brew tap Hmbown/deepseek-tui && brew install deepseek-tui
#
# https://github.com/Hmbown/CodeWhale/releases`}
</pre>
<p>
<code className="inline">codewhale</code> <code className="inline">~/.codewhale/</code> <code className="inline">~/.deepseek/</code> 退
<Link href="/zh/install" className="body-link"></Link> Docker
</p>
</>
),
sources: ["README.md", "#1860", "#1914"],
},
{
q: "codewhale 和 codewhale-tui 有什么区别?",
a: (
<>
<code className="inline">codewhale</code> CLI TUI
<code className="inline">codewhale-tui</code> UI
<code className="inline">codewhale</code> <code className="inline">codewhale-tui</code>
</>
),
sources: ["README.md"],
},
{
q: "CodeWhale 和 DeepSeek TUI 是什么关系?改名是怎么回事?",
a: (
<>
CodeWhale DeepSeek TUI <code className="inline">codewhale</code> <code className="inline">deepseek</code> <code className="inline">deepseek-tui</code>
<code className="inline">~/.codewhale/</code> <code className="inline">~/.deepseek/</code> 退<code className="inline">DEEPSEEK_*</code>
DeepSeek CodeWhale 广使 DeepSeek
</>
),
sources: ["docs/REBRAND.md", "README.md"],
},
{
q: "如何设置 API 密钥?",
a: (
<>
<pre className="code-block mb-2">
{`# 方法 1:环境变量
export DEEPSEEK_API_KEY=sk-...
# 方法 2:保存在配置中(推荐 — 重启 Shell 后仍然有效)
codewhale auth set --provider deepseek --api-key sk-...
# 方法 3config.toml
# 在 ~/.codewhale/config.toml 中添加:
api_key = "sk-..."
# 查看当前状态:
codewhale auth status # 显示配置、密钥环和环境变量状态
codewhale doctor # 完整连接检查`}
</pre>
<p>
使 <code className="inline">codewhale auth clear --provider deepseek</code>
</p>
</>
),
sources: ["#907", "#1545", "docs/CONFIGURATION.md"],
},
{
q: "CodeWhale 支持哪些提供商?",
a: (
<>
<p className="mb-2">CodeWhale </p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft mb-3">
<li><strong>DeepSeek</strong> API</li>
<li><strong>OpenRouter</strong> API访 DeepSeek </li>
<li><strong>OpenAI</strong><strong>NVIDIA NIM</strong><strong>Volcengine Ark</strong><strong>Xiaomi MiMo</strong><strong>SiliconFlow</strong><strong>Novita</strong><strong>Fireworks</strong><strong>sglang</strong><strong>vLLM</strong><strong>Ollama</strong></li>
</ul>
<p>
<code className="inline">OPENROUTER_API_KEY</code> <code className="inline">~/.codewhale/config.toml</code>
OpenAI provider
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978", "#1710"],
},
{
q: "如何使用 OpenRouter",
a: (
<>
<pre className="code-block mb-2">
{`# 1. 设置 OpenRouter 密钥
export OPENROUTER_API_KEY=sk-or-v1-...
# 2. 在 ~/.codewhale/config.toml 中:
[providers.openrouter]
api_key = "sk-or-v1-..."
# 3. 使用 OpenRouter 模型运行:
codewhale --model openrouter/deepseek/deepseek-v4-pro
# 或在 config.toml 中设为默认:
default_text_model = "openrouter/deepseek/deepseek-v4-pro"`}
</pre>
<p>
OpenRouter 使 DeepSeek /
ID <code className="inline">provider/model-id</code> <code className="inline">openrouter/deepseek/deepseek-v4-flash</code>
</p>
</>
),
sources: ["docs/CONFIGURATION.md", "#1978"],
},
{
q: "可以使用自托管或本地模型吗(vLLM、Ollama、llama.cpp)?",
a: (
<>
使 <code className="inline">vllm</code><code className="inline">sglang</code> <code className="inline">ollama</code>
OpenAI llama.cpp servertext-generation-webui 使 <code className="inline">openai</code> <code className="inline">base_url</code>
CodeWhale <code className="inline">DEEPSEEK_ALLOW_INSECURE_HTTP=true</code> HTTP
Hugging Face TGI/vLLM 线
</>
),
sources: ["#574", "#1303", "docs/CONFIGURATION.md"],
},
{
q: "Plan、Agent、YOLO 三种模式有什么区别?",
a: (
<>
<ul className="list-disc pl-5 space-y-2 text-sm text-ink-soft">
<li><strong>Plan</strong> grep URL Shell</li>
<li><strong>Agent</strong> Shell approval_mode </li>
<li><strong>YOLO</strong> 使</li>
</ul>
<p className="mt-2">
<kbd className="font-mono text-xs px-1.5 py-0.5 hairline-t hairline-b hairline-l hairline-r">Tab</kbd>
/ / Agent 使
</p>
</>
),
sources: ["docs/MODES.md"],
},
{
q: "什么是模型自动路由?Fin 是什么?",
a: (
<>
<p className="mb-2">
使 <code className="inline">codewhale --model auto</code> <code className="inline">/model auto</code> CodeWhale
</p>
<p className="mb-2">
<strong>Fin</strong> <code className="inline">deepseek-v4-flash</code>RLM Fin
</p>
<p>
Flash + Pro /Fin CodeWhale API <code className="inline">model: "auto"</code>
</p>
</>
),
sources: ["README.md", "#1207"],
},
{
q: "什么是 Goal 模式?现在可用吗?",
a: (
<>
Goal / <code className="inline">/goal</code>
<code className="inline">/goal</code> Goal /
<a href="https://github.com/Hmbown/CodeWhale/issues/891" className="body-link">#891</a>
</>
),
sources: ["#891"],
},
{
q: "我的代码安全吗?CodeWhale 使用什么沙箱机制?",
a: (
<>
CodeWhale
<strong>seatbelt</strong>macOS<strong>landlock</strong>LinuxWindows
<code className="inline">--workspace</code><code className="inline">/trust</code>
// <code className="inline">~/.codewhale/audit.log</code>
</>
),
sources: ["SECURITY.md", "docs/ARCHITECTURE.md"],
},
{
q: "MCP 服务器如何工作?",
a: (
<>
CodeWhale MCP <code className="inline">~/.codewhale/mcp.json</code>
<code className="inline">mcp_&lt;server&gt;_&lt;tool&gt;</code> <code className="inline">codewhale mcp</code> CodeWhale MCP
<Link href="/zh/docs#mcp" className="body-link"></Link>
</>
),
sources: ["docs/MCP.md"],
},
{
q: "如何参与贡献?",
a: (
<>
CLAFork<code className="inline">feat:</code><code className="inline">fix:</code> PR
<code className="inline">good first issue</code>
<Link href="/zh/contribute" className="body-link"></Link> <a href="https://github.com/Hmbown/CodeWhale/blob/main/CONTRIBUTING.md" className="body-link">CONTRIBUTING.md</a>
</>
),
sources: ["CONTRIBUTING.md"],
},
{
q: "我在国内,安装很慢怎么办?",
a: (
<>
使
<pre className="code-block my-2">
{`# npm 镜像
npm config set registry https://registry.npmmirror.com
npm install -g codewhale
# Cargo 镜像(清华 TUNA
# 在 ~/.cargo/config.toml 中添加:
[source.crates-io]
replace-with = "tuna"
[source.tuna]
registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`}
</pre>
<p>
<a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>
Gitee CNB
</p>
</>
),
sources: ["README.md", "#1914", "docs/CNB_MIRROR.md"],
},
{
q: "首次运行时提示 API 密钥被拒绝或认证错误?",
a: (
<>
<p className="mb-2"> <code className="inline">codewhale doctor</code> API MCP <code className="inline">~/.codewhale/doctor.log</code></p>
<p className="mb-2"></p>
<ul className="list-disc pl-5 space-y-1 text-sm text-ink-soft">
<li>Shell <code className="inline">DEEPSEEK_API_KEY</code> Shell 使 <code className="inline">codewhale auth set</code></li>
<li>使</li>
<li> <code className="inline">curl https://api.deepseek.com/v1/models</code></li>
</ul>
</>
),
sources: ["#907", "#1545"],
},
{
q: "Model Lab 是什么?Hugging Face 集成什么时候可用?",
a: (
<>
Model Lab Hugging Face Hub API safetensors Jobs
<a href="https://github.com/Hmbown/CodeWhale/issues/1977" className="body-link">#1977</a>
OpenRouter 使 Hugging Face
</>
),
sources: ["#1977", "docs/MODEL_LAB.md"],
},
{
q: "为什么 token 消耗这么大?/ 缓存命中率为什么低?",
a: (
<>
CodeWhale
DeepSeek 使
token 使使 <code className="inline">deepseek-v4-pro</code> Flash
Fin
</>
),
sources: ["#1177", "#1818", "#743"],
},
{
q: "如何更新 CodeWhale",
a: (
<>
<pre className="code-block mb-2">
{`# 发布二进制更新器(适用于 npm/二进制安装)
codewhale update
# npm
npm install -g codewhale@latest
# Cargo
cargo install codewhale-cli --locked --force
# Homebrew
brew update && brew upgrade deepseek-tui`}
</pre>
<p>
npm <code className="inline">codewhale update</code>
<a href="https://github.com/Hmbown/CodeWhale/releases" className="body-link">GitHub Releases</a>
</p>
</>
),
sources: ["README.md", "#1869", "#1914"],
},
];
export default async function FaqPage({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
const isZh = locale === "zh";
const items = isZh ? faqZh : faqEn;
return (
<>
<section className="mx-auto max-w-[1400px] px-6 pt-12 pb-8">
<div className="flex items-baseline gap-4 mb-3">
<Seal char="问" />
<div className="eyebrow">{isZh ? "常见问题" : "FAQ"}</div>
</div>
<h1 className="font-display tracking-crisp">
{isZh ? (
<> <span className="font-cjk text-indigo text-5xl ml-2">FAQ</span></>
) : (
<>FAQ <span className="font-cjk text-indigo text-5xl ml-2"></span></>
)}
</h1>
<p className="mt-5 max-w-3xl text-ink-soft text-lg leading-[1.9] tracking-wide">
{isZh
? "答案来自实际代码、文档、发布说明和 GitHub 议题。每个回答下方标注了信息来源。如有未覆盖的问题,请在 GitHub 上提交 Issue。"
: "Answers sourced from real code, docs, release notes, and GitHub issues. Sources are cited below each answer. If your question isn't covered, open an issue on GitHub."}
</p>
</section>
<section className="mx-auto max-w-[1400px] px-6 pb-20">
<div className="space-y-0 hairline-t hairline-b">
{items.map((item, i) => (
<details key={i} className="group hairline-b last:border-b-0">
<summary className="px-0 py-5 cursor-pointer flex items-start gap-4 hover:text-indigo transition-colors">
<span className="font-mono text-indigo tabular text-sm pt-0.5 shrink-0">
{String(i + 1).padStart(2, "0")}
</span>
<span className="font-display text-lg leading-snug flex-1">{item.q}</span>
<span className="font-mono text-ink-mute text-sm group-open:rotate-45 transition-transform shrink-0">+</span>
</summary>
<div className="pb-5 pl-10 pr-4">
<div className={`text-ink-soft leading-relaxed ${isZh ? "leading-[1.9] tracking-wide" : ""}`}>
{item.a}
</div>
{item.sources && item.sources.length > 0 && (
<div className="mt-3 flex items-center gap-2 flex-wrap">
<span className="font-mono text-[0.66rem] text-ink-mute uppercase tracking-wider">
{isZh ? "来源" : "Sources"}:
</span>
{item.sources.map((s) => (
<span key={s} className="font-mono text-[0.7rem] text-indigo">{s}</span>
))}
</div>
)}
</div>
</details>
))}
</div>
<div className="mt-12 text-center">
<p className="text-ink-soft text-sm mb-4">
{isZh
? "没找到你的问题?"
: "Didn't find your question?"}
</p>
<a
href="https://github.com/Hmbown/CodeWhale/issues/new/choose"
className="inline-flex items-center gap-2 px-5 py-3 bg-ink text-paper font-mono text-sm uppercase tracking-wider hover:bg-indigo transition-colors"
>
{isZh ? "提交 Issue →" : "Open an issue →"}
</a>
</div>
</section>
</>
);
}