@metagptx/deepflow-suite-cli 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,13 +2,13 @@
2
2
  "schemaVersion": 1,
3
3
  "distribution": "deepflow-suite",
4
4
  "package": "@metagptx/deepflow-suite-cli",
5
- "version": "0.2.3",
5
+ "version": "0.2.5",
6
6
  "platform": "any",
7
7
  "arch": "any",
8
8
  "cli": {
9
9
  "name": "deepflow-suite",
10
10
  "package": "@metagptx/deepflow-suite-cli",
11
- "version": "0.2.3",
11
+ "version": "0.2.5",
12
12
  "command": "deepflow-suite"
13
13
  },
14
14
  "skills": [
@@ -19,7 +19,7 @@
19
19
  {
20
20
  "path": "manifest.yaml",
21
21
  "size": 362,
22
- "sha256": "dc6578c11a62a29fee194a268ede90d1d8659b0f731787ca3fdab557bc39d51f"
22
+ "sha256": "afd23f0ad1d0c1967274391000eb8d4ad92a14071b8ef8ac9b101c24b5c325fe"
23
23
  },
24
24
  {
25
25
  "path": "SKILL.md",
@@ -39,8 +39,8 @@
39
39
  },
40
40
  {
41
41
  "path": "SKILL.md",
42
- "size": 2758,
43
- "sha256": "c86ee01f8b130669f87efc223ffdeff96841a89037c39738eaf8730bdd58091b"
42
+ "size": 3502,
43
+ "sha256": "9a0e81ec5df799b1fa7fb0ed3f7ec1ac97228c34baa8e6b83ea857e30e8aff85"
44
44
  }
45
45
  ]
46
46
  },
@@ -80,8 +80,8 @@
80
80
  },
81
81
  {
82
82
  "path": "references/fact-types.md",
83
- "size": 3353,
84
- "sha256": "37c13c13822734744d9f4a73710e1206009eeb037102620ccdb77af78e1dcb39"
83
+ "size": 3834,
84
+ "sha256": "66382b303f33944939be564722081549a45f1fbf737aa5dfc15d92274823d469"
85
85
  },
86
86
  {
87
87
  "path": "skill_test.go",
@@ -90,8 +90,8 @@
90
90
  },
91
91
  {
92
92
  "path": "SKILL.md",
93
- "size": 12155,
94
- "sha256": "aec1bb832519f6503b9e17cbe34bf4ff39bac451f57912d5cd42de1a3e2e77e2"
93
+ "size": 15347,
94
+ "sha256": "2a45f890bffab946701ab38c07d7ccb91056d881b77bccffcf3a7c03ce35a8b8"
95
95
  }
96
96
  ]
97
97
  },
@@ -138,8 +138,8 @@
138
138
  "files": [
139
139
  {
140
140
  "path": "SKILL.md",
141
- "size": 10128,
142
- "sha256": "baa0cac18c1683a0b2e52ab301854d8dc9e907ccd3ae451b2357b1780c2e3f33"
141
+ "size": 12164,
142
+ "sha256": "16ce0068a76a210231cb92913d12a39c2c94a779216e84125639febfcc0ce73f"
143
143
  }
144
144
  ]
145
145
  },
@@ -1,5 +1,5 @@
1
1
  id: deepflow-suite
2
- version: 0.2.3
2
+ version: 0.2.5
3
3
  kind: composite-skill
4
4
  requires:
5
5
  skills:
@@ -23,7 +23,9 @@ multica repo checkout <URL>
23
23
  其余的 `multica` 子命令敲下去都会被明确拒绝,stderr 上会告诉你这里没有这个东西、
24
24
  以及改做什么。那些拒绝信息是给你看的,照着做就行,**不要换个写法重试**。
25
25
 
26
- 你自己的能力在 `df-agentrt` 上,已经在 PATH 里,不需要定位路径。
26
+ 你自己的能力在 `df-agentrt` 上。Runtime 镜像通过标准 PATH 提供 `df-task`、`df-agentctrl`、`df-agentrt` 和 `multica` shim,普通 shell 与登录 shell 均应可直接调用。命令缺失或 `--help` 失败属于执行环境异常:报告并结束,不要在 Run 中安装、编译 CLI 或猜绝对路径反复尝试。
27
+
28
+ Skill 内容通过 provider 的原生目录交付,以当前会话的 Skill 目录清单为准。清单中的 `r0` 等是根目录别名,打开前先展开,不能拼成 `skills/r0/...`。Codex 的 Runtime Skills 在 `$CODEX_HOME/skills/<slug>/SKILL.md`;Claude 在任务工作目录的 `.claude/skills/<slug>/SKILL.md`。支持文件相对该 Skill 目录读取。`$DEEPFLOW_WORKDIR` 表示任务工作目录,不是通用 Skill 根目录。
27
29
 
28
30
  ## 目标环境门禁与地址
29
31
 
@@ -75,17 +77,17 @@ AGENTRT_ADDR=https://deepflowagentruntime.dev.deepwisdomai.com agentrt session l
75
77
  - `repo add` / `repo checkout` 检出的仓库,落在**你当前工作目录的同级**,不在里面。
76
78
  - 目录名取自 URL 的最后一段,**不一定等于应用名**。不要猜,用命令打印出来的绝对路径。
77
79
 
78
- ## release 之后工作目录会被回收
80
+ ## release 之后工作目录的生命周期
79
81
 
80
- 会话 release 之后:消息流仍然可读,**工作目录会被删掉**。
82
+ 当前 Runtime 部署中,会话 release 之后消息流仍然可读,且 Worker workspace 会继续保留;
83
+ release 只停止新轮次。归档、对象存储和本地清理属于后续生命周期能力,不能假设已经完成。
81
84
 
82
- 所以**不要把唯一的产出留在磁盘上**。重要的结论、生成的内容、分析结果,都要进消息流。
85
+ 所以**不要把唯一的交付结论留在磁盘上**。重要的结论、生成的内容、分析结果,都要进消息流。
83
86
  磁盘是工作区,不是交付区。
84
87
 
85
88
  ## 取消是协作式的
86
89
 
87
- 被取消时你不会被当场杀掉:状态先变成 `cancelled`,你会收到停止的请求,
88
- 然后有时间收尾。收到取消请求就**尽快收尾并把已有的结论说出来**,
90
+ 取消请求被接受不等于执行已经停止:先出现 `cancel_requested`,终态由 Runtime 后续确认。你收到停止请求时应尽快收尾。收到取消请求就**尽快收尾并把已有的结论说出来**,
89
91
  不要假装无事发生继续跑,也不要因为被取消就什么都不留下。
90
92
 
91
93
  ---
@@ -96,7 +98,7 @@ AGENTRT_ADDR=https://deepflowagentruntime.dev.deepwisdomai.com agentrt session l
96
98
  本会话(不需要会话 id,它自己知道是哪个)
97
99
  df-agentrt session info 你是谁:provider、model、工作目录、仓库,
98
100
  以及上一轮的对话历史有没有续上
99
- df-agentrt session turns 这个会话到目前为止的每一轮
101
+ df-agentrt session turns [--json] 这个会话到目前为止的每一轮
100
102
  df-agentrt events [--after N] 消息流,一行一条
101
103
  df-agentrt repo list 本会话可以检出哪些仓库
102
104
  df-agentrt repo search <应用名> 按应用名找仓库
@@ -105,15 +107,22 @@ AGENTRT_ADDR=https://deepflowagentruntime.dev.deepwisdomai.com agentrt session l
105
107
 
106
108
  别的会话(必须显式给会话 id)
107
109
  df-agentrt session ls 这个 runtime 上的会话
108
- df-agentrt session get <会话id> 某个会话的完整信息
110
+ df-agentrt session get <会话id> [--json] 某个会话的完整信息
111
+ df-agentrt session turns --session <会话id> [--json] 指定会话的轮次状态
112
+ df-agentrt events --session <会话id> [--after N] [--limit N] [--raw]
113
+ 指定会话的消息流
109
114
  df-agentrt session create ... 新建会话 💰
110
115
  df-agentrt msg send <会话id> <文本> 给别的会话排一轮 💰
111
116
 
112
117
  运行时
113
- df-agentrt ops runtimes 执行引擎注册了哪些、还活着哪些
118
+ df-agentrt ops runtimes [--json] 执行引擎注册了哪些、还活着哪些
114
119
  df-agentrt ops orphans 记录和现实哪里对不上(只读)
115
120
  ```
116
121
 
122
+ 只读查询省略 `--session` 时,`session turns` 和 `events` 仍查询当前会话。查询其他会话必须显式给 Runtime Session ID;业务 Run ID 不是 Session ID。只在 `session get`、`session turns`、`ops runtimes` 使用 `--json`;`events --raw` 是带事件前缀的原始 payload 展示,不是纯 JSON。
123
+
124
+ 需要按已授权的指令取消另一轮时,先从 Task 的 `invocation_accepted` 事实取得准确的 Runtime Session/Invocation 映射,用 `session turns --session <session-id> --json` 核对,再执行 `df-agentrt msg cancel <invocation-id>`。不带参数会取消**当前轮**;不要把 Run ID 或 Session ID 传给 cancel。接受取消后,核对同一 Invocation 已到终态,再写 `run_terminated`;消息流安静或命令返回成功都不足以证明停止。
125
+
117
126
  ## 业务 metadata 与软范围查询
118
127
 
119
128
  Runtime Session 可以携带业务方自定义的 JSON metadata。基础服务只约定顶层的 source、
@@ -141,7 +150,7 @@ Runtime 也不会从登录身份或当前会话自动推断业务范围。
141
150
 
142
151
  当前 session info、session get 和 session ls 的人类可读输出不会打印 metadata 原文,
143
152
  不要把输出中没有 metadata 理解成 Session 没有 metadata。需要核对原值时读取 Runtime API 的
144
- JSON 响应;CLI 过滤仍然可以正常使用。
153
+ JSON 响应(`df-agentrt session get <session-id> --json`);CLI 过滤仍然可以正常使用。
145
154
 
146
155
  💰 这两条会**真的跑起来一个 agent**,花的是真钱。而且新建的会话**不会自己结束**——
147
156
  它会一直占着一个工作目录,直到有人显式 release 它。确认你真的需要另一个会话再用,
@@ -169,7 +178,8 @@ key 时每次新建。同 key 只保留首次成功写入的配置,released
169
178
  ### 有三件事不归你做
170
179
 
171
180
  `session release`、`session rm`、`ops orphans --fix` **不要用**。它们都是替别人做决定:
172
- release 会停止会话接收新轮次(第一期不会归档 Worker 工作目录),删会话会抹掉永久可见的消息流,判死滞留轮次动的是别的会话。
181
+ release 会停止会话接收新轮次并改变生命周期状态(当前不会归档或清理 Worker 工作目录),
182
+ 删会话会抹掉永久可见的消息流,判死滞留轮次动的是别的会话。
173
183
  二进制不会拦你——它会照做,所以这条只能靠你守住。
174
184
 
175
185
  发现某个会话像是卡住了、或者某个工作目录该回收了,**在回复里说出来**,
@@ -52,12 +52,9 @@ df-task --base-url https://deepflowtask.dev.deepwisdomai.com facts "$DF_TASK_ID"
52
52
  **在 Run 里一律加 `--json`。** 不加 `--json` 的输出是给人看的排版,字段随时会调整。
53
53
 
54
54
  ```bash
55
- # 读本 Task 的全部事实
56
- df-task facts "$DF_TASK_ID" --json
57
-
58
- # 只读某几类,或从某个序号往后读
55
+ # 按本轮需要选择事实类型(选择标准见「读日志」)
59
56
  df-task facts "$DF_TASK_ID" --types user_message,artifact_published --json
60
- df-task facts "$DF_TASK_ID" --after 128 --json
57
+ df-task facts "$DF_TASK_ID" --types user_message,artifact_published --after 128 --limit 100 --json
61
58
 
62
59
  # 追加一条事实:payload 写成 JSON 文件再传
63
60
  # 注意 heredoc 的标记不加引号,加了引号 $DF_RUN_ID 就不会展开
@@ -115,16 +112,36 @@ df-task stream \
115
112
  metadata 只影响读请求的范围。`append`、`dispatch`、`wait`、`handoff` 和 `title` 仍按明确的
116
113
  Task ID 操作,不支持 metadata 过滤参数;事实服务不会根据 metadata 做鉴权。
117
114
 
118
- 命令不存在时,本项目源码可用的话在 `deepflow-task/` 下运行 `make install-cli`,它把 `df-task` 装到 `$HOME/.local/bin`。**注意不要把 runtime 的地址填成 Task 服务的地址** —— `df-agentrt` 和 `df-task` 是两个服务、两个端口、两套授权。
115
+ 托管 Run 中 `df-task` 由 Runtime 镜像提供。命令缺失或 `--help` 无法执行时,报告执行环境异常并结束;不要在 Run 中安装、编译 CLI 或猜测绝对路径来继续。非托管的本地开发可按项目 README 安装 CLI。**注意不要把 runtime 的地址填成 Task 服务的地址** —— `df-agentrt` 和 `df-task` 是两个服务、两个端口、两套授权。
119
116
 
120
117
  ## 读日志
121
118
 
122
- 1. 先 `df-task facts "$DF_TASK_ID" --json` 通读一遍,搞清这件工作已经发生过什么
123
- 2. 关心产物就加 `--types artifact_published`;关心人说了什么就加 `--types user_message`
124
- 3. 产物事实里存的是**引用坐标,不是内容**。要看 diff、spec、MR 的正文,拿着 `ref` 自己去外部系统取
125
- 4. 要分页往后读就用上一页返回的 `next_after_seq` 当下一次的 `--after`
119
+ 先确定本轮要作出的判断,再按需选择事实;不要求每轮先通读全部日志。当前描述与版本用上文的 `get` 读取,事实用于补足决策依据。
120
+
121
+ | 要判断什么 | 优先读取的类型 |
122
+ | --- | --- |
123
+ | 用户新增的要求、补充信息或外部结果 | `user_message,external_result`;同时检查消息的 `wake_policy` |
124
+ | 是否已经派发、Run 对应哪个 Runtime Session/Invocation、是否仍在执行 | `dispatch_intent,invocation_started,invocation_accepted,invocation_ended,run_terminated,attempt_failed` |
125
+ | 执行结果、待办与阻塞 | `summary,run_outcome,help_requested`;核对交付物时再读 `artifact_published` |
126
+ | 已有等待、人工接手或裁决是否影响本轮 | `waiting_reason,handoff_to_human,adjudication`;涉及 Task 生命周期时再读 `task_lifecycle` |
127
+
128
+ 这些是选择标准,不是每轮必须执行的四组查询。调度 Run 在再次派发前要查清相关派发与执行事实,避免重复工作;任务 Run 按交给自己的目标和引用补充上下文,无需重建整个调度历史。已有摘要不能代替被引用的关键事实;证据不足、存在矛盾或无法定位关联时,扩大类型和时间范围,必要时通读日志。同一轮已读到且仍适用的事实可以复用。
129
+
130
+ ```bash
131
+ # 示例:核对是否已派发,以及对应的执行状态
132
+ df-task facts "$DF_TASK_ID" \
133
+ --types dispatch_intent,invocation_started,invocation_accepted,invocation_ended,run_terminated,attempt_failed \
134
+ --limit 100 --json
135
+ ```
136
+
137
+ 分页与完整性:
126
138
 
127
- 序号有空洞,且落库顺序不保证与序号顺序一致。一次读不完就接着读,不要假设「序号连续就是读全了」。
139
+ - 响应按 `seq` 升序,`--limit` 默认 200、最大 1000,**不是取最新 N 条**。`--after` 排除给定序号;下一页用响应的 `next_after_seq`,保持同一 Task、类型和 metadata 过滤条件。
140
+ - 首次读取某组类型时,没有已确认的读取进度就从头读。更换类型不能复用另一组的游标;Driver 的输入水位也不是 Agent 已读游标,不能直接拿它作 `--after` 跳过本轮触发事实。
141
+ - `next_after_seq` 始终返回,即使空页也会保留输入游标;它不是“还有下一页”的标志。非空页可用它继续读取,空页停止;要断言“没有派发/结果”等不存在结论,必须读完相关范围。分页未完、类型未覆盖或只读摘要时,不能把没看到当成不存在。
142
+ - 序号有空洞,落库顺序也不保证与序号顺序一致;游标表示本次查询进度,不代表之前的序号永远不会再出现。关键判断证据矛盾时回查相关范围,不按连续序号推断读全。
143
+ - API 不支持按 `run_id` 过滤、精确查单个 `seq` 或倒序取尾页。返回中按关联字段核对 Run/引用;不要尝试不存在的参数。
144
+ - `artifact_published` 只有引用坐标。需要 diff、spec、MR 正文时,用 `ref` 到对应系统读取。
128
145
 
129
146
  ## 任务 Run 可以写什么
130
147
 
@@ -145,15 +162,17 @@ Task ID 操作,不支持 metadata 过滤参数;事实服务不会根据 meta
145
162
 
146
163
  | 命令 | 落成哪条事实 | 什么时候写 |
147
164
  | --- | --- | --- |
148
- | `df-task dispatch <task-id> --agent <name> --instruction <text>` | `dispatch_intent`(`mode` 为 `new_run`) | 把一块工作派给某个智能体,开一个新 Run |
149
- | `df-task dispatch <task-id> --agent <name> --instruction <text> --run <run-id>` | `dispatch_intent`(`mode` 为 `message`) | 往一个还活着的 Run 投一条消息 |
150
- | `df-task wait <task-id> --on <what> --reason <text>` | `waiting_reason` | 该派的都派了,在等人回话或等一条外部结果 |
165
+ | `df-task dispatch <task-id> --agent <name> --instruction <text>` | `dispatch_intent`(`mode` 为 `new_run`,不带 `target_run_id`) | 把一块工作派给某个智能体,Driver 会派生一个新逻辑 Run |
166
+ | `df-task dispatch <task-id> --agent <name> --instruction <text> --run <run-id>` | `dispatch_intent`(`mode` 为 `message`,带 `target_run_id`) | 往一个已有逻辑 Run 投一条消息 |
167
+ | `df-task wait <task-id> --on <what> --reason <text> [--waiting-run <run-id>]` | `waiting_reason` | 该派的都派了,在等人回话或等一条外部结果 |
151
168
  | `df-task handoff <task-id> --ask <text>` | `handoff_to_human` | 把球交给人。既用于「都做完了请验收」,也用于「这一步我做不了请你做」 |
152
169
  | `df-task append <task-id> --type adjudication --file p.json` | `adjudication` | 对某条事实下裁决,`subject` 是那条事实的序号 |
153
170
  | `df-task append <task-id> --type run_terminated --file p.json` | `run_terminated` | **已经用 `df-agentrt` 停完 Run 之后**,记录这个既成事实 |
154
171
 
155
172
  前四行是语法糖,落库的事实类型见中间那一列 —— 读日志时你看到的是 `dispatch_intent`,不是 `dispatch`。各列字段清单见 `references/fact-types.md`。
156
173
 
174
+ **先看人话的 `wake_policy`。** 带 `wake_policy: passive` 的人话是同事之间的讨论,不是给你的指令:可以用来理解上下文,但不能因为它去 `dispatch`。passive 消息不算本轮要处理的请求;处理完其他事实后如果没有要做的事,就写 `wait`,说明正在等待有人点名。
175
+
157
176
  **每一轮至少写一条。** 一轮调度什么都不写,这个 Task 就会静默停住 —— 那是最坏的失效模式。无事可做不是理由:无事可做就写 `wait` 或 `handoff`。
158
177
 
159
178
  `dispatch` 写完不等于 Run 起来了。**你写完就该结束**,真正拉起进程的是推进器。
@@ -175,3 +194,5 @@ Task ID 操作,不支持 metadata 过滤参数;事实服务不会根据 meta
175
194
  追加成功返回那条事实,含它的 `seq`。`--idempotency-key` 重复提交同一个键时返回**已存在的那条事实**,HTTP 状态是 `200` 而不是 `201` —— 这不是错误,重试是安全的。
176
195
 
177
196
  各类事实的字段清单见 `references/fact-types.md`,可直接抄改的 payload 样例在 `assets/payload-examples/`。
197
+
198
+ 等待已发起的工作 Run 时,使用 `--waiting-run` 填写 `invocation_started.payload.run_id` 的精确值;不要使用 dispatch 的 `target_run_id`,不要附加角色或 Session 描述。`--on` 仍是自由描述,`--reason` 保留调度依据。需要人采取行动时使用 `handoff`。此关联不改变 Driver 推进语义。
@@ -6,9 +6,11 @@
6
6
 
7
7
  | 类型 | 谁写 | 必填 | 可选 |
8
8
  | --- | --- | --- | --- |
9
- | `user_message` | 人 | `text` | —— |
9
+ | `user_message` | 人 | `text` | `wake_policy`、`agent_ids` |
10
10
  | `external_result` | 外部系统 | `source`、`ref`、`result` | —— |
11
11
 
12
+ `wake_policy` 由产品端写入,缺失时按 `default` 处理。`passive` 表示多人对话里人和人之间的讨论,它**不触发**调度,被别的事件唤醒时也只能当作上下文,不能单独据此派活。`agent_ids` 只是人提到的 Agent,作为提示;派给谁仍由调度根据全局事实决定。
13
+
12
14
  对求助的回答、对产物的意见、对裁决的确认,全都是 `user_message`,没有专门的类型。
13
15
 
14
16
  ## 人工任务管理(不触发调度)
@@ -28,8 +30,8 @@
28
30
 
29
31
  | 类型 | 必填 | 可选 | 说明 |
30
32
  | --- | --- | --- | --- |
31
- | `dispatch_intent` | `target_run_id`、`agent`、`instruction`、`mode` | —— | `mode` 是 `new_run` 或 `message`。用 `df-task dispatch` 更省事,它会替你填这四个字段 |
32
- | `waiting_reason` | `waiting_on`、`reason` | —— | 给人和给下一轮调度的上下文,**不是推进器的门** |
33
+ | `dispatch_intent` | `agent`、`instruction`、`mode`;`mode=message` 时还必须有 `target_run_id` | —— | `new_run` 不带 `target_run_id`,由 Driver 根据 `task_id + intent_seq` 派生逻辑 Run;`message` 只能指向已有逻辑 Run。用 `df-task dispatch` 更省事 |
34
+ | `waiting_reason` | `waiting_on`、`reason` | `waiting_run_id`(实际执行 ID) | 给人和给下一轮调度的上下文,**不是推进器的门** |
33
35
  | `handoff_to_human` | `ask` | `assignee` | 交球和派活是同一条事实,区别只在 `ask` 的内容 |
34
36
  | `adjudication` | `subject`、`verdict` | `reason` | `subject` 是被裁决那条事实的**序号**(数字,不是字符串) |
35
37
  | `run_terminated` | `run_id`、`confirmed_status` | —— | 已经停完并确认之后记录的既成事实 |
@@ -49,8 +49,18 @@ df-workbench task send <task-id> --message '补充检查 Safari 浏览器' --jso
49
49
  ```bash
50
50
  df-workbench task get <task-id> --json
51
51
  df-workbench task facts <task-id> --json
52
+ df-workbench task list [--scope <mine|workspace>] [--limit <n>] --json
52
53
  ```
53
54
 
55
+ `task list` 默认读取当前用户可以参与的任务;需要发现工作区内的其他任务时使用
56
+ `--scope workspace`。未参与的任务只提供安全概览,可能带有 `access: "overview"` 和
57
+ `overviewState`,不会暴露目标正文、讨论、成员或成果内容。
58
+
59
+ 只有任务所有者或已获批准的参与者才能读取完整事实、发送消息和读取成果。对未获准
60
+ 参与的任务,`task facts` 或 `task send` 会返回 `task_participation_required`(HTTP 403)。
61
+ 此时应引导用户在 Workbench 界面申请加入并等待负责人批准,而不是重试或把它当成
62
+ Token、工作区或服务地址配置错误。
63
+
54
64
  创建和发送必须使用稳定的 `--idempotency-key`。如果请求超时或返回未知结果,不要换一个 key 盲目重试;沿用原 key 核对结果。
55
65
 
56
66
  ## 用户反馈边界
package/manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "distribution": "deepflow-suite",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "skills": [
5
5
  {
6
6
  "name": "deepflow-suite",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metagptx/deepflow-suite-cli",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Agent-friendly installer and distribution CLI for the DeepFlow suite.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -26,11 +26,11 @@
26
26
  "access": "public"
27
27
  },
28
28
  "optionalDependencies": {
29
- "@metagptx/deepflow-suite-cli-darwin-arm64": "0.2.3",
30
- "@metagptx/deepflow-suite-cli-darwin-x64": "0.2.3",
31
- "@metagptx/deepflow-suite-cli-linux-arm64": "0.2.3",
32
- "@metagptx/deepflow-suite-cli-linux-x64": "0.2.3",
33
- "@metagptx/deepflow-suite-cli-win32-x64": "0.2.3"
29
+ "@metagptx/deepflow-suite-cli-darwin-arm64": "0.2.5",
30
+ "@metagptx/deepflow-suite-cli-darwin-x64": "0.2.5",
31
+ "@metagptx/deepflow-suite-cli-linux-arm64": "0.2.5",
32
+ "@metagptx/deepflow-suite-cli-linux-x64": "0.2.5",
33
+ "@metagptx/deepflow-suite-cli-win32-x64": "0.2.5"
34
34
  },
35
35
  "engines": {
36
36
  "node": ">=22.13.0"
@@ -43,6 +43,7 @@ export function parseArgs(argv, env = process.env) {
43
43
  title: "",
44
44
  after: "",
45
45
  limit: "",
46
+ scope: "mine",
46
47
  };
47
48
  const positionals = [];
48
49
  for (let index = 0; index < argv.length; index += 1) {
@@ -67,6 +68,7 @@ export function parseArgs(argv, env = process.env) {
67
68
  "--title",
68
69
  "--after",
69
70
  "--limit",
71
+ "--scope",
70
72
  ].includes(name)
71
73
  ) {
72
74
  const parsed =
@@ -79,6 +81,7 @@ export function parseArgs(argv, env = process.env) {
79
81
  if (name === "--title") options.title = parsed;
80
82
  if (name === "--after") options.after = parsed;
81
83
  if (name === "--limit") options.limit = parsed;
84
+ if (name === "--scope") options.scope = parsed;
82
85
  continue;
83
86
  }
84
87
  if (argument.startsWith("--"))
@@ -264,11 +267,25 @@ function taskSummary(value) {
264
267
  `Task: ${task.id || "未知"}`,
265
268
  task.title ? `标题: ${task.title}` : "",
266
269
  task.workspaceId ? `工作区: ${task.workspaceId}` : "",
270
+ task.access === "overview"
271
+ ? "访问: 仅概览(请先申请加入并等待批准后读取完整内容)"
272
+ : "",
273
+ task.overviewState?.status ? `状态: ${task.overviewState.status}` : "",
267
274
  ]
268
275
  .filter(Boolean)
269
276
  .join("\n");
270
277
  }
271
278
 
279
+ export function requestFailureHint(error) {
280
+ if (error?.code === "task_participation_required")
281
+ return "当前任务仅可查看概览;请先在 Workbench 中申请加入并等待批准。";
282
+ if (error?.code === "task_access_denied")
283
+ return "当前身份没有读取任务内容的权限,请先确认任务参与资格。";
284
+ if (error?.status === 401 || error?.status === 403)
285
+ return "请检查 DF_WORKBENCH_TOKEN、工作区和目标环境配置。";
286
+ return "";
287
+ }
288
+
272
289
  function factsSummary(value) {
273
290
  const facts = Array.isArray(value.facts) ? value.facts : [];
274
291
  const lines = [`事实数量: ${facts.length}`];
@@ -293,7 +310,7 @@ function help() {
293
310
  df-workbench task send <task-id> --message <消息> [--idempotency-key <key>]
294
311
  df-workbench task get <task-id> [--json]
295
312
  df-workbench task facts <task-id> [--after <seq>] [--limit <n>] [--json]
296
- df-workbench task list [--limit <n>] [--json]
313
+ df-workbench task list [--scope <mine|workspace>] [--limit <n>] [--json]
297
314
 
298
315
  全局配置:
299
316
  DF_WORKBENCH_BASE_URL Workbench 根地址,默认 http://127.0.0.1:8793
@@ -410,10 +427,16 @@ async function run(options) {
410
427
  }
411
428
  if (subject === "list") {
412
429
  const context = await currentContext(options);
430
+ if (!["mine", "workspace"].includes(options.scope))
431
+ throw new UsageError("--scope 必须是 mine 或 workspace。");
413
432
  const limit = integerOption(options.limit, "--limit", 50, 1, 200);
414
433
  const value = await request(
415
434
  options,
416
- `/api/v1/tasks?scope=mine&limit=${limit}`,
435
+ `/api/v1/tasks?${new URLSearchParams({
436
+ scope: options.scope,
437
+ limit: String(limit),
438
+ include_state: "1",
439
+ })}`,
417
440
  {},
418
441
  context,
419
442
  );
@@ -422,7 +445,9 @@ async function run(options) {
422
445
  options,
423
446
  (value) =>
424
447
  (value.tasks || [])
425
- .map((task) => `${task.id} ${task.title || ""}`.trim())
448
+ .map((task) =>
449
+ `${task.id} ${task.title || ""}${task.access === "overview" ? "(仅概览)" : ""}`.trim(),
450
+ )
426
451
  .join("\n") || "没有任务。",
427
452
  );
428
453
  return;
@@ -449,10 +474,8 @@ if (
449
474
  ? ` [${error.code}]`
450
475
  : "";
451
476
  process.stderr.write(`请求失败${suffix}:${error.message}\n`);
452
- if (error.details?.status === 401 || error.details?.status === 403)
453
- process.stderr.write(
454
- "请检查 DF_WORKBENCH_TOKEN、工作区和目标环境配置。\n",
455
- );
477
+ const hint = requestFailureHint(error);
478
+ if (hint) process.stderr.write(`${hint}\n`);
456
479
  } else {
457
480
  process.stderr.write(
458
481
  `失败:${error instanceof Error ? error.message : String(error)}\n`,
@@ -1,5 +1,5 @@
1
1
  id: deepflow-suite
2
- version: 0.2.3
2
+ version: 0.2.5
3
3
  kind: composite-skill
4
4
  requires:
5
5
  skills: