Conversation
|
先撤回,内容补全后会重新提交。 |
There was a problem hiding this comment.
Pull request overview
该 PR 旨在修复多工作区场景下看板读取了错误的数据目录(例如只显示 DEMO/旧数据),通过自动探测并选择正确的任务数据源目录,让看板任务与日志可见。
Changes:
- 增加任务数据目录候选探测与评分逻辑,并在服务周期内缓存选中的数据目录
- 让
load_tasks/save_tasks、/healthz、/api/live-status基于所选任务数据目录读写 - 刷新
live_status.json时根据所选数据目录选择对应的refresh_live_data.py
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def get_task_data_dir(): | ||
| """自动选择当前任务数据目录,并缓存结果以保持一次服务期内稳定。""" | ||
| global _ACTIVE_TASK_DATA_DIR | ||
| if _ACTIVE_TASK_DATA_DIR and _ACTIVE_TASK_DATA_DIR.is_dir(): | ||
| return _ACTIVE_TASK_DATA_DIR | ||
|
|
||
| best_dir = DATA | ||
| best_score = (-1, -1, -1, -1) | ||
| for d in _iter_task_data_dirs(): | ||
| tf = d / 'tasks_source.json' | ||
| if not tf.exists(): | ||
| continue | ||
| score = _task_source_score(tf) | ||
| if score > best_score: | ||
| best_score = score | ||
| best_dir = d | ||
|
|
||
| _ACTIVE_TASK_DATA_DIR = best_dir | ||
| log.info(f'任务数据源: {_ACTIVE_TASK_DATA_DIR}') | ||
| return _ACTIVE_TASK_DATA_DIR |
There was a problem hiding this comment.
get_task_data_dir() 会在“当前没有任何候选目录包含 tasks_source.json”时依然把 _ACTIVE_TASK_DATA_DIR 缓存为 DATA(best_dir 初始值),之后即使 workspace/data 下生成了 tasks_source.json 也不会重新探测(因为缓存目录 is_dir() 仍为 True)。建议只在找到有效 tasks_source.json 时才缓存,或增加重探测条件/TTL(例如当选中的 tasks_source.json 不存在时重新选择)。
| dirs = [DATA] | ||
| oclaw_home = pathlib.Path.home() / '.openclaw' | ||
| for p in sorted(oclaw_home.glob('workspace-*/data')): | ||
| if p.is_dir(): | ||
| dirs.append(p) |
There was a problem hiding this comment.
_iter_task_data_dirs() 的注释写的是“优先 workspace,其次本地 data”,但当前实现是先把 DATA 放进列表再 append workspace。由于 get_task_data_dir() 在评分相同的情况下不会覆盖 best_dir(使用的是 > 而不是 >=),这会导致同分时始终偏向本地 DATA,与注释/预期不一致。建议调整候选目录顺序(workspace 在前)或在评分相同时显式优先 workspace。
| dirs = [DATA] | |
| oclaw_home = pathlib.Path.home() / '.openclaw' | |
| for p in sorted(oclaw_home.glob('workspace-*/data')): | |
| if p.is_dir(): | |
| dirs.append(p) | |
| dirs = [] | |
| oclaw_home = pathlib.Path.home() / '.openclaw' | |
| for p in sorted(oclaw_home.glob('workspace-*/data')): | |
| if p.is_dir(): | |
| dirs.append(p) | |
| dirs.append(DATA) |
| tasks = [] | ||
| non_demo = 0 | ||
| for t in tasks: | ||
| tid = str((t or {}).get('id', '')) |
There was a problem hiding this comment.
_task_source_score() 遍历 tasks 时假设每个元素都是 dict:(t or {}).get(...) 在 t 为 str/int 等非 dict 时会抛 AttributeError,进而导致 get_task_data_dir()/healthz/live-status 等接口异常。建议在循环内先判断 t 是否为 dict(或使用 try/except / getattr 兜底),保证异常/脏数据不会把服务打挂。
| tid = str((t or {}).get('id', '')) | |
| if not isinstance(t, dict): | |
| continue | |
| tid = str(t.get('id', '')) |
| script = task_data_dir.parent / 'scripts' / 'refresh_live_data.py' | ||
| if not script.exists(): | ||
| script = SCRIPTS / 'refresh_live_data.py' | ||
|
|
||
| def _refresh(): | ||
| try: | ||
| subprocess.run(['python3', str(SCRIPTS / 'refresh_live_data.py')], timeout=30) | ||
| subprocess.run(['python3', str(script)], timeout=30) |
There was a problem hiding this comment.
_refresh_live_data_async() 在 workspace 数据目录未包含 scripts/refresh_live_data.py 时会 fallback 到项目级 SCRIPTS/refresh_live_data.py;但该脚本内部把 DATA 固定为“脚本所在仓库的 data/”,会把 live_status.json 写到项目 data 而不是已选中的 task_data_dir,导致看板读取的 live_status.json 仍不可见/不同步。建议:不要对 workspace 场景 fallback 到项目脚本;或给脚本增加 data_dir 参数/环境变量并在此处传入,确保生成文件落在 task_data_dir。
| elif p == '/api/live-status': | ||
| self.send_json(read_json(DATA / 'live_status.json')) | ||
| task_data_dir = get_task_data_dir() | ||
| self.send_json(read_json(task_data_dir / 'live_status.json')) | ||
| elif p == '/api/agent-config': | ||
| self.send_json(read_json(DATA / 'agent_config.json')) |
There was a problem hiding this comment.
PR 描述中提到“统一 /healthz /api/live-status /api/agent-config 使用同一数据源”,但当前 diff 只把 /healthz 与 /api/live-status 切到 get_task_data_dir();/api/agent-config(以及后续 model-change-log/last-result 等)仍固定读取 DATA。若这些文件也可能落在 workspace data 下,会继续出现数据源不一致。建议确认需求后要么同步改为使用 task_data_dir,要么在 PR 描述中澄清哪些文件仍然固定在 DATA。
| oclaw_home = pathlib.Path.home() / '.openclaw' | ||
| for p in sorted(oclaw_home.glob('workspace-*/data')): | ||
| if p.is_dir(): | ||
| dirs.append(p) | ||
| return dirs | ||
|
|
||
|
|
There was a problem hiding this comment.
这里重新定义了 oclaw_home = pathlib.Path.home() / '.openclaw',而文件顶部已定义常量 OCLAW_HOME。建议直接复用 OCLAW_HOME,避免路径来源分叉(也方便测试/patch)。
| oclaw_home = pathlib.Path.home() / '.openclaw' | |
| for p in sorted(oclaw_home.glob('workspace-*/data')): | |
| if p.is_dir(): | |
| dirs.append(p) | |
| return dirs | |
| for p in sorted(OCLAW_HOME.glob('workspace-*/data')): | |
| if p.is_dir(): | |
| dirs.append(p) | |
| return dirs |
此 PR 已撤回,不再维护。\n\n请改看新的 PR:#117\nhttps://github.com//pull/117\n\n撤回原因:首次提交正文不完整,已在 #117 重新提交完整内容。