feat(sources,organize): site agent capabilities and organize.minSizeBytes setting (W10-pre2)

- site.list / site.health_check / site.refresh_login / site.user_data capabilities
  over the W9-A site center services; outputs whitelisted (no secret refs,
  cookies, passwords, login names); execute kinds need automation grant.
  IDs use snake_case (CapabilityId regex); registry count 17 -> 21.
- settings.organize.minSizeBytes (default 50 MiB); file-manager identify /
  organize and planImport take request > setting > port default.
- tests and runbook notes (sites, files).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 16:02:30 +08:00
1 parent c08d8ce62a
commit 81bf010e3e
18 files changed
+563 -15

No files matched your search

@@ -53,7 +53,7 @@ describe.skipIf(skip)("files 识别 / 整理 / 探测 / 刮削", () => {
const r = await h.api(
"POST",
"/files/identify",
{ items: [{ root: h.dlRoot, path: "Some.Show.S01.1080p.WEB-DL" }] },
{ items: [{ root: h.dlRoot, path: "Some.Show.S01.1080p.WEB-DL" }], minSizeBytes: 0 },
READ_KEY,
);
expect(r.status).toBe(200);
@@ -72,6 +72,7 @@ describe.skipIf(skip)("files 识别 / 整理 / 探测 / 刮削", () => {
it("identify:远端候选(catalog.lookup)", async () => {
const r = await h.api("POST", "/files/identify", {
items: [{ root: h.dlRoot, path: "Remote.Film.2019.1080p.mkv" }],
minSizeBytes: 0,
});
expect(r.status).toBe(200);
const c = r.body.data.items[0].candidates;
@@ -82,7 +83,12 @@ describe.skipIf(skip)("files 识别 / 整理 / 探测 / 刮削", () => {
await mkdir(join(h.dl, "many"), { recursive: true });
const names = Array.from({ length: 23 }, (_, i) => `Distinct Title ${String.fromCharCode(65 + i)}.2019.1080p.mkv`);
for (const n of names) await writeFile(join(h.dl, "many", n), "x");
const r = await h.api("POST", "/files/identify", { items: [{ root: h.dlRoot, path: "many" }] }, READ_KEY);
const r = await h.api(
"POST",
"/files/identify",
{ items: [{ root: h.dlRoot, path: "many" }], minSizeBytes: 0 },
READ_KEY,
);
expect(r.status).toBe(200);
expect(r.body.data.items).toHaveLength(23);
const capped = r.body.data.items.filter((i: { warnings: string[] }) => i.warnings.some((w) => w.includes("上限")));