Skip to content

fix: resolve model-emitted short path prefixes in tool calls#29

Open
Archelunch wants to merge 2 commits into
microsoft:mainfrom
Archelunch:fix/path-resolution
Open

fix: resolve model-emitted short path prefixes in tool calls#29
Archelunch wants to merge 2 commits into
microsoft:mainfrom
Archelunch:fix/path-resolution

Conversation

@Archelunch

@Archelunch Archelunch commented Jun 25, 2026

Copy link
Copy Markdown

Problem

My OS: MacOS

The FastContext model consistently uses the last directory component of the workspace path as a prefix in its tool calls. For example, when the workspace is /home/user/projects/myrepo, the model emits paths like /myrepo/backend/src/worker.py instead of /home/user/projects/myrepo/backend/src/worker.py.

This causes every Grep, Glob, and Read call to fail with a permission error:

Permission error: `/myrepo/backend` is not within the working directory `/home/user/projects/myrepo`

The agent receives zero useful search results, hallucinates file paths in its final answer, and the citation validator filters them all out, producing an empty <final_answer> block. This affects any workspace whose absolute path has more than one component.

Reproduction

git clone https://github.com/some/repo ~/projects/myrepo
cd ~/projects/myrepo

BASE_URL=http://your-endpoint/v1 \
MODEL=microsoft/FastContext-1.0-4B-RL \
API_KEY=dummy \
fastcontext -q "Where is the main entry point?" --max-turns 4 --citation --verbose

All tool calls fail with permission errors; the final answer is empty.

Changes

  • resolve_path() helper (agent/tool/utils.py): detects the /{cwd_name}/... short-prefix pattern and rewrites it to the full absolute path before the is_relative_to(cwd) check, with a longest-existing-suffix fallback. Returns the original path when nothing resolves, preserving the existing error behavior.
  • Applied to Grep, Glob, and Read, and to citation validation in format_citations() / get_final_answer() so short paths in the final answer pass the existence check.
  • Read: return a clear error when the path is a directory instead of attempting to open it as a file.
  • Glob: strip a path prefix from the pattern argument when the model passes a full path (e.g. /myrepo/backend/**/*.py -> backend/**/*.py).

Tests

Added tests/test_path_resolution.py covering the resolver: passthrough for in-cwd paths, short-prefix rewrite, suffix-match fallback, and unresolvable-path passthrough. All pass; existing tests are unaffected. ruff check is clean on all changed files.

Verified against

  • Models: microsoft/FastContext-1.0-4B-RL and microsoft/FastContext-1.0-4B-SFT, served via SGLang v0.5.13 (FP8, 262K context)
  • Before: empty <final_answer>, all tool calls fail with permission errors
  • After: the model finds the correct files and returns valid citations with line ranges

@Archelunch Archelunch force-pushed the fix/path-resolution branch 2 times, most recently from b9f505b to 05c3cd6 Compare June 25, 2026 13:02
The model emits paths prefixed with the last directory component of the
workspace (e.g. /myrepo/backend/main.py instead of the full absolute
path), causing every Grep, Glob, and Read call to fail the
is_relative_to(cwd) permission check. The agent then returns an empty
<final_answer> because all citations are filtered out.

- add resolve_path() helper that rewrites the short prefix to the full
  absolute path, with a longest-existing-suffix fallback
- apply it in Grep, Glob, Read, and citation validation
- Read: return a clear error when the path is a directory
- Glob: strip a path prefix from the pattern argument
- add tests/test_path_resolution.py

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@Archelunch Archelunch force-pushed the fix/path-resolution branch from 05c3cd6 to eb46dff Compare June 25, 2026 13:06
@Archelunch

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@Archelunch Archelunch marked this pull request as ready for review June 25, 2026 13:09
When the model omits <final_answer> tags, parse_citations returned a dict
instead of a list, causing format_citations to iterate the dict's string keys
and crash with 'TypeError: string indices must be integers'. Return [] so
get_final_answer produces an empty block instead of crashing.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
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