fix(fs): mark directory matches in glob results with a trailing slash - #4466
Merged
Conversation
`glob` returns a flat list of uri strings, dropping the `is_dir` flag that AGFS already provides. Callers had no way to tell a directory match from a file match, so web-studio rendered every glob hit with a file icon. Keep `matches` as `list[str]` and append `/` to directory uris, matching the convention `normalize_dir_uri` and the tree renderer already use. ACL lookups still use the bare uri, so access decisions are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C65Cb79Dvr5zLD6ib1T9Ew
1 task
qin-ctx
approved these changes
Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
起因
web-studio 的搜索面板加了 glob 模式后,glob 命中的目录全部被渲染成文件图标。查下来不是前端判断错了,而是前端根本拿不到这个信息。
问题性质
AGFS 的 glob entry 本身是带
is_dir的(crates/ragfs/src/core/filesystem.rs:573),但_ops.py的glob()把结果拍平成matches: list[str]时把这个 flag 丢了。返回的目录 uri 和文件 uri 长得一模一样:调用方没有任何办法区分这两条。对比
fs/ls—— 它给每个 entry 一个显式的isDir字段,所以一直是对的;只有 glob 这条路把类型信息扔了。这不是疏漏,
test_glob_keeps_directory_matches明确锁了「目录不带尾斜杠」这个行为,所以本 PR 一并更新该断言。修改方式
matches保持list[str]不变,只给目录 uri 补一个尾斜杠:尾斜杠是 OV 里已有的目录约定 ——
normalize_dir_uri和 tree 渲染器(mcp_endpoint.py里目录打印成name/)都是这么表达的,这里只是让 glob 跟上。实现上新增一个模块级
_glob_match_uri(entry_uri, is_dir),在 append 时决定要不要补斜杠。ACL 查询仍然用不带斜杠的原始 uri(page_matches改成(acl_uri, match_uri)二元组),所以权限判定逻辑逐字节不变。待评审决策点
考虑过另一个方案:把
matches改成[{uri, isDir}],语义上和fs/ls彻底对齐、最干净。但那会破坏 MCP glob 工具、CLI、web-studiofetchGlob和 e2e 测试的全部调用方,代价明显不成比例。选了破坏面最小的尾斜杠方案。如果 maintainer 更倾向结构化返回,可以在这个 PR 上改。未改动
matches的类型(仍是list[str])、count字段uri.endsWith('/')的判断本来就写好了,服务端修正后自动生效,无需改动验证
tests/storage/test_viking_fs_glob.py11 passed。更新了test_glob_keeps_directory_matches的断言;新增test_glob_marks_directories_but_not_files,覆盖is_dir: True/is_dir: False/is_dir字段缺失三种 entry 混排。tests/storage/全量对照:clean main 是 33 failed / 392 passed,本 PR 是 33 failed / 393 passed —— 同样的 33 个预先存在的失败(volcengine_clients、vectordb_adaptor 等,与本改动无关),多出的 1 个 pass 是新增用例。零回归。image_rewrite.py、parsers/markdown.py、semantic_processor.py用的都是**/*.md,只匹配文件,拿不到目录;resource_memory_link_service.py和mcp_endpoint.py:1281消费的是 grep 的 matches 不是 glob 的。均不受影响。🤖 Generated with Claude Code
https://claude.ai/code/session_01C65Cb79Dvr5zLD6ib1T9Ew