新增 DATA_SOURCES.md、data-sources 示例与双后端 connection 骨架;CLI 与宿主 UI 可读写同一库。要求匠厂 Host ≥ 6.9.28。 Co-authored-by: Cursor <cursoragent@cursor.com>
8.2 KiB
用户数据目录与文件路径黄金标准
本文是 skill 读写本地文件 的权威约定。凡涉及输入、输出、缓存、RPA 存证等路径,复制模板后须遵守本文;Agent 实现业务 skill 时也应先读本文。
1. 根目录
所有技能持久化数据(配置、数据库、业务文件)默认落在:
{JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{skill_slug}/
示例:
D:\jiangchang-data\12500\download-video-baidu-haokan\
实现:util.runtime_paths.get_skill_data_dir()。
禁止把技能自己写入的文件落到:
- Agent / 宿主 workspace(进程 CWD)
- 技能安装目录(含
.openclaw/skills/...) - 未在本文声明的任意相对 CWD 路径
2. 标准子目录树
用户可见 · 文件目录(数据管理「输入 / 输出」文件浏览器只挂这两个):
| 子目录 | 方向 | 用途 | 默认 helper |
|---|---|---|---|
input/ |
上行 | 用户/Agent 放入的待处理材料(urls.txt、batch.json、CSV、产品表…) | get_input_dir() |
output/ |
下行 | 技能/宿主交给用户拿走的结果(视频、回单、xlsx/csv/json…) | get_output_dir() |
用户可见 · HTML 报告页(宿主扫描挂到技能下,不是 input/output 文件浏览器):
| 子目录 | 用途 | 默认 helper |
|---|---|---|
html/ |
技能写出的静态 .html 报告;宿主一层扫描 *.html,侧栏预览 / 右键重新生成 |
get_html_dir() |
内部 / 可选目录(不上侧栏):
| 子目录 | 用途 | 默认 helper |
|---|---|---|
uploads/ |
待发布到外部平台的 staging(可选) | get_uploads_dir() |
cache/ |
可再生缓存(页面快照、解析中间结果) | get_cache_dir() |
temp/ |
单次任务 scratch,任务结束可删 | get_temp_dir() |
rpa-artifacts/ |
RPA 失败截图、录屏中间产物 | get_rpa_artifacts_dir(batch_id) |
videos/ |
RPA 录屏成片 MP4 | get_videos_dir() |
{skill_slug}.db |
SQLite(默认本地库) | get_db_path() |
data-sources.json |
声明式数据源(可选;不配则宿主自动扫描 .db) |
用户目录根;格式见 ../references/DATA_SOURCES.md |
.env |
用户配置(含可选 MYSQL_DSN) |
config.get_env_file_path() |
复制后若业务不需要某目录,可不创建;但一旦写入该类文件,必须走对应 helper。
开发者硬规则:
- 用户/Agent 放进来的文件 →
input/(get_input_dir()) - 技能/宿主 交给用户拿走的文件 →
output/(get_output_dir()) - 可浏览的 HTML 报告页 →
html/(get_html_dir()/service.html_page_service);不要把整页报告塞进output/指望侧栏预览 - 禁止再引入业务「文件浏览器」第三目录(如旧的
downloads/imports/exports三分法);html/是报告页扫描面,不是第三种文件浏览器 - 缓存、临时、RPA 录屏用
cache/temp/videos,不要当成用户可见的「输出目录」
宿主约定(与本模板对齐):
- 工具栏「导入」UI 一律打开宿主「导入数据」面板(默认从本技能
input/选文件);「导出」默认写到output/ - Action 表单里
display_type/format为file或directory时:宿主原生对话框默认打开当前技能{skill_data}/input;若字段声明可选pathRoot(相对技能数据根,如input/库存数据),则打开该子目录。禁止在技能里写用户 ID 或绝对盘符。契约见../references/ACTIONS.md「本地路径选择与 pathRoot」 - 若表声明了
replaces: import,确认导入后由技能 CLI 写库(见../references/ACTIONS.md「replaces」);仅有replaces: create时宿主可按行调 create(兼容) - 数据管理扫描两处 HTML(都只扫一层):安装包
assets/html/pages/*.html是装完就有的壳子页;{skill_data}/html/*.html是快照,「重新生成」调用 Action idrender-html。页面里用jiangchang.call调本技能已声明的命令。详见../references/ACTIONS.md「HTML 页面报告」
3. 两类路径
A. 技能拥有(skill-owned)
技能创建或更新的文件:下载结果、导出报表、失败截图、队列 sidecar 等。
- 默认必须在
{skill_data_dir}/<子目录>/下。 - 用户可拿走的业务产出 →
output/。 - 必须通过
resolve_data_path()或get_*_dir()解析,禁止os.path.abspath(config.get(...))相对 CWD。
B. 用户显式输入(user-owned)
用户在 CLI / Agent 对话中给出的已有文件绝对路径,例如「发布这个视频 D:\素材\x.mp4」。
- 技能只读,路径可以是用户磁盘任意位置。
- 使用
resolve_input_path():绝对路径原样;相对路径解析为{skill_data_dir}/input/<相对路径>,不相对 workspace/CWD。
4. 配置项(.env)
可选覆盖项(留空则用默认子目录):
# ── 数据目录子路径(见 development/DATA_PATHS.md)──
# 相对路径相对于 {JIANGCHANG_DATA_ROOT}/{USER_ID}/{slug}/,不是 workspace
# SKILL_INPUT_DIR=input
# SKILL_OUTPUT_DIR=output/videos
# SKILL_UPLOAD_DIR=uploads
# SKILL_CACHE_DIR=cache
# SKILL_TEMP_DIR=temp
| 规则 | 说明 |
|---|---|
| 未配置 | {skill_data_dir}/{default_subdir} |
相对值 output/videos |
{skill_data_dir}/output/videos |
绝对值 D:\nas\output |
高级用户/NAS 挂载,原样使用 |
禁止 ./outputs/... |
会随 CWD 漂移,不得作为 .env.example 活跃配置行 |
业务专属路径 env key 须带 SKILL_ 前缀(或技能 slug 前缀),避免污染全局命名空间。
5. 代码用法
from util.runtime_paths import (
get_input_dir,
get_output_dir,
resolve_data_path,
resolve_input_path,
list_resolved_data_paths,
)
# 下行产出(A 类)——视频、报表等
dest = os.path.join(get_output_dir(), f"{vid}.mp4")
# 或带 env 覆盖
out_dir = resolve_data_path("SKILL_OUTPUT_DIR", "output")
# CLI -i urls.txt(B 类,相对路径 → input/)
manifest = resolve_input_path(args.input_path)
# health 诊断
paths = list_resolved_data_paths()
反模式(禁止):
# ❌ 相对 CWD,Agent 从 workspace 执行时会写错盘
os.path.abspath(config.get("DOWNLOAD_OUTPUT_DIR"))
# ❌ .env.example 里写 ./outputs/videos
DOWNLOAD_OUTPUT_DIR=./outputs/videos
# ❌ 再拆 downloads / imports / exports 三个用户目录
6. health / config-path
health 或 config-path 建议输出 list_resolved_data_paths() 中的路径,便于排查「文件写到哪里去了」。展示路径须与 run 实际使用的一致。
7. 与 RPA 存证的关系
业务 output/ 与 RPA videos/ 分工不同:前者是业务产出文件,后者是操作过程录屏。
8. 测试
- 单元测试须用
IsolatedDataRoot,断言路径落在临时数据根下。 tests/test_runtime_paths.py覆盖resolve_data_path/resolve_input_path。POLICY-DATA-PATH-001:禁止.env.example中./路径;禁止业务代码abspath(config.get(...))。
卸载技能与数据保留
宿主卸载技能只删除安装目录(如 .openclaw/skills/{slug}),不会删除 {JIANGCHANG_DATA_ROOT}/{user_id}/{skill_slug}/ 下的 SQLite、输入输出与日志。重装会复用同一用户库;schema 迁移须在 init_db() 中幂等完成(见 ../references/SCHEMA.md「表增删改与退役」)。
9. 相关文档
| 文档 | 内容 |
|---|---|
RUNTIME.md |
数据根、共享 runtime、编码 |
CONFIG.md |
.env bootstrap 与三层优先级 |
RPA.md |
rpa-artifacts / videos 存证 |
POLICY_MATRIX.md |
POLICY-DATA-PATH-001 |