Files

9.4 KiB
Raw Permalink Blame History

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 — 逆向出的完整接口文档