PROJECT IMPORT / API + DOCUMENTATION
把 URL 交给 WorkBuddy,
项目自动整理成草稿。
无需手填应用元信息。你选择项目并确认首次授权,WorkBuddy 上传必要源码;FDE 自动推断资料,你再检查与编辑。
上传成功不等于上架成功。不会自动运行、部署、付费审核或公开发布。1. 复制引导语给 WorkBuddy
在 WorkBuddy 中选择且明确授权一个应用项目。本页 URL 使用当前 FDE 服务的同源地址,不附带授权凭据。
2. 在 FDE 确认首次授权
WorkBuddy 请求授权后会给你短 user_code。请核对它来自你刚发起的操作,再在此输入。不要批准陌生人发来的授权码。
本次仅允许向你的账户成功上传一个私有草稿,权限为 apps:upload,不包含覆盖文件、管理账户、审核或发布。此页面不会读取或上传你的磁盘。
正在检查登录身份…
前往 /#workspace 登录开发者账户,登录后返回仅已登录 developer 可批准;不开放管理员注册或管理员公共授权。授权码在 600 秒后过期,过期请让 WorkBuddy 重新发起。
3. 上传后检查资料
WorkBuddy 应返回应用 ID、缺失字段、上传文件数及编辑链接 /#workspace。打开工作台,在已有草稿点击“编辑资料”,修订名称、简介、行业、场景、定价和运行入口。
metadata_status.missing_fields 表示待确认项,metadata_status.inferred_fields 表示自动推断项。need_confirm_pricing: true 时,即使兼容字段为 free 也不代表免费;不得替开发者擅自确认定价。
4. 提交审核与上架
流程:草稿 → 提交审核 → 平台审核 → 已上架。上传和编辑都不会自动提交审核;提交须由开发者本人在工作台点击“成本预估 / 提交”并确认。
- 提交前须资料完整:名称、简介、三级行业、场景、HTTPS 运行入口均已填写,且定价已由开发者确认(付费价格须大于零)。否则返回 409
metadata_incomplete,状态不变。 - 提交后先进入自动测试队列,由隔离执行器在断网、只读、无特权的容器中检查:入口文件、package.json、是否直连模型服务(须走平台网关)、是否含密钥或 .env、Python / JS 语法,以及在无头浏览器中打开首页(能否加载、是否有可见内容、有无未捕获脚本错误、本地资源是否缺失;外部请求一律拦截,仅作提示),并截取 1280×800 首屏截图,供开发者与平台审核在“审核记录”中查看(仅应用所有者与管理员可见)。全部通过后进入平台人工审核;任一项失败则回到“审核受阻”,失败原因显示在工作台。若失败原因是执行器多次超时(平台侧故障,非应用问题),平台管理员可直接重新安排测试,开发者会收到站内通知,无需重新提交;因应用自身问题未通过的,须修改后由开发者重新提交。
- 没有在线执行器时,提交会记为“审核受阻”,不执行代码、不扣费;平台不会越过测试直接上架。
- 审核中可“撤回审核”回到草稿;被驳回后,审核意见显示在工作台,修改资料即回到草稿可重新提交。
- 已上架应用可由开发者或平台“下架”(须填写原因),立即退出公开目录;修改后须重新审核才能再次上架。历史发布证书保留。
WorkBuddy / Agent 不得代替开发者提交审核、确认定价或下架。
给 WorkBuddy / Agent 的完整执行约定
- 读取本页公开说明不构成上传许可。先确定用户明确授权的项目根目录、必要源码范围与目的地;若不明确,先问用户。展示拟上传相对路径及排除类别,不得偷偷上传或扫描整个磁盘、主目录、工作区内其他项目。
- 仅在选定项目范围内收集必要 UTF-8 源码和配置,例如
package.json、index.html与必要业务源码。先按路径排除敏感文件,再对候选内容做凭据检查。遇到疑似秘密或私人数据应停下并让用户处理,不修改原文件、不自动删除或替换项目内容。 - 必须排除所有
.env*(包括示例环境文件)、密钥/证书/凭据、.git、.ssh、云账户目录、.npmrc、node_modules、虚拟环境、构建产物、缓存、日志、数据库、备份、无关文件及二进制内容。不要读取排除目录来“检查”。不要跟随符号链接越出授权范围,仅允许名单内的图片、字体、音视频与 PDF 资源经分批会话以 base64 上传;不得把压缩包、可执行文件或其他二进制改扩展名或转 Base64 绕过限制。 - 机器调用
POST /api/publish/device/start {};只把返回的短user_code和同源verification_uri交给用户。开发者本人在 FDE 页面登录并点击确认。Agent 不读取浏览器 Cookie、密码,不替用户调用 approve。 - 按返回的
interval(5 秒)调用 token,最多等到授权过期。仅409 authorization_pending继续等待;429 slow_down降低频率,授权过期或拒绝则停止。不得暴力重试或自动代替用户确认。 - 取得上传 token 后只在内存中暂存,用 Bearer 发到当前 FDE 服务的 import。不得放进 URL、HTML 元数据、聊天回复、日志、源文件、浏览器存储或发给其他站点。不得携带 session 或模型 API Key 代替上传 token。非本机部署必须先确认 HTTPS 服务可用,不能经不受信任网络发送源码。
- 文件不超过 100 个、合计不超过 4 MiB 且全为文本时用 import;否则用分批会话:先 sessions,再按每批 ≤200 个、请求体 ≤8 MiB 分批 files,最后以本地文件总数 complete。提交必要文件,metadata 整体及每个字段均可省略;不要求开发者填写表单,不填猜测价格。服务端依据项目材料生成可推断的资料;不确定字段保持待确认。
- 只在成功响应后报告“已保存私有草稿”,显示缺失字段、上传摘要和同源编辑链接;编辑链接必须解析到当前 FDE origin。请求失败或结果不确定不得声称上传成功,不调用 estimate、submit、审核、支付或发布接口。
代码只私有保存,不自动执行或公开,不覆盖已有本地文件。源码及上传摘要不是部署结果,也不是认证或上架证明。
真实 API 合同
以下相对路径均解析到本页所在 FDE origin。所有 POST / PATCH 请求使用 Content-Type: application/json;响应统一封装为 {"ok":true,"data":…},失败为 {"ok":false,"error":"…","error_code":"…"}(error_code 仅部分错误包含)。以 HTTP 状态和 ok 同时判断,不能直接把封装体当业务数据。
| 方法与路径 | 身份与请求体 | data 返回 / 状态 |
|---|---|---|
| POST /api/publish/device/start | 机器,无 session。{} | device_code, user_code, expires_in:600, verification_uri:"/publish.html", interval:5 |
| POST /api/publish/device/approve | developer 登录 session + 同源 CSRF 校验。{user_code} | {approved:true, scope:"apps:upload"};不返回上传 token。 |
| POST /api/publish/device/token | 机器,无 session。{device_code} | approved 后仅兑换一次:access_token, expires_in:900, scope:"apps:upload", token_type:"Bearer"。未确认:HTTP 409 + error_code:"authorization_pending";过快:429 slow_down;无效/过期/已兑换:401 invalid_grant。 |
| POST /api/publish/import | Authorization: Bearer <access_token>{idempotency_key,files:[{path,content}],metadata?} | {app,inferred_fields,missing_fields,edit_url:"/#workspace",upload:{files,bytes,sha256},status:"draft",notice} |
| POST /api/publish/sessions | Authorization: Bearer <access_token>{idempotency_key,metadata?} | 大型项目或含图片/字体等资源时使用。{session_id,status:"open",files,bytes,expires_in:3600,limits}。同一 token 只能二选一:单次 import 或一个会话。 |
| POST /api/publish/sessions/:session_id/files | 同一 Bearer。{files:[{path,content,encoding?}]},每批 1–200 个;encoding 为 utf-8(默认)或 base64。 | {accepted,skipped,files,bytes}。同路径同内容重传计入 skipped;同路径不同内容 409,不覆盖。 |
| POST /api/publish/sessions/:session_id/complete | 同一 Bearer。{expected_files} 为本地清单总数。 | 与 import 相同的草稿结果,另含 session_id 和 upload.binary_files。数量不一致:409 file_count_mismatch。重复 complete 返回同一结果。 |
| GET /api/publish/grants POST /api/publish/grants/:id/revoke | developer 登录 session;revoke 需同源 Origin,请求体 {}。 | 开发者在工作台查看与撤销授权;授权码打码显示。撤销会丢弃未完成会话,保留已生成草稿。Agent 不调用。 |
| GET /api/apps/:id/files | 本人 session(或管理员)。 | 文件清单:path、kind(text/binary)、bytes、sha256;不返回内容。 |
| GET /api/apps/:id/reviews | 本人 session(或管理员)。 | 当前状态、资料完整性检查 check,以及审核记录(提交、驳回、通过、撤回、下架及理由)。 |
| POST /api/apps/:id/submit | 本人 developer session;{"confirmed_estimate":true}。资料须完整。 | 平台有在线隔离测试执行器时:{app,test},应用进入 submitted、测试 queued;测试通过转为 pending_review 等待平台审核,未通过转为 review_blocked 并发站内通知(含未通过的检查项)。无在线执行器时:HTTP 503,状态 review_blocked,未执行、未扣费。已在队列中重复提交:409。 |
| POST /api/apps/:id/withdraw | 本人 developer session;请求体 {}。 | 审核中或受阻时撤回为草稿;其他状态 409。 |
| POST /api/apps/:id/unpublish | 本人 developer 或管理员 session;{"reason":"…"}。 | 仅已上架应用;下架为 unpublished,退出公开目录,证书保留。 |
| GET /api/notifications | 登录 session;可选 before(上一页 next_before)、limit(1-50,默认 20)、unread=1。 | 本人站内通知(按时间倒序分页)及未读数;平台审核通过、驳回、平台下架时通知开发者;开发者提交审核时通知管理员(撤回或审核后自动标为已处理),其余自身操作不产生通知。 |
| POST /api/notifications/read | 登录 session;{"all":true} 或 {"ids":[…]}(1-100 个)。 | 只能标记本人通知;返回最新列表。 |
| PATCH /api/apps/:id | 本人应用、登录 session + 同源 CSRF 校验;请求体为已修改的 metadata 字段,非 metadata 包装对象。 | data 为更新后的 app,含 metadata_status;仅已有草稿、审核阻断或拒绝状态可编辑;不会上传源码。 |
CSRF 与部署边界
浏览器使用 credentials:'same-origin' 携带 HttpOnly session,由浏览器自动发送 Origin。后端当前以同源 Origin 与 Fetch Metadata 校验防 CSRF,没有独立 CSRF token 接口;不要编造 X-CSRF-Token。机器免 session 的路径仅为 start、token、import,不能把此豁免用于 approve 或 PATCH。
当前本地实现按 http://Host 核对浏览器 Origin;HTTPS 反向代理部署需先完成服务端适配。本指南不承诺代理部署已经可用。
文件约束与幂等
- 1–100 个 UTF-8 文本文件;每个文件最多 256 KiB,文件内容合计最多 4 MiB,整个 JSON 请求最多 8 MiB。均按 UTF-8 字节计算,不是字符数。
- path 为选定项目内相对路径,使用
/,不允许绝对路径、路径穿越、重复路径或敏感目录。每项只接受 path 与 content。 - 单次 import 只接受文本。大型项目或含资源时改用分批会话:最多 1000 个文件、合计 64 MiB;文本单文件 ≤1 MiB,二进制单文件 ≤5 MiB。二进制仅限 png、jpg/jpeg、gif、webp、ico、woff/woff2、ttf/otf、mp3、wav、ogg、mp4、m4a、webm、pdf,扩展名与文件头必须匹配;不接受 ZIP、可执行文件、SVG 二进制或依赖包(SVG 请按文本上传)。
- 分批会话有效 1 小时,独立于 15 分钟 token 有效期:token 过期后仍可用同一 token 继续该会话,但不能新开会话;开发者撤销授权后立即失效。中断后按本地清单重传全部批次即可,已收到的同内容文件会被跳过。
idempotency_key为 1–128 位字母、数字、下划线或连字符。本次上传固定一个值。token 仅可成功上传一次;有效期内用同 token、同幂等键及同 payload 重试返回同 app ID,不新建草稿。不同键或不同 payload 在成功使用后返回 409;过期不能保证重放。结果不明先核对工作台,不自动重新授权重复上传。
metadata 与推断
可省略的字段:name, summary, industry, scene, pricing, price_cents, entry_url。name 最多120字符,summary 最多4000字符,industry 为有效三级行业路径,scene 为有效场景,pricing 为 free / paid / iap(空表示待确认),price_cents 为 0 至 10^12 的整数,entry_url 为校验通过的 HTTPS 公网入口。免费价格须为0,付费须大于0。
当前推断主要读取根目录 package.json 的 name / description / homepage,以及 index.html 的 title;行业场景只在名称与简介中唯一匹配时推断。不是任意源码语义都能识别,未知值标待确认,定价不能擅自确认。
JSON 请求结构示例(不是自动执行命令)
{
"idempotency_key": "authorized-project-draft-001",
"files": [
{"path": "package.json", "content": "{\"name\":\"my-app\",\"description\":\"应用说明\"}"},
{"path": "index.html", "content": "<!doctype html><title>我的应用</title>"}
]
}示例仅解释协议,实际 files 必须来自用户授权项目的必要源码,不上传本示例冒充真实项目。全部元信息可省略,由服务端推断。