feat(skill-marketplace): seed 4 demo Skills with publish→package→download pipeline (DR-51) - #53
Conversation
…oad 链路 (DR-51) 为 R2 下载演示补齐 DR-51 依赖的后端最小纵切,使 4 个 demo Skill 达到 「已发布 + 已打包 + 可下载」状态,满足 D-09 合规五条。 新增: - internal/skill/tiers: 平台 tier 别名注册表(smart/balanced/fast-tier), ValidateWhitelist 校验(DR-110)+ Resolve 解析(DR-96);tier→model 解析 表仅留在服务端,绝不进入下载包。 - internal/skill/model: skill_versions 表 + 迁移(sha256、单 active 版本部分 唯一索引、快照字段),迁移已接入 model/main.go。 - internal/skill/packaging: 发布即打包,BuildPackage 生成 zip(manifest.json + 可读 instruction_template + SKILL.md + 瘦客户端 run.py);构建期守卫拒绝 凭证与具体模型 id(FR-A20)。 - internal/skill/handler/download.go + 路由 GET /api/v1/marketplace/skills/:id/download (DR-81),由新增 middleware.SkillUserAuth 鉴权;无 key → AUTH_REQUIRED。 - internal/skill/seed + cmd/seed-skills: draft→version→publish 播种 4 个 Skill (polished-writer / faithful-translator / code-helper / data-analyst),按 slug 幂等。 D-09 合规:声明 tier 而非模型;输入/指令分离(用户内容走结构化 input,绝不 拼接进指令);服务端权威(下载绑定 skill_version_id,不信任包内模板);运行者 自带 key 计费(包内无凭证)。example_outputs 全部为合成数据。 仍缺(live demo 闭环的最后一块,属独立票 M05/DR-68):包内 run.py 调用的公开 路由执行端点 POST /api/v1/skills/run 尚未实现。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
完整测试覆盖与结果命令:
|
| 测试 | 断言 | 结果 |
|---|---|---|
TestValidAndResolve |
三个 tier 均有效且能解析到具体模型;硬编码模型 id 无效 | ✅ PASS |
TestValidateWhitelist |
合法 tier 列表通过;混入硬编码模型被拒;空列表被拒 | ✅ PASS |
TestResolvedModelsNonEmpty |
解析模型集非空;至少 3 个 tier | ✅ PASS |
internal/skill/model(skill_versions 模型 + 迁移,DR-47)
| 测试 | 断言 | 结果 |
|---|---|---|
TestMigrateSkillVersions_SQLite_SucceedsFromEmptyDB |
空库迁移成功 | ✅ PASS |
TestComputeTemplateSHA256_Stable |
sha256 确定性、64 位、内容不同则不同 | ✅ PASS |
TestSkillVersion_BeforeCreate_DefaultsAndSha |
BeforeCreate 补 id/sha;对象列默认 {}、数组列默认 [] |
✅ PASS |
TestSkillVersion_OneActivePerSkill_SQLite |
同一 skill 第二个 active 版本触发唯一约束 | ✅ PASS |
TestMonetizationSnapshotJSON |
快照含字段;nil quota 被省略 | ✅ PASS |
同包既有 skills / user_enabled_skills 测试(约 55 个)全部仍 PASS。
internal/skill/packaging(发布即打包 + 构建期守卫,DR-79/FR-A20)
| 测试 | 断言 | 结果 |
|---|---|---|
TestBuildPackage_Contents |
zip 含 manifest/SKILL.md/template/run.py;模板可读;manifest 绑定 skill_version_id + tier;run.py 强制 AUTH_REQUIRED + runner key | ✅ PASS |
TestBuildPackage_GuardRejectsConcreteModel |
包内出现具体模型 id 时构建被拒 | ✅ PASS |
TestBuildPackage_GuardRejectsCredential |
包内出现凭证样式 token 时构建被拒 | ✅ PASS |
TestBuildPackage_RejectsNonActiveVersion |
非 active 版本拒绝打包 | ✅ PASS |
internal/skill/handler(下载端点,DR-81)
| 测试 | 断言 | 结果 |
|---|---|---|
TestDownloadSkillPackage_Success |
200 + application/zip + 文件名;返回真 zip(PK 魔数);写入 entitlement 行 |
✅ PASS |
TestDownloadSkillPackage_AuthRequired |
未登录 → 401 AUTH_REQUIRED |
✅ PASS |
TestDownloadSkillPackage_NotFound |
未知 slug → 404 | ✅ PASS |
TestDownloadSkillPackage_DraftNotDownloadable |
草稿 Skill 不可下载 → 404 | ✅ PASS |
同包既有 marketplace/admin 列表与详情测试(约 28 个)全部仍 PASS。
internal/skill/seed(播种器,DR-46/47/48/51)
| 测试 | 断言 | 结果 |
|---|---|---|
TestSeedDemoSkills_CreatesFourPublishedPackagedSkills |
4 个 Skill 均 published + 有 active version + tier 合法 + 可成功打包 | ✅ PASS |
TestSeedDemoSkills_Idempotent |
重跑全部 up-to-date,skills/versions 各 4 条无增量 |
✅ PASS |
TestSeedDemoSkills_NewVersionOnTemplateChange |
模板变更后生成 v2 并保持唯一 active 版本 | ✅ PASS |
包级汇总
ok github.com/QuantumNous/new-api/relay
ok github.com/QuantumNous/new-api/internal/billing
ok github.com/QuantumNous/new-api/internal/kids
ok github.com/QuantumNous/new-api/internal/policy
ok github.com/QuantumNous/new-api/internal/quota
ok github.com/QuantumNous/new-api/internal/skill/api
ok github.com/QuantumNous/new-api/internal/skill/availability
ok github.com/QuantumNous/new-api/internal/skill/enums
ok github.com/QuantumNous/new-api/internal/skill/errcodes
ok github.com/QuantumNous/new-api/internal/skill/handler
ok github.com/QuantumNous/new-api/internal/skill/model
ok github.com/QuantumNous/new-api/internal/skill/packaging
ok github.com/QuantumNous/new-api/internal/skill/seed
ok github.com/QuantumNous/new-api/internal/skill/tiers
ok github.com/QuantumNous/new-api/internal/smart_router_client
main 已独立实现 Skill Marketplace 后端底座(skill_versions 模型 + 迁移、 download 端点 + 打包 + D-09 守卫、SkillUserAuth、DR-68 relay/executor、 skill_usage_events)。本次合并以 main 的实现为准,解决冲突并把 DR-51 收敛为 「在 main 底座之上播种 4 个 demo Skill」这一真正独有的交付物。 冲突解决(全部采用 main 版本): - internal/skill/handler/download.go(+test) - internal/skill/model/skill_version.go - middleware/skill-auth.go(main 已有 SkillUserAuth) - router/skill-router.go(main 已有 download 路由) - model/main.go 自动合并(main 已接入 MigrateSkillVersions) 删除我方冗余重复实现(main 已提供等价物): - internal/skill/model/skill_version_migrate.go、skill_version_test.go - internal/skill/packaging/*(改用 main 的 download 打包) 保留并适配的独有交付物: - internal/skill/seed/*、cmd/seed-skills:适配 main 的 SkillVersion (OutputSchema *SkillJSONB、RequiredPlanSnapshot 强类型、显式算 sha256、 内联 monetization snapshot);并在 Description 注入「## Work step」DeepRouter 路由调用,使 capability 包通过 main 的 D-09 下载守卫、可真正下载。 - internal/skill/tiers/*:tier 别名注册表(DR-110 校验)。 - internal/skill/relay/executor.go:selectModel 接入 tiers.Resolve(DR-96), tier 别名解析为具体模型,字面模型名透传,使播种的 tier 型 Skill 真正可路由。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
更新:已合并 main 并解决冲突(PR 收敛为「在 main 底座上播种」)
净改动 vs
测试(focused + regression):数据集 / 验证点 / 结果1.
|
|
Findings |
…t (DR-82) Review P1 (@pjwan2): seeded work steps used POST /v1/chat/completions, the ordinary chat endpoint, which bypasses the public-routing abuse gate — only /v1/routing/chat/completions is wired to markSkillPublicRoutingAPI + PublicRoutingAbuseControl (router/relay-router.go), and DR-82 explicitly excludes the ordinary endpoint from the stricter throttle. - workStepSection now references POST /v1/routing/chat/completions (still an accepted marker for main's D-09 download guard). - seed_download_test.go now asserts the package references /v1/routing/chat/completions AND NOT /v1/chat/completions, locking out the bypass instead of pinning it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@pjwan2 已修复 P1(commit 602b619)。感谢指出——确实把运行者引到了普通 chat 端点、绕过了公开路由滥用网关。 改动
验证
第三点建议(断言指向公开路由端点而非任意 DeepRouter 端点)也一并做了:正向断言公开路由路径 + 负向断言普通路径缺失。 |
背景 / Problem
DR-51 要求播种 4 个已发布 + 已打包 + 可下载的 demo Skill,用于 R2「下载 → 运行 → 路由」演示。但其依赖票(DR-46/47/48/79/81 + tier 别名注册表)此前均未实现——仓库里只有
skills表和只读的 marketplace/admin/ops GET 路由,缺少skill_versions模型、写入/发布/打包/下载 API 与 tier 别名。因此「播种」无法仅靠现有 API 完成,需要先补齐最小后端纵切。经确认采用演示纵切方案,并以 Go cmd + 迁移 驱动播种。
改动 / Fix
smart/balanced/fast-tier),校验 + 解析internal/skill/tiers/skill_versions模型 + 迁移(sha256、单 active 版本部分唯一索引、快照)internal/skill/model/skill_version*.go(接入model/main.go)manifest.json+ 可读instruction_template.txt+SKILL.md+ 瘦客户端run.py;构建期守卫拒绝凭证/具体模型 idinternal/skill/packaging/GET /api/v1/marketplace/skills/:id/download+ 新增SkillUserAuth(无登录 →AUTH_REQUIRED)internal/skill/handler/download.go、middleware/skill-auth.go、router/skill-router.gointernal/skill/seed/、cmd/seed-skills/D-09 合规(4 个 Skill 全部满足):
run.pyPOST 路由 API;包内无凭证/无路由逻辑,离线跑不了)model_whitelist仅含平台别名,已校验input,绝不拼接进指令skill_version_id,包内模板不被信任Authorization: Bearer <runner key>,无 key →AUTH_REQUIREDexample_outputs全部为合成数据。验证 / Verification
go test ./relay/ ./internal/...全部ok。tiers{}modelpackagingAUTH_REQUIRED/ 404 / 草稿不可下载handlerseedSQLITE_PATH=… go run ./cmd/seed-skills端到端跑通仍缺 / Out of scope
包内
run.py调用的公开路由执行端点POST /api/v1/skills/run(服务端解析 tier→model、套用权威模板、路由、对运行者计费)尚未实现——属 relay/执行层(M05 / DR-68),独立票。目前 create→version→publish→package→download 全部可用,仅「运行调用」缺服务端落点。🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com