Skip to content

fix(lib): name files_from_dir entries from the directory, not from how it was spelled - #1993

Open
v0ropaev wants to merge 1 commit into
anthropics:mainfrom
v0ropaev:fix/files-from-dir-relative-root
Open

v0ropaev wants to merge 1 commit into
anthropics:mainfrom
v0ropaev:fix/files-from-dir-relative-root

Conversation

@v0ropaev

@v0ropaev v0ropaev commented Oct 6, 2026

Copy link
Copy Markdown

What was wrong

files_from_dir names each file relative to the directory's parent, so the name carries the directory itself, which is the shape the skills upload wants. examples/agents_comprehensive.py passes ("greeting/SKILL.md", ...) by hand, same thing.

A relative root has no parent to take that name from. Running it on a skill laid out as greeting/SKILL.md and greeting/scripts/run.py:

files_from_dir(skill_dir)        ['greeting/SKILL.md', 'greeting/scripts/run.py']
files_from_dir('.')              ['SKILL.md', 'scripts/run.py']
files_from_dir('..')             ['../greeting/SKILL.md', '../greeting/scripts/run.py']

. is the one that bites, since calling it from inside the skill directory is the natural thing to do in a per-skill script. The wrapper directory is gone from every name and the call still succeeds. .. is the same root cause pointing the other way, it puts a .. segment in a name that goes to the API.

What changed

The root is normalized before its parent is taken, with os.path.abspath, which is lexical and leaves symlinks alone, so a symlinked skill directory still gets named after itself rather than after its target. Path.resolve() would have renamed it.

Same change in async_files_from_dir.

How I know it works

A new tests/lib/test_files.py, covering the absolute root, ., ./, ../greeting, a trailing separator, and the async twin. The two relative-root tests fail on main and pass with the change; the absolute-root ones pass on both, which is the point, that spelling already worked.

…w it was spelled

- the names are built relative to the directory's parent, and a relative root
  has none to take a name from: files_from_dir('.') dropped the wrapper
  directory from every name, and '..' put a .. segment in them
- the same directory given as an absolute path named the files correctly, so
  the two spellings disagreed
- normalize the root first, which leaves symlinks alone
- tests for both, sync and async
@v0ropaev
v0ropaev requested a review from a team as a code owner October 6, 2026 18:01

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant