Files
UHD_Media_Tool/packages/contracts/src/api/platform.ts
T
rootandClaude Opus 5.5 b752ce26f7 copy(contracts): 设置校验、事件说明与 API 摘要统一术语
恢复水位 / 硬阈值 → 恢复线 / 暂停线;库根、哨兵、Feed、快照、建档、纳管等按术语表改。

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
2026-10-07 01:52:24 +08:00

314 lines
11 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 { z } from "zod";
import * as cache from "../cache.ts";
import { WebSearchTestInput, WebSearchTestResult } from "../capabilities-io.ts";
import { CapabilityDescriptor, KnownCapabilityId } from "../capability.ts";
import { Id, IdParam } from "../common.ts";
import * as mcp from "../mcp.ts";
import * as pi from "../pi.ts";
import * as settingsNs from "../settings.ts";
import { GlobalSettings, GlobalSettingsUpdate } from "../settings.ts";
import { ep, OkResult } from "./shared.ts";
export const platformApi = {
// ── 能力 ──
capabilities: {
list: ep({
method: "get",
path: "/capabilities",
scope: "read",
summary: "能力注册中心描述",
response: z.object({ items: z.array(CapabilityDescriptor) }),
}),
invoke: ep({
method: "post",
path: "/capabilities/{capabilityId}/invoke",
scope: "read",
summary: "调用能力(实际所需 scope 见描述符;服务端按能力再次鉴权)",
params: z.object({ capabilityId: KnownCapabilityId }),
body: z.object({ input: z.unknown(), preview: z.boolean().default(false) }),
response: z.object({ output: z.unknown(), taskId: Id.nullable(), planId: Id.nullable() }),
}),
stats: ep({
method: "get",
path: "/capabilities/stats",
scope: "read",
summary: "能力调用统计:每能力调用数、失败数、平均耗时、最近调用、调用来源(内置智能体 / MCP / REST)",
query: mcp.CapabilityStatsQuery,
response: mcp.CapabilityStatsResponse,
}),
tools: ep({
method: "get",
path: "/capabilities/tools",
scope: "read",
summary: "能力清单:描述符、工具名、输入输出 JSON Schema、当前授权状态",
response: mcp.CapabilityToolsResponse,
}),
},
// ── 对外 MCP 服务端(Streamable HTTP 在 /mcp,不进 OpenAPI;这里是状态与配置)──
mcp: {
status: ep({
method: "get",
path: "/mcp/status",
scope: "admin",
summary: "MCP 服务端状态:启用、允许的 API Key、当前会话、最近调用、限速",
response: mcp.McpServerStatus,
}),
update: ep({
method: "patch",
path: "/mcp/config",
scope: "admin",
summary: "修改 MCP 服务端配置(启用开关、允许的 API Key)",
body: mcp.McpServerConfigUpdate,
response: mcp.McpServerConfig,
}),
},
// ── 缓存(C2-A,docs/runbook/cache.md) ──
cache: {
tmdb: ep({
method: "get",
path: "/cache/tmdb",
scope: "admin",
summary: "TMDB 缓存条目(请求响应与识别结果:键、过期时间、大小)与上限 / TTL",
query: cache.TmdbCacheQuery,
response: cache.TmdbCacheList,
}),
tmdbClear: ep({
method: "post",
path: "/cache/tmdb/clear",
scope: "admin",
summary: "清空 TMDB 缓存(请求响应与识别结果)",
response: cache.CacheClearResult,
}),
images: ep({
method: "get",
path: "/cache/images",
scope: "admin",
summary: "图片代理缓存用量",
response: cache.ImageCacheStatus,
}),
imagesClear: ep({
method: "post",
path: "/cache/images/clear",
scope: "admin",
summary: "清空图片代理缓存",
response: cache.CacheClearResult,
}),
regions: ep({
method: "get",
path: "/cache/regions",
scope: "admin",
summary: "通用缓存(kv_cache)按区统计:条目数、已过期数、占用字节、最近写入",
response: cache.CacheRegionList,
}),
regionClear: ep({
method: "post",
path: "/cache/regions/{region}/clear",
scope: "admin",
summary: "清空通用缓存的一个区",
params: cache.CacheRegionParam,
response: cache.CacheClearResult,
}),
},
// ── 网页搜索(WEB-1,docs/runbook/websearch.md) ──
websearch: {
test: ep({
method: "post",
path: "/websearch/test",
scope: "admin",
summary: "用已保存的搜索服务 Key 实际查询一次(不走缓存,计入每分钟上限)",
body: WebSearchTestInput,
response: WebSearchTestResult,
}),
},
// ── 设置 ──
settings: {
get: ep({ method: "get", path: "/settings", scope: "read", summary: "全局设置", response: GlobalSettings }),
update: ep({
method: "patch",
path: "/settings",
scope: "admin",
summary: "修改全局设置",
body: GlobalSettingsUpdate,
response: GlobalSettings,
}),
},
// ── 整理命名模板(W9-C,docs/design/naming-template.md):保存前服务端编译校验 ──
naming: {
variables: ep({
method: "get",
path: "/naming/variables",
scope: "read",
summary: "命名变量表(名称对齐 MP,含说明/示例值/我们特有标记)、过滤器、预览内置样本",
response: settingsNs.NamingVariablesResponse,
}),
preview: ep({
method: "post",
path: "/naming/preview",
scope: "read",
summary:
"预览:模板 + 样本(文件名 / 资源 / 已整理文件 / 内置)→ 相对路径、段角色、错误(行列号)、提示;已有路径绑定时目录用绑定",
body: settingsNs.NamingPreviewInput,
response: settingsNs.NamingPreviewResult,
}),
templates: ep({
method: "get",
path: "/naming/templates",
scope: "read",
summary: "全局 / 媒体库目录 / 作品三级模板与按类型的生效结果(作品 > 媒体库目录 > 全局)",
query: settingsNs.NamingTemplatesQuery,
response: settingsNs.NamingTemplatesView,
}),
saveTemplates: ep({
method: "put",
path: "/naming/templates",
scope: "admin",
summary: "保存全局命名模板(逐条编译校验,有错 422 不保存)",
body: settingsNs.NamingSettingsPut,
response: settingsNs.NamingSettings,
}),
libraryRoot: ep({
method: "put",
path: "/library-roots/{id}/naming",
scope: "admin",
summary: "媒体库目录级命名覆盖(按类型;null 清除)",
params: IdParam,
body: settingsNs.LibraryRootNamingPut,
response: settingsNs.LibraryRootNamingPut,
}),
entity: ep({
method: "put",
path: "/media-entities/{id}/naming-override",
scope: "admin",
summary: "作品级命名覆盖(按类型;null 清除)。已有路径绑定的目录不受影响,只影响之后的文件名与新季目录",
params: IdParam,
body: settingsNs.EntityNamingOverridePut,
response: settingsNs.EntityNamingOverridePut,
}),
},
// ── Pi 模型上游(W7-A):多上游共存 + 订阅登录;写操作与登录只接受控制台会话 ──
pi: {
providers: ep({
method: "get",
path: "/pi/providers",
scope: "admin",
summary: "Pi provider 能力表(认证方式、订阅登录方式与条款提示、baseUrl 覆盖、env 字段、静态模型表)",
query: pi.PiProvidersQuery,
response: pi.PiProvidersResponse,
}),
list: ep({
method: "get",
path: "/pi/upstreams",
scope: "admin",
summary: "模型服务列表(不含密钥)",
response: pi.PiUpstreamList,
}),
get: ep({
method: "get",
path: "/pi/upstreams/{id}",
scope: "admin",
summary: "模型服务详情",
params: IdParam,
response: pi.PiUpstream,
}),
create: ep({
method: "post",
path: "/pi/upstreams",
scope: "admin",
auth: "session",
summary: "新建模型服务(apiKey 只写,存 secret 表)",
body: pi.PiUpstreamCreate,
response: pi.PiUpstream,
}),
update: ep({
method: "patch",
path: "/pi/upstreams/{id}",
scope: "admin",
auth: "session",
summary: "修改模型服务(provider 不可改;makeDefault 设默认模型服务)",
params: IdParam,
body: pi.PiUpstreamUpdate,
response: pi.PiUpstream,
}),
remove: ep({
method: "delete",
path: "/pi/upstreams/{id}",
scope: "admin",
auth: "session",
summary: "删除模型服务(连同凭据;是默认模型服务时清空默认)",
params: IdParam,
response: OkResult,
}),
test: ep({
method: "post",
path: "/pi/upstreams/{id}/test",
scope: "admin",
auth: "session",
summary: "测试模型服务:默认只解析凭据与校验模型(不产生费用);mode=completion 发一次最小补全",
params: IdParam,
body: pi.PiUpstreamTestRequest,
response: pi.PiUpstreamTestResult,
}),
models: ep({
method: "get",
path: "/pi/upstreams/{id}/models",
scope: "admin",
summary: "模型列表:已获取过远程列表时返回远程与静态目录的合并(远程优先),否则静态目录",
params: IdParam,
response: pi.PiUpstreamModels,
}),
modelsRefresh: ep({
method: "post",
path: "/pi/upstreams/{id}/models/refresh",
scope: "admin",
auth: "session",
summary: "获取模型列表:用该模型服务的凭证调 provider 的模型列表接口并存库;失败或不支持时回静态目录并给出原因",
params: IdParam,
response: pi.PiUpstreamModels,
}),
modelsProbe: ep({
method: "post",
path: "/pi/models/probe",
scope: "admin",
auth: "session",
summary: "新建模型服务前试拉模型列表(凭证只用于这一次请求,不落库)",
body: pi.PiModelsProbeRequest,
response: pi.PiUpstreamModels,
}),
oauthStart: ep({
method: "post",
path: "/pi/upstreams/{id}/oauth/start",
scope: "admin",
auth: "session",
summary: "开始订阅登录:返回授权链接(browser)或验证码(device)",
params: IdParam,
body: pi.PiOAuthStartRequest,
response: pi.PiOAuthStartResult,
}),
oauthComplete: ep({
method: "post",
path: "/pi/upstreams/{id}/oauth/complete",
scope: "admin",
auth: "session",
summary: "完成订阅登录:browser 粘回地址栏 URL;device 服务端轮询(本次最多等 waitMs,未完成返回 pending)",
params: IdParam,
body: pi.PiOAuthCompleteRequest,
response: pi.PiOAuthCompleteResult,
}),
oauthLogout: ep({
method: "post",
path: "/pi/upstreams/{id}/oauth/logout",
scope: "admin",
auth: "session",
summary: "退出订阅登录:删除本地 token(不会撤销提供方侧授权)",
params: IdParam,
response: pi.PiUpstream,
}),
},
} as const;