docs(plan): v0.2 adds Pi subagents and scheduled-jobs board

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-28 02:09:39 +08:00
1 parent b839ed4056
commit 16ab2a6c84
97 files changed
+592 -648

No files matched your search

@@ -19,10 +19,10 @@ import { errorMessage } from "~/lib/api.ts";
import { formatBytes } from "~/lib/utils.ts";
const STEPS = [
"生成下载计划并预留 Slot 与预算(同一 Slot 同时只有一个在途计划)",
"去重:已有相同资源或同 hash 任务时走接管,不重复提交",
"缓存卷硬阈值检查:超过阈值或读不到磁盘状态时阻止新提交,不能手动绕过",
"选择下载器实例并打管理标签提交;下单前复核免费/做种等易变字段",
"生成下载计划,预留版本目标和预算;每个版本目标同时只有一个在途计划",
"已有相同资源或相同 hash 的任务时直接接管,不重复提交",
"缓存卷超过硬阈值或读不到磁盘状态时无法提交",
"提交前复核免费、做种等易变字段",
];
/**
@@ -56,10 +56,10 @@ export function DownloadDialog({
if (r.submitted && r.plan) {
setRejected(null);
setDone(r.plan.id);
toast.success(`已提交(计划${slotName(r.slotId) ? ` · ${slotName(r.slotId)}` : ""}),进度见“下载与任务”`);
toast.success(`已提交${slotName(r.slotId) ? `(${slotName(r.slotId)})` : ""},进度见“下载与任务”`);
} else {
setRejected(r.rejected);
toast.warning("没有生成下载计划,原因见对话框");
toast.warning("没有生成下载计划");
}
},
onError: (e) => toast.error(errorMessage(e)),
@@ -102,9 +102,7 @@ export function DownloadDialog({
</div>
) : (
<p className="text-meta text-muted-foreground">
{release.entity
? "该作品还没有版本目标(Slot),需要先在订阅里建目标才能提交。"
: "资源尚未识别到本地作品,请先在“身份与元数据”指定作品。"}
{release.entity ? "这个作品没有版本目标。先在订阅里新建。" : "资源未关联本地作品。先在“身份与元数据”指定。"}
</p>
)}
{rejected ? (
@@ -124,7 +122,7 @@ export function DownloadDialog({
<p className="text-caption text-success">
计划已生成。
<Link to="/console/tasks" className="underline underline-offset-4">
去“下载与任务”查看
查看
</Link>
</p>
) : null}
@@ -108,7 +108,7 @@ export function FeedFormDialog({
if (!parsed.success) {
const e = zodFieldErrors(parsed.error.issues);
if (e.pollIntervalSec) e.pollMin = "轮询间隔至少 1 分钟";
if (e.url) e.url = feed ? "URL 格式不对" : "需要完整的 Feed URL";
if (e.url) e.url = feed ? "URL 格式不对" : "填写完整的 Feed URL";
if (e.name) e.name = "名称不能为空";
setErrors(e);
return;
@@ -116,7 +116,7 @@ export function FeedFormDialog({
setErrors({});
const done = {
onSuccess: () => {
toast.success(feed ? "已保存" : "已新建 Feed,会按轮询策略抓取");
toast.success(feed ? "已保存" : "Feed 已创建");
onOpenChange(false);
},
onError: (e: unknown) => toast.error(errorMessage(e)),
@@ -130,7 +130,7 @@ export function FeedFormDialog({
<DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-lg">
<DialogHeader>
<DialogTitle>{feed ? "编辑 Feed" : "新建 Feed"}</DialogTitle>
<DialogDescription>URL 可能含 passkey,只写入加密凭证,之后只显示脱敏地址。</DialogDescription>
<DialogDescription>URL 加密保存,之后只显示脱敏地址。</DialogDescription>
</DialogHeader>
<form
className="grid gap-1"
@@ -248,7 +248,7 @@ export function FeedFormDialog({
/>
</FormField>
<div className="flex items-center justify-between gap-3 py-1 text-caption text-foreground">
<label htmlFor="feed-enabled">启用(关闭后停止轮询,历史观察保留)</label>
<label htmlFor="feed-enabled">启用(关闭后停止轮询)</label>
<Switch id="feed-enabled" checked={d.enabled} onCheckedChange={(v) => set("enabled", v)} />
</div>
<DialogFooter className="mt-2 gap-2">
@@ -33,9 +33,9 @@ function LocalInventory({ release, entry }: { release: WorkbenchRelease; entry:
if (!release.entity) {
return (
<p className="text-caption text-muted-foreground">
尚未识别到本地作品({release.resolutionStatus}),不显示库存推断。
未关联本地作品({release.resolutionStatus})。
<Link to="/console/identity" className="ml-1 underline underline-offset-4">
去身份与元数据处理
去指定作品
</Link>
</p>
);
@@ -100,7 +100,7 @@ function LocalInventory({ release, entry }: { release: WorkbenchRelease; entry:
})}
</ul>
) : (
<p className="text-meta text-muted-foreground">规则引擎还没评估过这条资源。</p>
<p className="text-meta text-muted-foreground">这条资源还没有评估。</p>
)}
</>
)}
@@ -177,8 +177,8 @@ export function ReleaseDetailSheet({
{
onSuccess: (d) =>
d.refreshError
? toast.warning(`复核失败,保留既有数据:${d.refreshError}`)
: toast.success("已从站点复核详情"),
? toast.warning(`复核失败,显示上次数据:${d.refreshError}`)
: toast.success("已复核"),
onError: (e) => toast.error(errorMessage(e)),
},
)
@@ -197,7 +197,7 @@ export function ReleaseDetailSheet({
<>
{detail.data.refreshError ? (
<p className="mb-2 rounded-lg border border-warning/40 bg-warning/10 px-3 py-2 text-caption text-warning">
最近一次复核失败,以下为既有数据(已过期):{detail.data.refreshError}
最近一次复核失败,以下是过期数据:{detail.data.refreshError}
</p>
) : null}
<KvList
@@ -211,9 +211,7 @@ export function ReleaseDetailSheet({
{ label: "详情抓取于", value: formatDateTime(detail.data.volatile.detailFetchedAt) },
]}
/>
<p className="mt-2 text-meta text-muted-foreground">
缓存命中不代替下单前复核:提交下载时会再次核对免费与做种状态。
</p>
<p className="mt-2 text-meta text-muted-foreground">提交下载时会再次核对免费和做种状态。</p>
</>
) : null}
</DetailSection>
@@ -232,7 +230,7 @@ export function ReleaseDetailSheet({
{ label: "首次发现", value: formatDateTime(r.firstSeenAt) },
{ label: "最近确认", value: `${formatDateTime(r.dataUpdatedAt)}(${ORIGIN_LABEL[r.origin]})` },
{ label: "Feed 观察次数", value: r.observedByFeeds },
{ label: "站点资源 ID", value: r.siteReleaseId, mono: true },
{ label: "站点 ID", value: r.siteReleaseId, mono: true },
{ label: "infohash", value: r.infohashV1 ?? r.infohashV2, mono: true, wide: true },
]}
/>
@@ -64,7 +64,7 @@ export function SnapshotPanel({ site }: { site: Site }) {
snap.mutate(
{ id: site.id, maxPages: 2 },
{
onSuccess: () => toast.success(`${site.name}:已排队手动快照`),
onSuccess: () => toast.success(`${site.name}:快照已排队`),
onError: (e) => toast.error(errorMessage(e)),
},
)
@@ -80,7 +80,7 @@ export function SnapshotPanel({ site }: { site: Site }) {
) : snaps.error ? (
<ErrorState plain error={snaps.error} onRetry={() => void snaps.refetch()} />
) : !snaps.data.items.length ? (
<p className="text-caption text-muted-foreground">还没有快照记录。</p>
<p className="text-caption text-muted-foreground">还没有快照。</p>
) : (
<ul className="divide-y divide-border/60 text-caption">
{snaps.data.items.map((s) => (