feat(files): 文件面板根目录隐藏定时/渠道系统工作目录(bump 0.55.2)
- /v1/files 根层与 /v1/folders 候选过滤 scheduled-*/wechat-*/wecom-* 工作目录 - 判定走 DB 回查(_system_wd_names:scheduled_job_id / channel),孤儿目录不隐藏 - 仅列表降噪非权限拦截:带 path 访问照常,点任务跳入目录的前端行为不变 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9e59cf9e44
commit
3ef472c112
|
|
@ -5,6 +5,10 @@
|
|||
> 所以不是每个版本号都有条目。条目格式 `## <版本> — <日期>`,新条目加在最上面。
|
||||
> 工程口径的完整记录见 `PROGRESS.md` / git log。
|
||||
|
||||
## 0.55.2 — 2026-07-10
|
||||
|
||||
- 文件面板根目录不再显示定时任务 / 微信对话自动生成的工作文件夹(如 `scheduled-xxxx`),减少干扰;点开对应定时任务或微信对话,右侧文件面板照常查看其中的文件。
|
||||
|
||||
## 0.55.1 — 2026-07-10
|
||||
|
||||
- 个人存储空间从 5GB 提升到 20GB(上传文件 + 生成的文档 / PPT 等产物合计)。
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
### 2026-07
|
||||
|
||||
- **07-10 / 0.55.2**:文件面板根目录隐藏系统工作目录:`/v1/files`(仅根层)与 `/v1/folders`(新建任务目录候选)过滤定时任务执行目录 / 渠道镜像对话目录(`web/app.py::_system_wd_names`,DB 回查 `scheduled_job_id`/`channel` 判定而非硬编码名字前缀 —— 孤儿目录(task 已删)无任务入口,刻意留在根目录可见)。只是列表降噪非权限拦截:带 path 直接访问照常放行,点定时任务运行历史 / 微信卡片时文件面板自动跳入该目录不受影响(chat.js 既有逻辑,前端零改动)。
|
||||
- **07-10 / 0.55.1**:per-user 磁盘配额 5GB→20GB(`config/agent.yaml quotas.disk_bytes_per_user`;RUN 故障兜底行、CHANGELOG 同步)。仍是应用层软配额,OS 层 xfs prjquota 兜底照旧留待外部用户开放前(§7.5 #4)。
|
||||
- **07-09 / 0.55.0**:**用户版更新日志**(点版本号看"更新了什么"):新增仓库根 `CHANGELOG.md`(面向用户口径,只记可感知变化,回填至 0.30;与工程笔记 PROGRESS 分离——PROGRESS 满是内部模块/env/部署细节不宜外露);`GET /v1/changelog`(公开无鉴权,`## <版本> — <日期>` 正则切段,mtime 缓存热改即生效,无 DB 零 migration);前端右栏底部版本号变可点 → 更新日志弹层(`changelog.js`,复用 marked+purify 渲染),localStorage 记 last-seen 版本、与 /healthz 版本不一致时版本号旁亮红点、打开即清(公测用户发现更新的唯一入口)。CLAUDE.md 加维护约定:bump 版本若用户可感知顺手补 CHANGELOG 条目。
|
||||
- **07-09 / 0.54.2**:清理 `deepseek-chat/reasoner` 下线残留描述(旧模型 2026-07 已下线):删 `config/models/deepseek_v4.yaml` 里"可退回 deepseek-chat"的误导注释(照做会打不通),DESIGN 附录迁移提醒改为已完成陈述。全库 grep 确认代码/配置本体无旧 model id 引用。
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# zcbot 版本号单一事实源:web/app.py 的 FastAPI version、/healthz 返回、前端展示都引这里。
|
||||
# 改版本只动这一行。
|
||||
__version__ = "0.55.1"
|
||||
__version__ = "0.55.2"
|
||||
|
|
|
|||
36
web/app.py
36
web/app.py
|
|
@ -333,6 +333,29 @@ def _enumerate_files(root: Path, current: Path) -> tuple[list[dict], list[dict],
|
|||
return entries, crumbs, exists
|
||||
|
||||
|
||||
def _system_wd_names(user_id: UUID) -> set[str]:
|
||||
"""有任务入口的系统工作目录末段名(定时任务执行目录 + 渠道镜像对话目录)。
|
||||
|
||||
这些目录点开对应入口(定时任务运行历史 / 渠道固定卡片)时文件面板会自动跳进去,
|
||||
根目录列表隐藏它们只是降噪,不是权限拦截 —— 带 path 直接访问照常放行(任务跳转
|
||||
依赖这条路)。孤儿目录(task 已软删 / job 物理删后的漏网)没有别的 UI 入口,
|
||||
刻意不隐藏,留在根目录可见。
|
||||
"""
|
||||
with session_scope() as s:
|
||||
rows = s.execute(
|
||||
select(Task.working_dir).where(
|
||||
Task.user_id == user_id,
|
||||
Task.deleted_at.is_(None),
|
||||
Task.working_dir.isnot(None),
|
||||
or_(
|
||||
Task.scheduled_job_id.isnot(None),
|
||||
func.coalesce(Task.channel, "web").in_(CHANNEL_MIRROR_KINDS),
|
||||
),
|
||||
)
|
||||
).all()
|
||||
return {wd.rstrip("/").rsplit("/", 1)[-1] for (wd,) in rows if wd}
|
||||
|
||||
|
||||
def _validate_transfer(
|
||||
root: Path, paths: list[str], dest_dir: str,
|
||||
) -> tuple[list[Path], Path]:
|
||||
|
|
@ -2232,6 +2255,9 @@ def create_app() -> FastAPI:
|
|||
for p in sorted(root.iterdir(), key=lambda x: x.name.lower()):
|
||||
if p.is_dir() and not p.name.startswith("."):
|
||||
folder_names.append(p.name)
|
||||
# 系统工作目录(定时/渠道)不进候选 —— 新任务不该落到它们里面
|
||||
hidden = _system_wd_names(user_id) if folder_names else set()
|
||||
folder_names = [n for n in folder_names if n not in hidden]
|
||||
|
||||
folders: list[dict] = []
|
||||
if folder_names:
|
||||
|
|
@ -3185,11 +3211,19 @@ def create_app() -> FastAPI:
|
|||
user_id: UUID = Depends(require_user),
|
||||
):
|
||||
"""列 user_root 下子目录条目 + 面包屑。`path` 留空 → user_root;
|
||||
`../` / 绝对 → 400。dotfile(`.memory/` 等)一律隐藏。
|
||||
`../` / 绝对 → 400。dotfile(`.memory/` 等)一律隐藏;根目录层再隐藏
|
||||
系统工作目录(定时任务 / 渠道对话,见 _system_wd_names)。
|
||||
"""
|
||||
root = _load_user_root(user_id)
|
||||
current = _safe_join(root, path)
|
||||
entries, crumbs, exists = _enumerate_files(root, current)
|
||||
if not _rel_to(root, current):
|
||||
hidden = _system_wd_names(user_id)
|
||||
if hidden:
|
||||
entries = [
|
||||
e for e in entries
|
||||
if not (e["is_dir"] and e["name"] in hidden)
|
||||
]
|
||||
return {
|
||||
"root": _norm_path(str(root)),
|
||||
"current": _rel_to(root, current),
|
||||
|
|
|
|||
Loading…
Reference in New Issue