Add DATA_PATHS golden standard and resolve_data_path helpers.
All checks were successful
技能自动化发布 / release (push) Successful in 5s
All checks were successful
技能自动化发布 / release (push) Successful in 5s
Document skill-owned file layout under user data dir, extend runtime_paths with standard subdir helpers, add POLICY-DATA-PATH-001, and update CONFIG/RUNTIME cross-references. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -40,7 +40,15 @@ STEP_DELAY_MAX=5.0
|
||||
HUMAN_WAIT_TIMEOUT=180 # 滑块/验证码/2FA 等人工超时(秒)
|
||||
```
|
||||
|
||||
**业务专属配置必须带技能前缀**(如 `DEMO_XXX`、`MY_SKILL_XXX`),**不要污染全局命名空间**(禁止 `SCRAPE_1688_*`、`RECEIVE_ORDER_*` 等跨技能前缀写入模板)。
|
||||
**业务专属配置必须带技能前缀**(如 `DEMO_XXX`、`MY_SKILL_XXX`、`SKILL_DOWNLOAD_DIR`),**不要污染全局命名空间**(禁止 `SCRAPE_1688_*`、`RECEIVE_ORDER_*` 等跨技能前缀写入模板)。
|
||||
|
||||
### 数据目录子路径(下载 / 导入 / 导出)
|
||||
|
||||
技能**自己写入**的文件默认在 `{JIANGCHANG_DATA_ROOT}/{USER_ID}/{slug}/` 下标准子目录(`downloads/`、`imports/`、`exports/` 等)。须通过 `util.runtime_paths.resolve_data_path()` 或 `get_*_dir()` 解析,**禁止** `os.path.abspath(config.get(...))` 相对 CWD。
|
||||
|
||||
- 权威说明:[`DATA_PATHS.md`](DATA_PATHS.md)
|
||||
- `.env.example` 中路径类配置**留空即用默认**;若写相对路径,必须相对 **skill 数据目录**,**禁止** `./outputs/...` 这类相对 workspace 的写法
|
||||
- 可选 env:`SKILL_DOWNLOAD_DIR`、`SKILL_IMPORT_DIR`、`SKILL_EXPORT_DIR` 等(见 DATA_PATHS.md)
|
||||
|
||||
### 录屏开关(`OPENCLAW_RECORD_VIDEO`)
|
||||
|
||||
@@ -91,7 +99,7 @@ config.get_float("STEP_DELAY_MIN", 1.0)
|
||||
## health / config-path
|
||||
|
||||
- **`health`**:输出 `collect_runtime_diagnostics` 字段(`platform_kit_version_ok`、`ffmpeg_path` 等),**不打印敏感值**;补充 `env_path` / `env_exists` / `example_path`。
|
||||
- **`config-path`**:输出 JSON,包含 `skill`、`env_path`(用户数据目录 `.env`)、`example_path`(仓库 `.env.example` 绝对路径),便于排查落盘位置。
|
||||
- **`config-path`**:输出 JSON,包含 `skill`、`env_path`(用户数据目录 `.env`)、`example_path`(仓库 `.env.example` 绝对路径),便于排查落盘位置;业务 skill 建议附加 `list_resolved_data_paths()` 中的子目录路径(见 [`DATA_PATHS.md`](DATA_PATHS.md))。
|
||||
|
||||
## doctor / setup 命令(可选)
|
||||
|
||||
@@ -104,4 +112,5 @@ config.get_float("STEP_DELAY_MIN", 1.0)
|
||||
|
||||
- `RPA.md` — 三端 RPA 标准与各开关含义
|
||||
- `ADAPTER.md` — `OPENCLAW_TEST_TARGET` 四档模式
|
||||
- `RUNTIME.md` — `JIANGCHANG_*` 环境变量与数据目录约定
|
||||
- `RUNTIME.md` — `JIANGCHANG_DATA_ROOT` 与数据根约定
|
||||
- `DATA_PATHS.md` — 下载/导入/导出等子目录与 `resolve_data_path` 规范
|
||||
|
||||
160
development/DATA_PATHS.md
Normal file
160
development/DATA_PATHS.md
Normal file
@@ -0,0 +1,160 @@
|
||||
# 用户数据目录与文件路径黄金标准
|
||||
|
||||
> 本文是 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 |
|
||||
@@ -27,6 +27,7 @@
|
||||
| POLICY-CONTROL-001 | 不得存在 `scripts/util/progress.py` 或自建 stdout 进度模块 | development/LOGGING.md §2.5;development/RPA.md §0.1 | hard | 文件不存在检查 | `tests/test_development_policy_guard.py::TestPolicyControl001` |
|
||||
| POLICY-CONTROL-002 | `task_service.py` 须使用 `job_context(` 与 `finish(` | development/LOGGING.md §2.5、§7 | hard | 扫描 `scripts/service/task_service.py` | `tests/test_development_policy_guard.py::TestPolicyControl002` |
|
||||
| POLICY-CONTROL-003 | `scripts/service/*.py` 不得裸 `asyncio.sleep`(RPA 等待须 `interruptible_sleep`) | development/RPA.md §0.1 | hard | 扫描 service 层 Python | `tests/test_development_policy_guard.py::TestPolicyControl003` |
|
||||
| POLICY-DATA-PATH-001 | 技能拥有路径须经 `resolve_data_path` / `get_*_dir`;`.env.example` 禁止 `./` CWD 相对路径;业务代码禁止 `abspath(config.get(...))` | development/DATA_PATHS.md | hard | 扫描 `.env.example` 与 `scripts/**/*.py` | `tests/test_development_policy_guard.py::TestPolicyDataPath001` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
6. [`ADAPTER.md`](ADAPTER.md) — 涉及外部系统对接时
|
||||
7. [`RPA.md`](RPA.md) — 涉及浏览器 / 桌面 / 手机自动化时
|
||||
8. [`CONFIG.md`](CONFIG.md) — `.env` 规范与 bootstrap 机制
|
||||
9. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
|
||||
9. [`DATA_PATHS.md`](DATA_PATHS.md) — 下载/导入/导出等本地文件路径标准(涉及文件读写时必读)
|
||||
10. [`RUNTIME.md`](RUNTIME.md) — 共享 runtime、数据路径、发布打包与编码约定
|
||||
|
||||
脚手架与 Git 防串库:[`../tools/README.md`](../tools/README.md)(`scaffold_skill.ps1`)。
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ RPA 录屏成片(`RpaVideoSession`)、ffmpeg 路径、背景音乐探测均
|
||||
{...}/{skill_slug}.db
|
||||
```
|
||||
|
||||
**业务文件(下载、导入、导出、缓存等)** 须落在上述数据目录的标准子目录下,**不得**相对 workspace/CWD 写入。完整子目录树、env 覆盖规则、`resolve_data_path()` 用法见 **[`DATA_PATHS.md`](DATA_PATHS.md)**。
|
||||
|
||||
- 业务表使用英文 snake_case;中文表名/字段名写入 `_jiangchang_tables` / `_jiangchang_columns`(见 `references/SCHEMA.md`)。
|
||||
- 界面字段顺序由 `CREATE TABLE` 列定义顺序决定,**不要**维护 `display_order` 来调整顺序。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user