# 用户数据目录与文件路径黄金标准 > 本文是 skill **读写本地文件** 的权威约定。凡涉及下载、导入、导出、缓存、RPA 存证等路径,复制模板后须遵守本文;Agent 实现业务 skill 时也应先读本文。 --- ## 1. 根目录 所有技能持久化数据(配置、数据库、业务文件)默认落在: ```text {JIANGCHANG_DATA_ROOT}/{JIANGCHANG_USER_ID}/{skill_slug}/ ``` 示例: ```text D:\jiangchang-data\12500\download-video-baidu-haokan\ ``` 实现:`util.runtime_paths.get_skill_data_dir()`。 **禁止**把技能自己写入的文件落到: - Agent / 宿主 **workspace**(进程 CWD) - 技能安装目录(含 `.openclaw/skills/...`) - 未在本文声明的任意相对 CWD 路径 --- ## 2. 标准子目录树 | 子目录 | 用途 | 默认 helper | |--------|------|-------------| | `downloads/` | 从外部拉取的原始文件(视频、回单、PDF…) | `get_downloads_dir()` | | `imports/` | 用户/Agent 放入的待处理清单(urls.txt、batch.json、CSV) | `get_imports_dir()` | | `exports/` | 导出给用户的结果(xlsx/csv/json) | `get_exports_dir()` | | `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()` | | `.env` | 用户配置 | `config.get_env_file_path()` | 复制后若业务不需要某目录,可不创建;**但一旦写入该类文件,必须走对应 helper**。 --- ## 3. 两类路径 ### A. 技能拥有(skill-owned) 技能**创建或更新**的文件:下载结果、导出报表、失败截图、队列 sidecar 等。 - **默认**必须在 `{skill_data_dir}/<子目录>/` 下。 - **必须**通过 `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}/imports/<相对路径>`,**不**相对 workspace/CWD。 --- ## 4. 配置项(`.env`) 可选覆盖项(**留空则用默认子目录**): ```ini # ── 数据目录子路径(见 development/DATA_PATHS.md)── # 相对路径相对于 {JIANGCHANG_DATA_ROOT}/{USER_ID}/{slug}/,不是 workspace # SKILL_DOWNLOAD_DIR=downloads/videos # SKILL_IMPORT_DIR=imports # SKILL_EXPORT_DIR=exports # SKILL_UPLOAD_DIR=uploads # SKILL_CACHE_DIR=cache # SKILL_TEMP_DIR=temp ``` | 规则 | 说明 | |------|------| | 未配置 | `{skill_data_dir}/{default_subdir}` | | 相对值 `downloads/videos` | `{skill_data_dir}/downloads/videos` | | 绝对值 `D:\nas\exports` | 高级用户/NAS 挂载,原样使用 | | **禁止** `./outputs/...` | 会随 CWD 漂移,不得作为 `.env.example` 活跃配置行 | 业务专属路径 env key 须带 **`SKILL_` 前缀**(或技能 slug 前缀),避免污染全局命名空间。 --- ## 5. 代码用法 ```python from util.runtime_paths import ( get_downloads_dir, get_imports_dir, resolve_data_path, resolve_input_path, list_resolved_data_paths, ) # 下载保存(A 类) dest = os.path.join(get_downloads_dir(), f"{vid}.mp4") # 或带 env 覆盖 out_dir = resolve_data_path("SKILL_DOWNLOAD_DIR", "downloads") # CLI -i urls.txt(B 类,相对路径 → imports/) manifest = resolve_input_path(args.input_path) # health 诊断 paths = list_resolved_data_paths() ``` **反模式(禁止):** ```python # ❌ 相对 CWD,Agent 从 workspace 执行时会写错盘 os.path.abspath(config.get("DOWNLOAD_OUTPUT_DIR")) # ❌ .env.example 里写 ./outputs/videos DOWNLOAD_OUTPUT_DIR=./outputs/videos ``` --- ## 6. health / config-path `health` 或 `config-path` 建议输出 `list_resolved_data_paths()` 中的路径,便于排查「文件写到哪里去了」。展示路径须与 `run` 实际使用的一致。 --- ## 7. 与 RPA 存证的关系 - 失败截图、录屏中间文件:`rpa-artifacts/{batch_id}/`(见 [`RPA.md`](RPA.md) §5.1) - 录屏成片:`videos/`(见 [`RPA.md`](RPA.md) §5.3) 业务 `downloads/` 与 RPA `videos/` **分工不同**:前者是业务产出文件,后者是操作过程录屏。 --- ## 8. 测试 - 单元测试须用 `IsolatedDataRoot`,断言路径落在临时数据根下。 - `tests/test_runtime_paths.py` 覆盖 `resolve_data_path` / `resolve_input_path`。 - `POLICY-DATA-PATH-001`:禁止 `.env.example` 中 `./` 路径;禁止业务代码 `abspath(config.get(...))`。 --- ## 9. 相关文档 | 文档 | 内容 | |------|------| | [`RUNTIME.md`](RUNTIME.md) | 数据根、共享 runtime、编码 | | [`CONFIG.md`](CONFIG.md) | `.env` bootstrap 与三层优先级 | | [`RPA.md`](RPA.md) | rpa-artifacts / videos 存证 | | [`POLICY_MATRIX.md`](POLICY_MATRIX.md) | POLICY-DATA-PATH-001 |