返回 CodeWhale
page.tsx
根目录 / web / app / [locale] / docs / fleet / page.tsx
1 import { Fragment } from "react";
2 import { PRODUCT_TERMS } from "@/lib/content/vocabulary";
3 import { getDocsFleet, pickText, splitTokens } from "@/lib/i18n/dictionaries";
4 import { buildPageMetadata } from "@/lib/page-meta";
5
6 const CODE_SPANS: Record<string, string> = {
7 fleetSaved: "/fleet saved",
8 fleetStatusTui: "/fleet status",
9 fleetWorkers: "/fleet workers",
10 subagents: "/subagents",
11 fleetStatusShell: "codewhale fleet status",
12 };
13
14 export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
15 const { locale } = await params;
16 const t = getDocsFleet(locale);
17 return buildPageMetadata({
18 path: "/docs/fleet",
19 locale,
20 title: t.metaTitle,
21 description: t.metaDescription,
22 });
23 }
24
25 export default async function FleetPage({ params }: { params: Promise<{ locale: string }> }) {
26 const { locale } = await params;
27 const t = getDocsFleet(locale);
28 const vocabulary = PRODUCT_TERMS.map((row) => ({
29 term: row.term,
30 definition: pickText(row.long, locale),
31 }));
32
33 return (
34 <section className="space-y-10">
35 <section id="overview" className="scroll-mt-32">
36 <h1 className="font-display text-3xl mb-1">{t.overviewTitle}</h1>
37 <p className={`${t.bodyClassName} mt-3`}>{t.overviewLead}</p>
38 <div className="hairline-t mt-6">
39 {vocabulary.map((row) => (
40 <section key={row.term} className="py-4 hairline-b">
41 <h2 className="font-display text-xl">{row.term}</h2>
42 <p className={`${t.bodyClassName} mt-1 text-sm`}>{row.definition}</p>
43 </section>
44 ))}
45 </div>
46 </section>
47
48 <section id="cli" className="scroll-mt-32">
49 <h2 className="font-display text-2xl mb-1">{t.runTitle}</h2>
50 <p className={`${t.bodyClassName} mt-3`}>{t.runLead}</p>
51 <pre className="code-block mt-4">{`codewhale fleet run tasks.json --max-workers 4
52 codewhale fleet status
53 codewhale fleet inspect <worker-id>
54 codewhale fleet logs <worker-id>
55 codewhale fleet interrupt <worker-id>
56 codewhale fleet resume <run-id>
57 codewhale fleet stop --all`}</pre>
58 <p className={`${t.bodyClassName} mt-3`}>
59 {splitTokens(t.statusLead).map((part, i) =>
60 "token" in part ? (
61 <code key={`${i}-${part.token}`} className="inline">
62 {CODE_SPANS[part.token] ?? `{${part.token}}`}
63 </code>
64 ) : (
65 <Fragment key={`${i}-text`}>{part.text}</Fragment>
66 ),
67 )}
68 </p>
69 </section>
70
71 <section id="profiles" className="scroll-mt-32">
72 <h2 className="font-display text-2xl mb-1">{t.profilesTitle}</h2>
73 <p className={`${t.bodyClassName} mt-3`}>
74 {splitTokens(t.profilesLead).map((part, i) =>
75 "token" in part ? (
76 <code key={`${i}-${part.token}`} className="inline">
77 {CODE_SPANS[part.token] ?? `{${part.token}}`}
78 </code>
79 ) : (
80 <Fragment key={`${i}-text`}>{part.text}</Fragment>
81 ),
82 )}
83 </p>
84 </section>
85
86 <section id="workflow" className="scroll-mt-32">
87 <h2 className="font-display text-2xl mb-1">{t.workflowTitle}</h2>
88 <p className={`${t.bodyClassName} mt-3`}>{t.workflowLead}</p>
89 <p className={`${t.bodyClassName} mt-3`}>{t.workflowLimits}</p>
90 </section>
91
92 <section id="source" className="hairline-t pt-8">
93 <p className="text-sm text-ink-mute">{t.sourceNote}</p>
94 </section>
95 </section>
96 );
97 }
98
98 lines Plain Text