
修雨andClaude Opus 4.7
c7d8ddf98d
feat: align drive with wukong — helper (upload) + skill docs (doc/sheet dingpan URL) (#335)
* feat(helpers): drive upload 三步合成胶水(list-spaces / delete 由 envelope 接管)
业务背景:开源版 dws drive 仅有来自服务发现 envelope 的 6 个工具,悟空版多
3 个能力 — list-spaces / upload / delete。这 3 个里只有 upload 是真正的客户端
胶水(PUT 文件二进制到 OSS 的中间 HTTP 步),其它两个完全可以通过 envelope
toolOverrides 表达,无需 Go 代码。
按 envelope 优先原则拆分:
1. envelope/pre-discovery.pre.json (单独提供 / 不在本 commit)
- drive.toolOverrides.list_spaces → cliName: list-spaces
- drive.toolOverrides.delete_document → cliName: delete, serverOverride: doc,
isSensitive: true
2. internal/helpers/drive.go (本 commit)
- 仅注册 upload 一个 leaf
- 原因:envelope.PipelineStep 只支持 type:"call"/"download",没有
type:"upload"。客户端流式 PUT 本地文件到 OSS 签名 URL(含 per-URL
headers)当前 envelope schema 表达不了,故保留为 helper。
internal/helpers/drive.go (新增 ~290 行)
- upload — 三步合成:
1) drive get_upload_info → resourceUrl + uploadId + headers
2) HTTP PUT 文件二进制 → OSS(沿用 aitable upload-file 模式,
10min timeout,跟随 per-URL headers)
3) drive commit_upload → 提交入库
--dry-run 输出三步 invocation 预览不实际请求。
parseDriveUploadInfo 兼容 content/result 包裹层与 resourceUrls 数组
及 flat resourceUrl/uploadUrl fallback,与悟空侧 parseDriveUploadInfo
等价。
validateDriveParentID 拒纯数字 dentryId(防混淆 chat 链路 dentryId 与
drive 链路 dentryUuid)。
注入路径:helpers.RegisterPublic → pickCommands.MergeHardcodedLeaves(dynamic,
helper)(dynamic 赢冲突、helper 填空白)。本 helper root.Use="drive" 不覆盖
dynamic 的 6 个 leaf,仅追加 upload。
dry-run 实测:
$ dws drive upload --file /etc/hosts --dry-run --format json
→ step_1_get_upload_info + step_2_http_put_oss + step_3_commit_upload 三步预览
测试结果:
ok internal/helpers (含全部既有 TestSendByBot* / TestAtomicWrite* /
TestValidate* 等 23 个测试)
ok test/integration/extensions
test/cli_compat pre-existing failures 与本改动无关(在干净 origin/main HEAD
同样 fail,fixture 缺失等)。
未来工作 (follow-up):
- 等 envelope 文件 commit 到主线后,list-spaces / delete 自动从 envelope
生成 cobra command,无需此 helper 操心
- 如果 envelope schema 加入 type:"upload" pipeline 步类型,本 helper 整个
可以删除,由 envelope pipeline 表达完整三步
关联:
- 悟空源头实现:dws-wukong/wukong/products/drive.go
(runDriveUpload / parseDriveUploadInfo / httpPutFile + delete 路由)
- 配套 skill 文档 PR:#333 (doc 端钉盘 URL 识别)
- envelope 改动: drive.toolOverrides 增加 list_spaces + delete_document,
见对应的 envelope PR / commit
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(skill): doc --node 接受钉盘 document/edit|preview?dentryKey URL + 新增 url-patterns 分流
业务背景:hho 业务侧用户在悟空版上已用钉盘 URL(alidocs.dingtalk.com/document/edit?dentryKey=...)
直接喂给 Agent,但开源版 skill 文档未覆盖这种格式,Agent 不知道整段 URL 应原样传给 --node,
经常误把 dentryKey 当成裸 nodeId 调用导致失败。
本 PR 把悟空 dws-wukong PR #82157526 的 skill 文档增量移植到开源主线,保持 doc/sheet
两端入口的 URL 识别策略对齐悟空:
skills/SKILL.md
- 核心流程新增 Step 0「URL 预检」:含 alidocs URL 必须先读 url-patterns.md 分流,再选择产品
- 详细参考目录加入 url-patterns.md 引用
skills/references/products/doc.md
- dws doc info/read 的 Example 各 +2 行钉盘 URL 示例
- 「URL 识别与 DOC_ID 提取」支持的 URL 格式表新增 document/edit|preview?dentryKey={key} 一行
- 提取规则拆成 3 条,禁止 Agent 自行提取 dentryKey 当裸 nodeId
- 「nodeId 双格式说明」升级为「nodeId 多格式说明」,给出 4 种 --node 输入等价示例
skills/references/url-patterns.md (新建)
- 沉淀 alidocs URL 5 类分流决策:/i/p/ 短链 / /i/nodes/ 节点 / /spreadsheetv2/ 直链 /
/document/edit|preview?dentryKey 链接 / 其他
- 含 i/nodes/ 类型探测流程(doc info 探 contentType/extension/nodeType 后再选产品)
- 含分享短链 read_url 兜底处理 + 动态渲染失败时的标准答复
skill 命名形态兼容:
- 当前 main 上 skills/ 是扁平结构,改动直接落在 skills/* 路径
- 单点(mono)/ 多点(multi)拆分形态在 feature/skill-setup 分支,待该分支合主线时
按相同语义同步到 skills/mono/* 和 skills/multi/dingtalk-{doc,sheet}/* 两套
不涉及 Go 代码变更,纯 skill 文档;钉盘 URL 解析逻辑由 MCP 服务端承担。
关联悟空 PR:dws-wukong commit 565c63f8 / 712da968(#82157526)
对应 wukong skill 包:dingtalk-workspace/{SKILL.md,references/products/doc.md,references/url-patterns.md}
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:38:00 +08:00
..
2026-05-08 16:07:14 +08:00
2026-05-19 15:25:39 +08:00
2026-05-17 17:43:20 +08:00
2026-03-28 17:51:22 +08:00
2026-05-19 15:25:39 +08:00
2026-04-24 20:41:30 +08:00
2026-05-19 15:25:39 +08:00
2026-04-17 17:45:35 +08:00
2026-04-30 09:44:25 +08:00
2026-05-13 10:56:02 +08:00
2026-03-27 17:55:57 +08:00
2026-04-12 14:23:11 +08:00
2026-05-21 17:38:00 +08:00
2026-04-20 20:51:07 +08:00
2026-04-24 00:01:22 +08:00
2026-05-12 14:57:00 +08:00
2026-04-03 18:03:28 +08:00
2026-05-19 15:25:39 +08:00
2026-05-11 22:15:59 +08:00
2026-04-28 21:17:23 +08:00
2026-05-13 10:56:02 +08:00
2026-04-27 20:54:57 +08:00
2026-03-28 20:41:56 +08:00
2026-03-27 17:55:57 +08:00
2026-03-27 17:55:57 +08:00
2026-03-31 15:29:21 +08:00
2026-05-14 14:45:23 +08:00
2026-05-07 11:07:27 +08:00