@comate/zulu 1.3.2-beta.1 → 1.3.3

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.
@@ -45,7 +45,7 @@ curl -s -X POST https://comate.baidu-int.com/api/aidevops/autocomate/rest/autowo
45
45
  -H "Content-Type: application/json" \
46
46
  -H "login-name: ${COMATE_USERNAME}" \
47
47
  -d '{
48
- "contents": [{"parts": [{"text": "YOUR_PROMPT_HERE"}]}],
48
+ "contents": [{"role": "USER", "parts": [{"text": "YOUR_PROMPT_HERE"}]}],
49
49
  "resolution": "1K"
50
50
  }' \
51
51
  | jq -r '.candidates[0].content.parts[] | select(.inlineData) | .inlineData.data' \
@@ -58,7 +58,7 @@ curl -s -X POST https://comate.baidu-int.com/api/aidevops/autocomate/rest/autowo
58
58
  # Write JSON to temp file to avoid PowerShell double-quote escaping bug with curl.exe -d
59
59
  $tmpFile = "$env:TEMP\request.json"
60
60
  @'
61
- {"contents":[{"parts":[{"text":"YOUR_PROMPT_HERE"}]}],"resolution":"1K"}
61
+ {"contents":[{"role": "USER", "parts":[{"text":"YOUR_PROMPT_HERE"}]}],"resolution":"1K"}
62
62
  '@ | Set-Content -Path $tmpFile -Encoding UTF8 -NoNewline
63
63
 
64
64
  $response = curl.exe -s -X POST https://comate.baidu-int.com/api/aidevops/autocomate/rest/autowork/v1/generate-image `
@@ -91,6 +91,7 @@ cat > /tmp/request.json << EOF
91
91
  {
92
92
  "contents": [
93
93
  {
94
+ "role": "USER",
94
95
  "parts": [
95
96
  {"inline_data": {"mime_type": "image/png", "data": "${IMG_B64}"}},
96
97
  {"text": "YOUR_EDIT_INSTRUCTIONS_HERE"}
@@ -123,6 +124,7 @@ $tmpFile = "$env:TEMP\request.json"
123
124
  {
124
125
  "contents": [
125
126
  {
127
+ "role": "USER",
126
128
  "parts": [
127
129
  {"inline_data": {"mime_type": "image/png", "data": "$imgBase64"}},
128
130
  {"text": "YOUR_EDIT_INSTRUCTIONS_HERE"}
@@ -219,12 +221,13 @@ $resolution = if ($maxDim -ge 3000) { "4K" }
219
221
 
220
222
  ## Output
221
223
 
222
- - Saves PNG to current directory
224
+ - Saves PNG to `.comate/images` directory, if directory is not exist, you need to create it.
223
225
  - Script outputs the full path to the generated image
224
- - **Do not read the image back** - display the image using markdown syntax: `![image](relative/path/to/image.png)`
225
- - **Display the image path only once** using a relative path (e.g. `output-name.png` or `subdir/output-name.png`);
226
- - do NOT display absolute paths (e.g. `/home/user/...` formats are forbidden); do NOT repeat the path multiple times in
227
- the conversation
226
+ - **Do not read the image back** - display the image using markdown syntax: `![image](/absolute/path/to/image.png)`
227
+ - **Display the image path only once** using an absolute path (e.g. `/home/user/project/.comate/images/output-name.png`)
228
+ - Absolute paths are REQUIRED (e.g. paths starting with `/` on Unix or `C:\` on Windows);
229
+ - do NOT use relative paths (e.g. `./output.png` or `images/output.png` formats are forbidden);
230
+ - do NOT repeat the path multiple times in the conversation
228
231
 
229
232
  ---
230
233
 
@@ -264,7 +267,7 @@ curl.exe ... -d $body # PowerShell corrupts the " characters
264
267
  # Single-quote here-string: content is taken literally, no escaping
265
268
  $tmpFile = "$env:TEMP\request.json"
266
269
  @'
267
- {"contents":[{"parts":[{"text":"YOUR_PROMPT_HERE"}]}],"resolution":"1K"}
270
+ {"contents":[{"role": "USER", "parts":[{"text":"YOUR_PROMPT_HERE"}]}],"resolution":"1K"}
268
271
  '@ | Set-Content -Path $tmpFile -Encoding UTF8 -NoNewline
269
272
 
270
273
  curl.exe ... -d "@$tmpFile" # curl reads the file directly, no PowerShell escaping
@@ -20,7 +20,7 @@ metadata:
20
20
  ## 文件结构
21
21
 
22
22
  ```
23
- get-ugate-token/
23
+ ${COMATE_SKILL_DIR}/
24
24
  ├── SKILL.md # 技能说明文档
25
25
  └── getUgateToken.py # Python 主脚本
26
26
  ```
@@ -39,14 +39,14 @@ get-ugate-token/
39
39
 
40
40
  ```bash
41
41
  # 用户发送消息:ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
42
- USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 getUgateToken.py chenshouqin 2>&1
42
+ USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME} 2>&1
43
43
  TOKEN_SAVED:Token 已保存
44
44
  eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
45
45
  ```
46
46
 
47
47
  ### 2. 检查缓存的 token
48
48
 
49
- - 检查文件 `~/.config/uuap/.eac_ugate_token_{username}` 是否存在
49
+ - 检查文件 `~/.config/uuap/.eac_ugate_token_${COMATE_USERNAME}` 是否存在
50
50
  - 如果文件存在,直接返回缓存的 token(永久有效)
51
51
 
52
52
  ### 3. 需要手动获取 token
@@ -65,10 +65,10 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
65
65
 
66
66
  ```bash
67
67
  # 获取 ugate token(需要传入用户名)
68
- python3 /home/gem/.openclaw/skills/get-ugate-token/getUgateToken.py <username>
68
+ python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME}
69
69
 
70
70
  # 手动输入 token(通过 USER_MESSAGE 环境变量)
71
- USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 /home/gem/.openclaw/skills/get-ugate-token/getUgateToken.py <username>
71
+ USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME}
72
72
  ```
73
73
 
74
74
  ## 输出格式
@@ -76,14 +76,14 @@ USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 /hom
76
76
  ### 成功场景(缓存有效)
77
77
 
78
78
  ```bash
79
- $ python3 getUgateToken.py chenshouqin
79
+ $ python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME}
80
80
  eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
81
81
  ```
82
82
 
83
83
  ### 手动输入 token 场景
84
84
 
85
85
  ```bash
86
- $ USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 getUgateToken.py chenshouqin 2>&1
86
+ $ USER_MESSAGE="ugate token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME} 2>&1
87
87
  TOKEN_SAVED:Token 已保存
88
88
  eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
89
89
  ```
@@ -93,7 +93,7 @@ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
93
93
  脚本会输出到 stderr 并以退出码 2 退出:
94
94
 
95
95
  ```bash
96
- $ python3 getUgateToken.py chenshouqin 2>&1
96
+ $ python3 getUgateToken.py ${COMATE_USERNAME} 2>&1
97
97
  NEED_MANUAL_TOKEN:请点击 https://uuap.baidu.com/agent/token 获取token,然后复制内容发送给我
98
98
  ```
99
99
 
@@ -117,7 +117,7 @@ NEED_MANUAL_TOKEN:请点击 https://uuap.baidu.com/agent/token 获取token,然
117
117
  **使用方式:** 在调用脚本时设置环境变量 `USER_MESSAGE`,例如:
118
118
 
119
119
  ```bash
120
- USER_MESSAGE="刷新ugate" python3 /home/gem/.openclaw/skills/get-ugate-token/getUgateToken.py <username>
120
+ USER_MESSAGE="刷新ugate" python3 ${COMATE_SKILL_DIR}/getUgateToken.py ${COMATE_USERNAME}
121
121
  ```
122
122
 
123
123
  ## 环境变量依赖
@@ -126,7 +126,7 @@ USER_MESSAGE="刷新ugate" python3 /home/gem/.openclaw/skills/get-ugate-token/ge
126
126
 
127
127
  ## 缓存机制
128
128
 
129
- - **缓存文件:** `~/.config/uuap/.eac_ugate_token_{username}`(多用户独立缓存)
129
+ - **缓存文件:** `~/.config/uuap/.eac_ugate_token_${COMATE_USERNAME}`(多用户独立缓存)
130
130
  - **缓存格式:** JSON
131
131
  ```json
132
132
  {
@@ -138,9 +138,9 @@ USER_MESSAGE="刷新ugate" python3 /home/gem/.openclaw/skills/get-ugate-token/ge
138
138
 
139
139
  ## 多用户支持
140
140
 
141
- 每个用户有独立的缓存文件,文件名格式为 `.eac_ugate_token_{username}`,例如:
141
+ 每个用户有独立的缓存文件,文件名格式为 `.eac_ugate_token_${COMATE_USERNAME}`,例如:
142
142
 
143
- - 用户 `chenshouqin` → `~/.config/uuap/.eac_ugate_token_chenshouqin`
143
+ - 用户 `${COMATE_USERNAME}` → `~/.config/uuap/.eac_ugate_token_${COMATE_USERNAME}`
144
144
  - 用户 `zhangjianxing` → `~/.config/uuap/.eac_ugate_token_zhangjianxing`
145
145
 
146
146
  这样可以避免不同用户的 token 相互干扰。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ku-operator
3
- description: 操作百度内部知识库(Ku)系统的文档。支持文档内容查询、知识库目录查询、新建文档、移动文档等操作。当用户需要在知识库中创建文档、查看文档内容、浏览目录结构、或移动文档位置时使用此 Skill。
3
+ description: 操作百度内部知识库(ku.baidu-int.com)系统的文档。支持文档内容查询、知识库目录查询、新建文档、移动文档等操作。当用户需要在知识库中创建文档、查看文档内容、浏览目录结构、或移动文档位置时使用此 Skill。
4
4
  metadata:
5
5
  enableWhen:
6
6
  - isInternal
@@ -14,22 +14,32 @@ metadata:
14
14
 
15
15
  - **Skill 依赖 `get-ugate-token`**:认证通过 get-ugate-token skill 自动获取个人身份 token
16
16
  - **环境变量 `COMATE_USERNAME`**:当前用户的百度用户名,认证和创建/移动文档时自动读取
17
- - **当前用户名**: ${COMATE_USERNAME},即`COMATE_USERNAME=${COMATE_USERNAME}`
18
17
  - **Python 依赖**:`requests` 库
19
- - **CLI 工具 `dodo_cli bos upload`**:`create-doc` 上传图片/附件时自动调用
20
18
  - **执行方式**:在 Skill 目录下使用 **`python3`** 直接运行脚本,不要 import 调用
19
+ - **`create-doc`** 目前不支持 上传图片/附件 功能,禁止执行 上传图片/附件 的操作
20
+
21
+
22
+ ## Skill 路径
23
+
24
+ - skill 所在的路径是:${COMATE_SKILL_DIR},
25
+ - 执行脚本或是查看文档请先打开 skill 所在路径,导出环境变量,然后再执行脚本
26
+ - 示例:cd ${COMATE_SKILL_DIR} && COMATE_USERNAME=${COMATE_USERNAME} && python3 scripts/ku_operator.py args
21
27
 
22
28
  ## 认证说明
23
29
 
24
30
  本 skill 依赖 `get-ugate-token` skill 进行个人身份认证。调用时自动获取 ugate token:
25
31
  - 若本地已有有效的 token 缓存文件,直接使用,无需用户介入
26
- - 若 token 不存在或已过期,`get-ugate-token` 会向用户推送授权卡片(如流消息),脚本以退出码 2 中断当前任务
27
- - 用户完成授权后,重新发起操作即可
32
+ - 若 token 不存在或已过期,需要前往 https://uuap.baidu.com/agent/token 页面给 Comate 开通 ugate 授权
33
+ - 开通后,token 永久有效,无需重复配置
28
34
 
29
35
  API 返回 401/403 时,脚本会提示用户重新触发授权流程并以退出码 2 退出。
30
36
 
31
37
  ## 知识库 URL 与 ID 解析(重要)
32
38
 
39
+ 知识库链接有两种格式:
40
+
41
+ ### 格式一:完整路径链接
42
+
33
43
  ```
34
44
  https://ku.baidu-int.com/knowledge/{spaceGuid}/{groupGuid}/{repoGuid}/{docGuid}
35
45
  ```
@@ -45,6 +55,22 @@ https://ku.baidu-int.com/knowledge/{spaceGuid}/{groupGuid}/{repoGuid}/{docGuid}
45
55
  - **4 段**(含 docGuid)→ 文档链接,可直接 `query-content` 读取
46
56
  - **3 段**(仅到 repoGuid)→ 知识库链接,需先 `query-repo` 查询目录
47
57
 
58
+ ### 格式二:短链接
59
+
60
+ ```
61
+ https://ku.baidu-int.com/d/{docId}
62
+ ```
63
+
64
+ 这是文档的短链接格式,`/d/` 后面的部分即为 **文档 ID**(doc-id)。例如 `https://ku.baidu-int.com/d/bLKhnZmWDDm7JH` 中 `bLKhnZmWDDm7JH` 就是 doc-id。
65
+
66
+ 短链接**始终是文档链接**,可直接使用 `query-content --url <短链接>` 或 `query-content --doc-id <docId>` 读取。
67
+
68
+ ### 识别知识库链接
69
+
70
+ 以下域名的 URL 均为知识库链接,应使用本 skill 处理:
71
+ - `ku.baidu-int.com/knowledge/...`(完整路径链接)
72
+ - `ku.baidu-int.com/d/...`(短链接)
73
+
48
74
  ## 重要概念:文档即目录
49
75
 
50
76
  知识库中**文档和目录是同一个概念**——任何文档都可以拥有子文档。读取文档后应通过 `query-repo --parent-doc-guid <该文档ID>` 检查是否有子文档,按需加载以提供完整结果。
@@ -58,7 +84,7 @@ https://ku.baidu-int.com/knowledge/{spaceGuid}/{groupGuid}/{repoGuid}/{docGuid}
58
84
  3. **询问用户**:请用户提供目标知识库文档的 URL
59
85
 
60
86
  **写入范围约束:**
61
- - 文档链接(4 段)→ 只能在该文档及其子目录下创建
87
+ - 文档链接(4 段路径或短链接 `/d/{docId}`)→ 只能在该文档及其子目录下创建
62
88
  - 知识库链接(3 段)→ 可在整个知识库范围内创建
63
89
  - 用户明确指定其他位置时,以用户指令为准
64
90
 
@@ -106,6 +132,8 @@ https://ku.baidu-int.com/knowledge/{spaceGuid}/{groupGuid}/{repoGuid}/{docGuid}
106
132
  | `references/query_user_info.md` | 用户信息查询详细说明 |
107
133
  | `references/upload_attachment.md` | 上传附件到文档正文 |
108
134
  | `references/query_flowchart.md` | 查询文档流程图数据 |
135
+ | `references/query_recent_view.md` | 查询文档浏览记录 |
136
+ | `references/add_member.md` | 添加文档成员 |
109
137
  | `references/update_member.md` | 更新文档成员角色 |
110
138
  | `references/query_permission.md` | 查询用户文档权限 |
111
139
  | `references/change_scope.md` | 修改文档公开/私密范围 |
@@ -115,7 +143,7 @@ https://ku.baidu-int.com/knowledge/{spaceGuid}/{groupGuid}/{repoGuid}/{docGuid}
115
143
  **可自行修复(重试):** 参数缺失、ID 格式错误(repoGuid/docGuid 搞反)、页码超出范围
116
144
 
117
145
  **需告知用户(不重试):**
118
- - 认证失败(401/403)→ 提示用户重新发起操作以触发 get-ugate-token 授权
146
+ - 认证失败(401/403)→ 提示用户前往 https://uuap.baidu.com/agent/token 页面给 Comate 开通 ugate 授权
119
147
  - 文档不存在(404)→ 告知用户检查文档是否已被删除
120
148
  - 无操作权限 → 告知用户联系知识库管理员
121
149
  - 服务端错误(5xx)→ 告知用户稍后再试
@@ -24,6 +24,19 @@ python3 scripts/ku_operator.py query-content \
24
24
 
25
25
  效果同上,适用于用户直接给出链接的场景。
26
26
 
27
+ ### 通过短链接查询
28
+
29
+ ```bash
30
+ python3 scripts/ku_operator.py query-content \
31
+ --url "https://ku.baidu-int.com/d/bLKhnZmWDDm7JH"
32
+ ```
33
+
34
+ 短链接格式为 `https://ku.baidu-int.com/d/{docId}`,`/d/` 后面即文档 ID。也可以直接提取 doc-id 使用:
35
+
36
+ ```bash
37
+ python3 scripts/ku_operator.py query-content --doc-id bLKhnZmWDDm7JH
38
+ ```
39
+
27
40
  ---
28
41
 
29
42
  ## 二、query-repo(查询知识库目录)
@@ -142,7 +142,9 @@ class KuApiClient:
142
142
  """
143
143
  if not doc_id and not url:
144
144
  raise ValueError("必须提供 --doc-id 或 --url 中的至少一个")
145
- payload: Dict[str, Any] = {}
145
+ payload: Dict[str, Any] = {
146
+ "protocol": 1
147
+ }
146
148
  if doc_id:
147
149
  payload["docId"] = doc_id
148
150
  if url:
@@ -909,24 +911,39 @@ def format_repo_tree(
909
911
  # ---------------------------------------------------------------------------
910
912
 
911
913
  def _get_ugate_token(username: str) -> str:
912
- """调用 get-ugate-token skill 获取 ugate token。"""
913
- script_path = Path(__file__).parent.parent.parent / "get-ugate-token" / "getUgateToken.py"
914
- if not script_path.exists():
915
- print(f"错误: 未找到 get-ugate-token 脚本: {script_path}", file=sys.stderr)
916
- sys.exit(1)
917
- result = subprocess.run(
918
- [sys.executable, str(script_path), username],
919
- capture_output=True, text=True, timeout=30,
920
- )
921
- if result.returncode == 0:
922
- return result.stdout.strip()
923
- if result.returncode == 2:
924
- # 需要用户授权
925
- print(result.stderr, file=sys.stderr, end="")
914
+ """
915
+ 获取 ugate token。策略:
916
+ 1. 首先从缓存文件获取(~/.config/uuap/.eac_ugate_token_{username})
917
+ 2. 如果缓存不存在或无效,提示用户调用 get-ugate-token skill
918
+ """
919
+ import json
920
+
921
+ # 步骤 1: 尝试从缓存读取
922
+ cache_file = Path.home() / ".config" / "uuap" / f".eac_ugate_token_{username}"
923
+ if cache_file.exists():
924
+ try:
925
+ with open(cache_file, 'r') as f:
926
+ data = json.load(f)
927
+ # 如果存在 expires_at 字段,认为 token 无效
928
+ if 'expires_at' not in data:
929
+ token = data.get('token')
930
+ if token:
931
+ return token
932
+ except (json.JSONDecodeError, KeyError, OSError):
933
+ pass
934
+
935
+ # 步骤 2: 缓存不可用,提示用户
936
+ token = None
937
+ if not token:
938
+ print(
939
+ "错误: 未从本地读取到 ugate token(~/.config/uuap/.eac_ugate_token_*)。",
940
+ file=sys.stderr,
941
+ )
942
+ print(
943
+ "请先调用 get-ugate-token skill 完成授权或写入 token,再重试本操作。",
944
+ file=sys.stderr,
945
+ )
926
946
  sys.exit(2)
927
- # 其他错误
928
- print(result.stderr, file=sys.stderr, end="")
929
- sys.exit(1)
930
947
 
931
948
 
932
949
  def _get_client() -> KuApiClient: