9.4 KiB
name, description, agent_created
| name | description | agent_created |
|---|---|---|
| docsys | 操作公司 MxsDoc / DocSystem 网络文档系统(http://172.1.4.31:8100/DocSystem)的文件系统——仓库浏览、目录创建/删除/重命名、文件上传/删除/重命名/移动/复制、以及按文件名或正文搜索。当用户提到"文档系统""DocSystem""MxsDoc""文档库""上传文件到文档系统""在文档系统里建目录/搜文件"时使用。 | true |
DocSystem 文档系统操作 Skill
通过纯 HTTP 调用 MxsDoc(DocSystem)后端接口,让 AI 直接操作公司文档系统的文件系统: 浏览、建目录、删除、重命名、移动、复制、上传、下载、搜索。
底层是一个零依赖的 Python CLI:只用标准库,不需要 pip 安装任何东西。
首次配置(凭证)
凭证不写在代码里,从 ~/.docsys/config.json 或环境变量读取。首次使用先建这个文件:
{
"baseUrl": "http://172.1.4.31:8100/DocSystem",
"user": "your.name@company.com",
"password": "your-password"
}
也可用环境变量 DOCSYS_BASE_URL / DOCSYS_USER / DOCSYS_PASSWORD,或命令行 --base-url / --user / --password 临时覆盖。
未配置时 CLI 会直接提示配置文件路径,不会用空账号去撞登录接口。
快速开始
PY="C:/Users/occul/.workbuddy/binaries/python/versions/3.13.12/python.exe"
SK="C:/Users/occul/WorkBuddy/docsys-skill/docsys"
$PY "$SK/scripts/docsys.py" login # 登录并缓存会话(首次执行即可)
$PY "$SK/scripts/docsys.py" repos # 列出可访问仓库
$PY "$SK/scripts/docsys.py" ls "意见与反馈" / # 列出仓库根目录
会话 cookie 缓存在 ~/.docsys/session.json,过期时会自动重新登录,不需要每次显式 login。
⚠️ 默认仓库约定
未指定仓库时一律使用 研发管理配置库(id=2)。 用户说"上传个文件""搜一下 XX"而没提别的库时,不要反问,直接对这个库操作。
$PY "$SK/scripts/docsys.py" ls # = ls 研发管理配置库 /
$PY "$SK/scripts/docsys.py" ls /Sunyard # 路径以 / 开头,仓库自动取默认
$PY "$SK/scripts/docsys.py" ls 1 / # 显式切到其他库才带仓库参数
$PY "$SK/scripts/docsys.py" search 详细设计 # 默认搜默认库
$PY "$SK/scripts/docsys.py" search 详细设计 --all-repos # 例外:搜全部库
repos 命令会给默认库打 ← 默认 标记。默认库可用环境变量 DOCSYS_DEFAULT_REPO 覆盖。
判定规则:第一个位置参数若以 / 或 ./ 开头 → 视为路径,仓库取默认;否则视为仓库名/id。所以 ls /Sunyard 和 ls 研发管理配置库 /Sunyard 等价。
内部实现是"位置参数整体左移一位",所以 touch /a/b.txt "内容" 这类后面还带可选参数的命令也不会错位。
命令一览
<repo> 全部可省略(省略即默认库):
| 命令 | 说明 |
|---|---|
login / logout / whoami |
会话管理 |
repos |
列出可访问仓库(id + 名称,标注默认) |
ls [repo] [path] |
列出目录内容 |
tree [repo] [path] [--depth N] |
递归列目录树 |
mkdir [repo] <path> [-p] |
创建目录;默认要求父目录已存在,-p 递归创建中间目录 |
touch [repo] <path> [content] |
创建文本文件;content=@file --file x.txt 从本地读内容 |
rename [repo] <path> <new_name> |
重命名(不能跨目录) |
rm [repo] <path> |
删除文件或目录(目录为递归删除) |
mv [repo] <src> <dst> |
移动/改名。dst 是已存在目录则移入其中,否则视为目标完整路径 |
cp [repo] <src> <dst> |
复制,语义同 mv |
upload [repo] <remote_dir> <local_file> [--name X] |
上传本地文件 |
download [repo] <path> <local_file> |
下载;local_file 为 - 时输出到 stdout |
cat [repo] <path> |
读取文本文件内容 |
search <keyword> [--repo R] [--all-repos] [--path P] |
按文件名或正文搜索;默认搜默认库,--all-repos 搜全部 |
auth [repo] [path] |
查看当前账号在该目录的权限 |
全局参数:--json(结构化输出,推荐 AI 解析用)、--base-url、--user、--password。
用法约定(给 AI 的操作说明)
0. 仓库默认就是「研发管理配置库」(id=2)。 用户没指名别的仓库时不要反问、不要先跑 repos 确认,直接操作。切库时才带 repo 参数。
1. 仓库也可以用 id 或名称指定,名称支持子串匹配:
$PY ... ls 1 / # 按 id
$PY ... ls 常用工具 / # 按名称
$PY ... ls 研发 / # 子串,唯一匹配
2. 路径一律用 /a/b/c 形式,前导斜杠可省略,仓库根写 / 或留空。
单独给路径时(ls /Sunyard)脚本会自动识别为"默认库的该路径",不会误判成仓库名。
3. 要解析用户输入("研发库的 2024 归档目录")时,先用 repos + search / tree 定位,不要猜。
4. 破坏性操作(rm、覆盖式 mv/cp)执行前先向用户确认,并优先用 ls 或 auth 确认目标存在且有权限。
5. 推荐加 --json,输出结构稳定:
[{"name":"t1.txt","fullPath":"_SELFTEST/t1.txt","type":"file","size":35,"mtime":"2026-10-20 14:33","docId":202070828624}]
权限边界(当前账号实测)
账号 qian.huang@sunyard.com 实测:
权限是逐目录授予的,不是仓库级。 同一个仓库里不同目录可以完全不同:
| 目录 | 访问 | 新增 | 编辑 | 删除 | 下载 |
|---|---|---|---|---|---|
研发管理配置库 /(根) |
✅ | ❌ | ❌ | ❌ | ❌ |
研发管理配置库 /Sunyard/Docs/开发流程 |
✅ | ❌ | ❌ | ❌ | ✅ |
研发管理配置库 /Sunyard/Dev/产品/系统研发/工具 |
✅ | ✅ | ✅ | ✅ | ✅ |
意见与反馈 /(根) |
✅ | ✅ | ✅ | ❌ | ❌ |
所以不要凭仓库名推断权限,任何写操作前先跑 auth <path> 确认。
已验证可完整 CRUD 的目录:/Sunyard/Dev/产品/系统研发/工具/测试(增删改 + 下载全开)。
服务端权限不足时返回中文错误,CLI 原样透出:
[docsys] 您没有该目录的删除权限,请联系管理员
遇到这类报错不要反复重试、也不要自作主张换到别的目录/仓库,直接告诉用户需要管理员授权。
注意:重命名和移动在服务端按"删除 + 新增"鉴权,所以即使有新增权限也可能被拒。
接口契约(排障用)
全部为 POST {BASE}/...,{BASE} = http://172.1.4.31:8100/DocSystem,表单编码,
需要带 X-Requested-With: XMLHttpRequest,会话靠 cookie(JSESSIONID / dstoken / dsuser)。
登录密码先做 base64 编码再提交。响应统一为 {status:"ok"|"fail", data, msgInfo}。
| 接口 | 参数 |
|---|---|
User/login.do |
userName, pwd(base64), rememberMe |
Repos/getReposList.do |
无 |
Repos/getSubDocList.do |
vid, docId, path, name, sort, needLockState |
Repos/getUserDocAuth.do |
docId, reposId, path, name |
Doc/addDoc.do |
reposId, type(1文件/2目录), pid, path, name, content(实测 content 被忽略,建出来恒为 0 字节空文件) |
Doc/renameDoc.do |
reposId, docId, pid, type, level, path, name, dstName |
Doc/deleteDoc.do |
reposId, docId, pid, path, name |
Doc/moveDoc.do |
reposId, docId, type, srcLevel, dstLevel, srcPid, dstPid, srcPath, srcName, dstPath, dstName |
Doc/copyDoc.do |
同 moveDoc |
Doc/uploadDoc.do |
multipart:reposId, path, name, size, checkSum(md5), uploadFile, commitMsg, dirPath |
Doc/downloadDocPrepare.do |
reposId, docId, pid, path, name, downloadType |
Doc/downloadDoc.do |
GET:vid, path, name, targetPath, targetName, deleteFlag, encryptEn=1 |
Doc/searchDoc.do |
searchWord, sort, reposId, path |
Doc/getDocContent.do |
reposId, docId, pid, path, name(返回纯文本,响应开头有 ok 前缀) |
路径语义(最容易踩的坑)
- 节点字段
path是它所在目录的路径:根目录下为"",其余以/结尾,如_SELFTEST/sub/。 节点完整路径 =path + name。 - 列举:
getSubDocList只看path + name拼接结果,docId不参与定位。 要列_SELFTEST的子项,必须传path=_SELFTEST/(或path=_SELFTEST/且name=空)。 - 写入(addDoc / uploadDoc / moveDoc 的
dstPath):要传父目录完整路径 +/, 例如往_SELFTEST下建文件,path应为_SELFTEST/,而不是节点自身的""。 - 删除 / 重命名:传节点自身的
path与name。
其他服务端怪癖
addDoc.do忽略content:新建文件永远得到 0 字节空文件,响应里size=0,getDocContent也读不到内容。要写内容必须走uploadDoc.do(CLI 的touch已自动改为走上传通道)。getDocContent.do返回纯文本且开头带ok两个字符前缀,解析要剥掉;空文件时只返回ok。getDocFileLink.do不可用:链接指向tmp/History/rdata/<commitId>/...历史目录,文件不存在会 500。 下载必须走downloadDocPrepare.do→downloadDoc.do。
文件
scripts/docsys.py— CLI 实现(Python 3 标准库,零依赖)README.md— 逆向出的完整接口文档