用于与 DM 系统交互的命令行工具。
bash
npm install -g deepminer-cli
bash
dm-cli config init --endpoint <API端点> --accesskey <AccessKey> --json
bash
dm-cli auth status --json
⚠️ 终止正在运行的任务必须用 thread stop,不能用发消息!
❌ 错误做法(只是发消息,不会终止任务):
bash
dm-cli thread start --thread-id xxx --message "取消任务"
✅ 正确做法:
bash
# 停止正在运行的 Agent
dm-cli thread stop --thread-id <thread_id>
# 取消异步标注任务(需要 task_id)
dm-cli task lifecycle --thread-id <thread_id> --task-id <task_id> --action cancel
命令对照表:
场景命令停止正在运行的 Agentdm-cli thread stop --thread-id <id>取消异步标注任务dm-cli task lifecycle --thread-id <id> --task-id <id> --action cancel
为什么重要:
每次使用本 Skill 前,必须检查版本是否为最新。
检查方法:
bash
# 获取 ClawHub 上的最新版本(带缓存,每天最多检查一次)
CACHE_FILE="/tmp/dmskills_version_cache"
if [ -f "$CACHE_FILE" ] && [ $(( $(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || stat -c %Y "$CACHE_FILE") )) -lt 86400 ]; then
LATEST=$(cat "$CACHE_FILE")
else
LATEST=$(curl -sL "https://clawhub.ai/dmpm-mininglamp/deepminer-skill" | grep -o 'version:"[^"]*"' | head -1 | cut -d'"' -f2)
echo "$LATEST" > "$CACHE_FILE"
fi
当前最新版本: 读取本文件 frontmatter 中的 version 字段
本地版本检查:
读取本 SKILL.md 文件 frontmatter 中的 version 字段。
版本不一致时:
text
⚠️ DeepMiner-skills 版本过旧!
本地版本:<frontmatter 中的 version>
最新版本:<LATEST 变量值>
请访问 https://clawhub.ai/dmpm-mininglamp/deepminer-skill 下载最新版本,
或使用 clawhub CLI 更新:
clawhub install dmpm-mininglamp/deepminer-skill
更新后继续执行任务。
为什么重要:
用户的 prompt 必须原样传递给 DM,禁止任何改写、润色或添加解释。
DM 返回的 last_messages 必须原样提取并返回,禁止省略、改写或总结。
--thread-id 追问⚠️ 除非用户明确要求在主 session 执行,否则一律使用 subagent!
原因:
使用 subagent 的方式:
typescript
sessions_spawn({
runtime: "subagent",
task: "使用 dm-cli 执行 DM 任务:{用户原始请求}",
mode: "run"
})
例外情况(可以在主 session 执行):
为什么重要:
⚠️ 追问前必须先检查上一次任务状态!
原因:如果上一次任务还在 running,直接追问可能会失败或被拒绝。
流程:
text
1. 用户发送追问指令
↓
2. 检查上一次 DM 任务状态
dm-cli thread result --thread-id <id> --json
↓
3. 根据 state 决定下一步:
- running → 需要使用 --force(见下方说明)
- ask_human/completed/failed → 直接追问
代码示例:
bash
# 追问前检查状态
prev_result=$(dm-cli thread result --thread-id "$thread_id" --json)
prev_state=$(echo "$prev_result" | jq -r '.data.state')
case "$prev_state" in
"running")
# 需要告知用户风险,确认后使用 --force
echo "⚠️ 上一次任务仍在执行中,追问会中断当前任务。"
echo "是否继续?(使用 --force 强制追问)"
# 等待用户确认后执行
dm-cli thread start --thread-id "$thread_id" --message "追问内容" --force --json
;;
"ask_human"|"completed"|"failed")
# 直接追问
dm-cli thread start --thread-id "$thread_id" --message "追问内容" --json
;;
esac
--force 参数说明#作用:强制停止当前正在运行的 agent_run,立即接受新消息。
使用场景:
running 状态风险:
示例:
bash
# 不带 --force(running 状态可能失败)
dm-cli thread start --thread-id abc123 --message "新问题" --json
# 可能返回错误:会话正在运行中
# 带 --force(强制中断当前任务)
dm-cli thread start --thread-id abc123 --message "新问题" --force --json
# 成功,但之前的任务被中断
最佳实践:
--forcecompleted 后再追问⚠️ 启动异步任务必须用 CLI 命令,不能用追问消息!
背景:DM 的所有异步任务(包括批量标注、批量媒体下载等)注册后都会进入 PENDING 状态, 必须通过 task lifecycle --action start 显式启动,不会自动执行。 PENDING 不是"排队等候",而是"等待用户确认才启动"。
通用规则:看到任何异步任务返回 state: pending,立即执行 task lifecycle --action start。
常见会触发异步任务的工具调用:
sample_data_label / 批量标注 → 返回 task_id + PENDINGmedia_download_task_register / 批量媒体下载 → 返回 task_id + pending两者都需要 start,否则任务永远不会执行。
❌ 错误做法(会导致任务被取消)
bash
# 错误:用追问消息启动任务
dm-cli thread start --thread-id "$thread_id" --message "请开始执行异步标注任务"
# 结果:任务被取消,状态变为 rejected
✅ 正确流程
步骤命令状态变化1️⃣thread start --message "确认执行全量标注"``ask_human → async_tag_task2️⃣等待状态稳定,获取 task_idPENDING3️⃣task lifecycle --action start``PENDING → RUNNING(真正启动)
完整代码示例
bash
# 步骤 1:第一次追问(提交异步任务)
dm-cli thread start --thread-id "$thread_id" --message "确认执行全量标注" --json
# 步骤 2:等待状态稳定,获取 task_id
sleep 10
result=$(dm-cli thread result --thread-id "$thread_id" --json)
state=$(echo "$result" | jq -r '.data.state')
task_id=$(echo "$result" | jq -r '.data.status_info.task_id')
if [ "$state" = "async_tag_task" ]; then
# 步骤 3:用 CLI 命令启动任务(关键!)
dm-cli task lifecycle --thread-id "$thread_id" --task-id "$task_id" --action start --json
echo "✅ 异步任务已启动执行!"
echo "任务ID: $task_id"
fi
关键命令:task lifecycle
参数说明--thread-id会话 ID--task-id异步任务 ID(从 status_info.task_id 获取)--action操作类型: start(启动)、 interrupt(中断)、 resume(恢复)、 cancel(取消)
状态说明
任务状态可执行操作PENDING✅ start(启动)RUNNING✅ interrupt(中断)INTERRUPTED✅ resume(恢复)或 cancel(取消)rejected❌ 无法启动(任务已取消)
常见错误
错误结果❌ 用追问消息启动任务被取消,状态变为 rejected❌ 不等待状态稳定task_id 未返回,无法启动❌ 任务状态不是 PENDINGCLI 返回 "Cannot start task in xxx state"
通知用户
第一次追问后:
text
📋 异步任务已提交(PENDING)
任务ID: xxx
预估积分: 45-90 credits
等待 CLI 启动命令执行...
CLI 启动后:
text
✅ 异步任务已启动执行!
任务ID: xxx
请等待完成,轮询子代理会通知结果。
为什么重要
用途:实时查询异步任务的状态、进度、统计数据。
bash
dm-cli task info --thread-id <thread_id> --task-id <task_id> --json
返回字段:
字段类型说明task_idstring任务 IDtask_namestring任务名称statestring任务状态(running/success/failed/interrupted)totalint总数据量completedint已完成数量failedint失败数量download_totalint已下载数量estimate_timestring预估耗时(秒)estimate_pointsstring预估积分范围(如 "245~490")file_pathstring结果文件 URL
⚠️ 已知 CLI Bug:当 estimate_time 字段返回数字(如 300)时,CLI 的 Go 结构体期望 string,会报 json: cannot unmarshal number into Go struct field 解析错误。遇到此错误时任务本身正常运行,可改用 thread result 查看 thread 级别状态,或直接用 task lifecycle --action start 确认任务状态。
使用场景:
示例输出:
json
{
"ok": true,
"data": {
"tasks": [{
"task_id": "xxx",
"task_name": "产品评价情感分析",
"state": "running",
"total": 500,
"completed": 89,
"failed": 0,
"estimate_time": "120",
"estimate_points": "245~490"
}]
}
}
用途:管理异步任务的启动、中断、恢复、取消。
bash
dm-cli task lifecycle --thread-id <thread_id> --task-id <task_id> --action <action> --json
action 参数:
action说明适用状态start启动任务PENDINGinterrupt中断任务runningresume恢复任务interruptedcancel取消任务running/interrupted
状态转换:
text
PENDING → start → running
running → interrupt → interrupted
interrupted → resume → running
running → cancel → rejected
interrupted → cancel → rejected
使用场景:
start:启动已提交的异步任务(替代追问消息)interrupt:临时暂停任务(可恢复)resume:恢复被中断的任务cancel:彻底取消任务(不可恢复)⚠️ 注意: task files 仅适用于 批量下载/采集类任务,标注任务不支持。
标注任务的文件获取方式:
bash
dm-cli thread file-list --thread-id <thread_id> --json
text
1. 用户发送任务
↓
2. dm-cli thread start --message "用户原话" --json
↓
3. 获取 thread_id
↓
4. 启动轮询子代理(sessions_spawn)
↓
5. 告知用户 "DM 任务已提交..."
↓
6. 主代理保持响应,等待子代理通知
↓
7. 子代理检测到状态变化 → sessions_send 通知主会话
↓
8. 主代理收到通知,处理并返回结果
原因:
message 工具 直接通知用户步骤 1:提交任务
bash
result=$(dm-cli thread start --message "用户原话" --json)
thread_id=$(echo "$result" | jq -r '.data.thread_id')
if [ -z "$thread_id" ] || [ "$thread_id" = "null" ]; then
echo "❌ 任务提交失败"
return
fi
步骤 2:启动轮询子代理(关键!)
使用 sessions_spawn 启动子代理,子代理会 直接向用户发送结果:
json
{
"action": "sessions_spawn",
"runtime": "subagent",
"mode": "run",
"label": "dm-poll-${thread_id}",
"timeoutSeconds": 3600,
"task": "你是 DM 轮询子代理。\n\n## 任务\n轮询 DM 任务状态,完成后**直接通知用户**。\n\n## 参数\n- thread_id: \"${thread_id}\"\n\n## 轮询流程\n\n1. 调用 `dm-cli thread result --thread-id ${thread_id} --json` 获取状态\n2. 如果 state 是 running,等待后继续轮询(间隔 5/10/20/40/60 秒递增)\n3. 如果 state 变化:\n - **使用 message 工具通知用户**:`{\"action\": \"send\", \"message\": \"结果内容\"}`\n - 如果是终止状态(completed/ask_human/failed),退出\n\n## 状态处理\n\n| 状态 | 动作 |\n|------|------|\n| running | 继续轮询 |\n| async_tag_task | 通知用户去 GUI 确认(附具体链接 https://deepminer.com.cn/agents/${thread_id}),继续轮询 |\n| ask_human | 通知用户问题,退出 |\n| completed | 通知用户结果(含文件链接),退出 |\n| failed | 通知用户错误,退出 |\n\n## 通知格式示例\n\n**完成时**:\n```\n✅ DM 任务完成\n\nthread_id: xxx\n\n结果:...\n\n📄 文件:[链接]\n```\n\n**需要用户输入时**:\n```\n⏸️ DM 需要您的回复\n\n[问题内容]\n\n请回复后继续。\n```\n\n**重要**:必须使用 message 工具直接发送给用户,不要只是输出到 stdout!\n\n开始执行轮询。"
}
步骤 3:告知用户任务已提交
text
⏳ DM 任务已提交,正在后台处理中...
步骤 4:主代理保持响应
步骤 5:用户可随时中断
text
用户: "停止"
主代理: subagents kill dm-poll-${thread_id}
主代理 spawn 子代理时,直接使用此模板作为 task 参数:
text
你是 DM 轮询子代理。
## ⚠️ 核心规则
1. **必须遍历所有 last_messages**,不能只看第一条
2. **必须原样呈现**,禁止总结、省略、改写 DM 的回复
3. **必须提取所有文件链接**,不能遗漏任何 attachment
## 参数
- thread_id: ${thread_id}
## 轮询流程
1. 使用 `exec` 工具调用 `dm-cli thread result --thread-id ${thread_id} --json`
2. 解析 `.data.state` 字段
3. 根据 state 处理:
| state | 动作 |
|-------|------|
| running | 等待 5/10/20/40/60 秒后继续轮询 |
| async_tag_task | 通知用户去 GUI 确认(链接:https://deepminer.com.cn/agents/${thread_id}),继续轮询 |
| ask_human | 输出问题,停止 |
| completed | 输出结果,停止 |
| failed | 输出错误,停止 |
## ⚠️ 通知方式
**直接输出以下格式的文本**(会自动推送给主代理,主代理转发给用户):
✅ DM 任务完成
thread_id: ${thread_id}
结果:
[遍历 last_messages,原样输出每条 assistant 消息的 content]
文件:
[遍历 last_messages,提取所有 tool 消息的 artifact.attachments,列出所有文件链接]
text
## ⚠️ 关键提醒
- **不要调用 message 或 sessions_send 工具**
- **直接输出文本**,系统会自动推送
- 停止后你的输出会通过 subagent_announce 发送给主代理
- 主代理收到后会转发给用户
开始执行轮询任务。
json
{
"action": "sessions_spawn",
"runtime": "subagent",
"mode": "run",
"label": "dm-poll-${thread_id}",
"timeoutSeconds": 3600,
"task": "<上面的模板内容,替换 ${thread_id} 为实际值>"
}
当用户发送"停止"、"中止"指令时:
bash
subagents kill --target dm-poll-${thread_id}
状态类型子代理行为主代理动作running执行中继续轮询等待async_tag_task待 GUI 确认通知用户去 GUI 确认(附链接 https://deepminer.com.cn/agents/${thread_id}),继续轮询告知用户去 GUI 确认,附具体会话链接ask_human等待输入输出问题,停止返回问题,等待追问completed成功输出结果,停止提取结果,返回用户failed失败输出错误,停止返回错误信息
DM 的 打标注任务 会进入 async_tag_task 状态,此时需要用户在 GUI 上确认后才能继续执行。这带来一个设计难题:
方案结果遇到 async_tag_task 立即停止并通知✅ 用户知道去 GUI 确认
❌ 但没人继续跟踪任务完成遇到 async_tag_task 继续静默轮询✅ 能跟踪到最终完成
❌ 用户不知道要去 GUI 确认
核心原则: 子代理 只输出、不停留,主代理负责决策和重启轮询。
text
流程:
1. 启动子代理轮询
2. 子代理检测到 `async_tag_task`
3. 子代理输出通知 → 停止(触发 subagent_announce)
4. 主代理收到通知,告知用户去 GUI 确认
5. 【关键】主代理提示:"去 GUI 确认后,请发送 '继续'"
6. 用户去 GUI 确认,回来后发送 "继续"
7. 主代理启动新子代理,继续轮询到 completed
text
你是 DM 轮询子代理。
## 任务
轮询 DM 任务状态,**关键状态变化后立即停止并输出**。
## 参数
- thread_id: ${thread_id}
## 状态处理规则
| state | 动作 |
|-------|------|
| running | sleep 15秒,继续轮询 |
| async_tag_task | **输出通知 + 停止**(等待用户 GUI 操作) |
| ask_human | 输出问题 + 停止 |
| completed | 输出完整结果(含文件链接)+ 停止 |
| failed | 输出错误 + 停止 |
## ⚠️ 关键要求
- 遍历所有 last_messages,原样呈现
- 提取所有文件附件链接
- **非终止状态(running)才继续轮询**
- 遇到 async_tag_task/ask_human/completed/failed **立即停止**
开始执行轮询。
typescript
// 1. 首次启动轮询
sessions_spawn({
runtime: "subagent",
mode: "run",
label: "dm-poll-${thread_id}",
timeoutSeconds: 600,
task: "<上面的子代理模板>"
})
// 2. 收到 subagent_announce 后判断
if (result.contains("async_tag_task")) {
// 通知用户去 GUI 确认
reply("⏸️ 需要你去 GUI 确认...\n\n确认后请发送 '继续'")
} else if (result.contains("completed")) {
// 任务完成,输出结果
reply("✅ 任务完成...")
}
// 3. 用户发送 "继续" 后,启动新轮询
if (user_message == "继续") {
sessions_spawn({
runtime: "subagent",
mode: "run",
label: "dm-poll-${thread_id}-2",
timeoutSeconds: 600,
task: "<同上>"
})
}
dm-poll-xxx-2、 dm-poll-xxx-3,避免冲突问题解决方案主代理阻塞使用 sessions_spawn 子代理轮询无法中断subagents kill 终止子代理通知延迟/丢失子代理直接输出文本,auto-announce 推送无限重试timeoutSeconds 限制,或用户手动终止async_tag_task 无法通知****分层设计:停止→通知→重启轮询
当没有已知命令能完成用户的需求时,优先使用 help 找命令。
⚠️ message 并不能操作 agent 状态! 发消息只是让 AI 对话,不会真正改变任务状态、停止任务、或控制异步任务。
正确做法:
bash
# 1. 先看顶层帮助
dm-cli --help
# 2. 看子命令帮助
dm-cli thread --help
dm-cli task --help
dm-cli agent --help
# 3. 看具体命令帮助
dm-cli thread start --help
dm-cli task lifecycle --help
# 4. 输出完整 Schema(供 AI 系统解析)
dm-cli schema --pretty
dm-cli schema 命令(⚠️ 重要!)
bash
# 压缩输出(默认)
dm-cli schema
# 格式化输出(人类可读)
dm-cli schema --pretty
为什么重要:
参数说明--json以 JSON 格式输出(脚本调用必加)--help / -h显示帮助
命令说明dm-cli config init --endpoint <url> --accesskey <key> [--poll-timeout <min>]初始化配置(默认 endpoint: https://deepminer.com.cn,默认 poll-timeout: 60 分钟)dm-cli config show [--json]显示当前配置
命令说明dm-cli auth status [--json]显示鉴权状态
命令说明dm-cli thread start --message <text> [--thread-id <id>] [--file <path> ...] [--agent-mode auto|cooperation] [--force] [--json]发起/继续 AI 会话dm-cli thread result --thread-id <id> [--json]获取会话结果和状态dm-cli thread stop --thread-id <id> [--json]停止正在运行的 Agentdm-cli thread list [--name <keyword>] [--json]获取项目会话列表,支持按名称模糊搜索dm-cli thread file-list --thread-id <id> [--json]获取会话的文件列表(文件空间)
thread start 完整参数:
参数类型必填说明--messagestring✅发送给 AI 的文本消息--thread-idstring已有会话 ID,用于追问--filestring[]本地文件路径(可多次指定)--agent-modeauto/cooperationAgent 运行模式,默认 auto--forceboolean会话运行中强制发送新问题
文件大小限制:
命令说明dm-cli task info --thread-id <id> [--task-id <id>] [--json]查询异步任务信息(不传 task-id 返回会话下所有任务)dm-cli task lifecycle --thread-id <id> --task-id <id> --action start|interrupt|resume|cancel [--json]管理异步任务生命周期dm-cli task files --thread-id <id> --task-id <id> [--page <n>] [--size <n>] [--json]列出任务产物文件(支持分页,默认 page=1, size=10)
命令说明dm-cli schema [--pretty]输出完整 CLI Schema(供 AI 系统动态发现命令)dm-cli version显示版本号
Exit Code处理方式0成功2校验错误,检查参数3认证失败,重新配置 Access Key4网络错误,检查 endpoint5内部错误,检查文件路径/权限6权限不足