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:
1 parent
c08d8ce62a
commit
81bf010e3e
18 files changed
+563
-15
No files matched your search
@@ -42,7 +42,7 @@
|
||||
| # | 接口 | 要点 |
|
||||
|---|---|---|
|
||||
| G1 | `POST /files/entity-from-candidate {provider:"tmdb", externalId, kind:"movie"\|"tv"}`;`/files/organize` 项 `external`(与 `mediaEntityId` 二选一,都给/都不给 400) | 取 TMDB 详情建 `media_entity` + `external_identity`(accepted,`evidence_level=manual`,IMDb 同时登记)+ 别名;剧集按 TMDB 季表建季/集单元(provisional,单季 ≤200 集)。幂等:同 TMDB id 已有 accepted 映射直接复用(跟随合并),并发冲突重试一次。organize 预览阶段就地建(同一请求内同一候选只建一次),组里 `entity{provider,externalId,created,title}`。TMDB 未配置 400、无此条目 404、上游失败 502(`upstream:`)。服务在 `sources-identity/service/entity-from-candidate.ts`(`createEntityFromTmdbCandidate`),TMDB 客户端经 `SourcesRuntime.tmdb()`(设置 `metadata.tmdb*`) |
|
||||
| G2 | organize `minSizeBytes`;identify `minSizeBytes` | 缺省取 `settings.organize.minSizeBytes`(设置契约加字段前恒缺省 → organize 用端口 `minVideoBytes` 50 MiB,identify 不过滤)。organize:低于阈值的视频进组 `excluded[]`,`reason=below_min_size`(sample/no_episode 等照原因名);identify:该项 `skipped="below_min_size"`、不查候选,结果 `excludedBySize` 计数;每项带 `size` |
|
||||
| G2 | organize `minSizeBytes`;identify `minSizeBytes` | 缺省取 `settings.organize.minSizeBytes`(缺省 50 MiB,W10-pre2 起进契约);设置读不到时 organize 退回端口 `minVideoBytes`,identify 不过滤。请求 / 向导给的值优先,给 0 表示不过滤。自动入库的 `planImport` 同样按"请求 > 设置 > 端口"取值。设置页还没有这个字段(前端后续在「媒体库与目录 → 整理方式」加),目前只能 `PATCH /settings` `{"organize":{"minSizeBytes":<字节>}}` 修改。organize:低于阈值的视频进组 `excluded[]`,`reason=below_min_size`(sample/no_episode 等照原因名);identify:该项 `skipped="below_min_size"`、不查候选,结果 `excludedBySize` 计数;每项带 `size` |
|
||||
| G3 | organize `onExisting: skip\|conflict\|replace_with_verify`(缺省 conflict) | 透传 `planImport.onExisting`;选 replace 即视为人工授权(`grantReplace`),执行走现有 replace 分支(新文件核验通过后旧文件进回收站)。预览逐文件 `action`(transfer/replace/skip/hold)+ `existing`(same 同一文件已在库 / skip / replace / conflict / null)+ `skipReason`;conflict 时该组 `error.code=plan_blocked`。策略进请求指纹,换策略须重新预览 |
|
||||
| G4 | organize `naming: template\|keep`(缺省 template) | keep = 保留源文件名(目录仍按模板/绑定/targetDir;改名后撞名 → hold + duplicate_target)。`planImport` 新参数 `namingMode` / `namingSource`,冻结计划 `organization_record.plan.naming = {mode, templateSource: entity\|root\|global\|override, templateVersion}`(模板来源按 作品 > 库根 > 全局 回落;keep = override)。组响应同名 `naming` + `targetSegments[{text, role: root\|season\|dir, bound}]`(bound = 沿用已有路径绑定) |
|
||||
| G5 | identify 项 `records{count,lastRecordId,lastStatus}`;`GET /files/record-sources?recordId=`;organize `refreshMetadata`;`POST /files/scrape-batch` | 整理记录按 `organization_file_result.source_path` 回查;record-sources 把记录主视频源(多个且同在源目录下时给目录)按登记目录 hostPath 换算成 FileRef,不在登记目录/已不存在的进 `unresolved`。`refreshMetadata=true`:执行成功的组按作品去重各排一次 `refreshMetadata`(组里 `refreshTaskId`)。scrape-batch:`items`(文件/目录 → 其下已登记资产的作品)∪ `mediaEntityIds` 去重,≤200 个作品;无 active 资产 `not_registered`、不存在 `not_found`、文件不属于任何作品 `no_entity`;带幂等键 |
|
||||
|
||||
@@ -71,6 +71,22 @@
|
||||
|
||||
运行时每 30 s 最多重读一次设置;设置变化会让站点适配器按新签名重建。
|
||||
|
||||
## Agent 能力(W10-pre2)
|
||||
|
||||
处理器在 `apps/server/src/modules/sources-identity/capabilities-sites.ts`,调用上面同一组 service。能力 ID 只允许小写 + 下划线(`CapabilityId` 正则),所以规格里的 `site.healthCheck` / `site.refreshLogin` / `site.userData` 落为下划线形式。
|
||||
|
||||
| 能力 | 类别 | 风险 | 重放 | HTTP scope | 说明 |
|
||||
|---|---|---|---|---|---|
|
||||
| `site.list` | read | low | safe | read | 站点健康、`lastHealth`、整体账号状态与账号摘要;缺省只列启用站点(`includeDisabled`、`keys` 可选) |
|
||||
| `site.health_check` | execute | low | safe | admin | 同 `POST /sites/{id}/health-check`;幂等,只读首页并写回健康列,所以例外地声明 replay safe |
|
||||
| `site.refresh_login` | execute | medium | never | admin | 同步执行 `refreshSiteAccount(mode=login)`,上限 30 s(同时跟随任务取消);`accountId` 缺省取第一个启用的非 passkey 账号 |
|
||||
| `site.user_data` | read | low | safe | read | 各账号最近一次用户数据 + `site_user_data` 按天历史(`days` 缺省 30,最多 400) |
|
||||
|
||||
- 授权:两个 execute 能力走通用授权,Agent / API Key / 后台调用必须有 `automation_grant`(`action` 为能力 ID 或 `*`),自动化总开关关闭或只读对账时一律拒绝;控制台管理员从 Web 直接调用视为人工授权。没有计划可绑定,所以不走单次审批。
|
||||
- 脱敏:输出按白名单逐字段拼装,没有 `secretRef` / `sessionSecretRef` / `passkeySecretRef`、Cookie、密码、登录名、UA 与站点 `config`;凭证只给 `hasSession` / `hasPasskey` 两个布尔。测试 `apps/server/test/sources-identity/site-capabilities.test.ts` 逐项断言。
|
||||
- 注册数:首批能力 17 → 21,启动断言 `assertCapabilityCount` 跟随 `CAPABILITY_IDS.length`。
|
||||
- 未接:`agent/invoke-limits.ts` 的站点并发上限还没把 `site.health_check` / `site.refresh_login` 算作外部站点调用;Agent 默认只读白名单(`agent/runner.ts`)也还没加 `site.list` / `site.user_data`。两处都在 agent 模块,留给该模块的负责人。
|
||||
|
||||
## 待核验
|
||||
|
||||
1. takelogin 表单字段、二次验证字段名、错误文本全部只对 `@umt/testkit` mock 站点验证过,未连接真实站点。
|
||||
|
||||
Reference in new issue
Block a user