Skip to content

fix(skills): use forward slashes in LocalSkillSource.listResources - #1542

Open
innoprej wants to merge 1 commit into
google:mainfrom
innoprej:fix/local-skill-source-forward-slashes
Open

innoprej wants to merge 1 commit into
google:mainfrom
innoprej:fix/local-skill-source-forward-slashes

Conversation

@innoprej

@innoprej innoprej commented Sep 24, 2026 •

Copy link
Copy Markdown

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

Problem:

LocalSkillSource.listResources turns each resource path, relative to the skill directory, into a string with Path.toString(), which uses the platform separator. On Windows it returns assets\file1.txt, while ClassPathSkillSource and InMemorySkillSource return assets/file1.txt for the same skill layout, and LoadSkillResourceTool rejects any path that does not start with assets/, references/ or scripts/. LocalSkillSourceTest.testListResources fails on Windows:

[ERROR]   LocalSkillSourceTest.testListResources:96 value of      : blockingGet()
missing (2)   : assets/file1.txt, assets/subdir/file2.txt
unexpected (2): assets\file1.txt, assets\subdir\file2.txt

The existing test uses the host filesystem. CI runs on Ubuntu, where Path.toString() already uses /, so that test misses the Windows bug. The code has been this way since LocalSkillSource was added in 1.3.0.

Solution:

Join the relative path's name elements with / using a static PATH_JOINER (Joiner.on('/')). A Path iterates over its name elements. This matches the other two implementations and adk-python, which made the same change for directory-loaded skill resources in google/adk-python@bc2c97c (str(relative_path) → relative_path.as_posix()). The returned Windows paths now satisfy LoadSkillResourceTool's prefix check.

Add Jimfs 1.3.2 as a test-scoped dependency and a regression test using Configuration.windows(). It checks direct and nested resource paths and reads each returned path through loadResource, so the Windows separator bug is testable on Ubuntu too.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally in the core module.

Windows 11, Microsoft OpenJDK 17.0.19, Maven 4.0.0-rc-3 via mvnw. For the regression check, the new test and Jimfs dependency were kept while only LocalSkillSource.java was restored to the original implementation from 4092a1fa.

Run Original implementation This change
Windows Maven, new Jimfs test only 1 test, 1 failure: backslash-separated paths Covered by the full class below
Windows Maven, LocalSkillSourceTest Existing test failed on Windows before the original fix 22 tests, 0 failures in both default-test and basic
Ubuntu 24.04.3 under WSL, JRE 17.0.20.1+1, JUnitCore LocalSkillSourceTest 22 tests, only the new Jimfs test fails 22 tests, 0 failures
Windows Maven, -pl core test Not rerun in full BUILD SUCCESS; default-test and basic each run 1,884 tests, 24 skipped, 0 failures and 0 errors

The Ubuntu check ran the same compiled test class on a Linux JVM with JUnitCore. It was not an Ubuntu Maven build or an upstream CI run. macOS was not run.

The remaining core Surefire executions ran 2, 24 (1 skipped), 1, and 0 tests, with no failures or errors. The existing zero-test apigee-llm-proxy-url execution is tracked separately in #1557. google-java-format checked 352 files and reformatted none.

Manual End-to-End (E2E) Tests:

No application-level E2E test was run. The new unit test covers the listResources → loadResource round trip using a Windows filesystem on both Windows and Ubuntu.

Checklist

  • I have read the CONTRIBUTING.md document.
  • My pull request contains a single commit.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing core unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules. (Not applicable.)

Additional context

Jimfs is limited to test scope. The resolved test classpath retains the project's existing Guava 33.0.0-jre version.

@hemasekhar-p hemasekhar-p self-assigned this Sep 24, 2026
@hemasekhar-p

Copy link
Copy Markdown
Contributor

Hi @innoprej, thank you for your contribution! We appreciate you taking the time to submit this pull request. Currently this PR is under review by our team, we will keep you posted if any additional information is required. thank you.

@MiloszSobczyk MiloszSobczyk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, thank you for your contribution.

One suggestion: the bug got through because CI runs only on Ubuntu, and this PR still adds no test that fails there. The Python fix added a test that simulates Windows paths. In Java, adding com.google.jimfs:jimfs as a test dependency would allow a test on jimfs.newFileSystem(Configuration.windows()). LocalSkillSource is already written to support non-default providers (see the comment in validatePathWithinBase), so that test would fail on main even on Linux.

Comment thread core/src/main/java/com/google/adk/skills/LocalSkillSource.java Outdated
@innoprej
innoprej force-pushed the fix/local-skill-source-forward-slashes branch from 8130cd0 to 101962e Compare September 29, 2026 11:31
@innoprej

Copy link
Copy Markdown
Author

Thanks for the suggestion in your review. I added Jimfs 1.3.2 as a test-scoped dependency and a test using Configuration.windows(). It checks both direct and nested resource paths and reads each returned path through loadResource.

With the original Path.toString() implementation, the new test fails with backslash-separated paths. With the fix, all 22 tests in LocalSkillSourceTest pass on Windows. I also ran the same compiled test class with JUnitCore on Ubuntu 24.04.3 under WSL: the original implementation fails only the new Windows-filesystem test, and the fixed implementation passes all 22 tests.

@MiloszSobczyk

Copy link
Copy Markdown
Member

Helllo, could you please merge the newest changes that were introduced in the code? Afterwards, please ensure that the code still works correctly.

LocalSkillSource.listResources turned each relative resource path into
a string with Path.toString(), which uses the platform separator. On
Windows it returned assets\file1.txt, while ClassPathSkillSource and
InMemorySkillSource return assets/file1.txt, and LoadSkillResourceTool
only accepts paths that start with assets/, references/ or scripts/.
LocalSkillSourceTest.testListResources fails on Windows:

  expected: [assets/file1.txt, assets/subdir/file2.txt]
  but was : [assets\file1.txt, assets\subdir\file2.txt]

Join the path's name elements with '/' instead, as adk-python now does
for skill resources loaded from a directory. Nothing changes on Linux
and macOS, where Path.toString() already uses '/'. CI runs on Ubuntu,
so it could not catch this.

- Reuse a static PATH_JOINER for each relative resource path.
- Add a test-scoped Jimfs Windows filesystem regression test that also
  reads the listed resources, so Ubuntu CI covers the separator bug.
@innoprej
innoprej force-pushed the fix/local-skill-source-forward-slashes branch from 101962e to 2a2ab5c Compare September 30, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LocalSkillSource.listResources returns backslash-separated paths on Windows

3 participants