Files
修雨 5ce7cb61b0 feat(skill): dws skill setup with mono/multi modes (#332)
新增 `dws skill setup` 交互式安装命令,支持单产品(mono)和多产品(multi,标记为试验版)两种 skill 布局,并与开源 dws v1.0.30 命令对齐。

主要变更:
- 骨架:skills/ 拆为 skills/mono/ 和 skills/multi/(29 个产品 skill),git rename 保留历史
- 命令:新增 `skill setup` cobra 子命令,支持 --mode、--target、--source、--yes,huh 交互
  - multi 模式支持 -s/--skill、-x/--exclude 按产品选择
  - 覆盖全部 14 个 agent home 目录(与 install.sh 一致)
- 发布:install.sh / install.ps1 / post-goreleaser.sh 改读 skills/mono;dws-skills.zip 同时包含 mono 和 multi 内容;~/.dws 本地缓存
- 内容对齐:删除 8 个仅内部使用的产品 skill、dingtalk-a2a;修正 mono/multi 共 15+ 处命令引用以匹配 OSS dws v1.0.30;chat skill 从 dws-wukong 回移更新
- 漂移清理:物理删除 skill 文档中 OSS 未暴露的命令,true-fail 命令转为 caveat;--help diff 100% 覆盖审计
- 测试:新增 Layer A 静态命令调度验证 + Layer B 端到端 mock 调度验证
- 同步 main:drive 9 个命令同步到 mono/multi skill
2026-05-26 09:17:37 +08:00

88 lines
2.6 KiB
Python
Raw Permalink 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.
#!/usr/bin/env python3
"""
从 dt_media_upload 返回的 URL 中提取 mediaId。
用法:
python extract_media_id.py <url>
python extract_media_id.py "https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw_960_1280.png"
# 输出: @lQLPD4JNnliqBq3NBQDNA8Cw
依赖: 无(纯 Python 标准库)
典型工作流(发送图片/语音/视频消息):
# 1. 用 dt_media_upload 上传文件,获得 URL
# 2. 用本脚本从 URL 提取 mediaId
python extract_media_id.py "<dt_media_upload 返回的 URL>"
# 输出: @lQLPxxx(直接用于 --media-id 或 --pic-url 参数)
"""
import argparse
import re
import sys
from urllib.parse import urlparse
def extract_media_id(url: str) -> str:
"""从 dt_media_upload 返回的 URL 中提取 mediaId。
支持的 URL 格式示例:
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw_960_1280.png
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw.png
https://down.dingtalk.com/media/lQLPD4JNnliqBq3NBQDNA8Cw
提取规则:
1. 取 URL 路径中 /media/ 之后的部分
2. 去除尾部的 _数字_数字.扩展名 后缀(如 _960_1280.png)
3. 如果没有尺寸后缀,去除尾部的 .扩展名
4. 加上 @ 前缀
返回: @lQLPD4JNnliqBq3NBQDNA8Cw
"""
url = url.strip()
# 提取路径部分
parsed = urlparse(url)
path = parsed.path # e.g. /media/lQLPxxx_960_1280.png
# 取 /media/ 之后的部分
media_prefix = "/media/"
idx = path.find(media_prefix)
if idx == -1:
print(f"错误:URL 中未找到 /media/ 路径: {url}", file=sys.stderr)
sys.exit(1)
raw = path[idx + len(media_prefix):] # e.g. lQLPxxx_960_1280.png
if not raw:
print(f"错误:/media/ 后无内容: {url}", file=sys.stderr)
sys.exit(1)
# 尝试去除 _数字_数字.扩展名 后缀(如 _960_1280.png)
match = re.match(r'^(.+?)(_\d+_\d+\.\w+)$', raw)
if match:
media_id = match.group(1)
else:
# 没有尺寸后缀,尝试去除 .扩展名
match2 = re.match(r'^(.+)\.\w+$', raw)
if match2:
media_id = match2.group(1)
else:
# 无后缀,直接使用
media_id = raw
return f"@{media_id}"
def main():
parser = argparse.ArgumentParser(
description="从 dt_media_upload 返回的 URL 中提取 mediaId"
)
parser.add_argument("url", help="dt_media_upload 返回的文件 URL")
args = parser.parse_args()
media_id = extract_media_id(args.url)
print(media_id)
if __name__ == "__main__":
main()