Skip to content

🤖 refactor: make path the canonical field for file tools#2305

Merged
ammario merged 9 commits intomainfrom
fix/file-path-alias-normalization
Feb 11, 2026
Merged

🤖 refactor: make path the canonical field for file tools#2305
ammario merged 9 commits intomainfrom
fix/file-path-alias-normalization

Conversation

@ammar-agent
Copy link
Collaborator

@ammar-agent ammar-agent commented Feb 10, 2026

Summary

Observed models attempt { path: "..." } for file tools and fail until the preprocessor rewrites it — an unnecessary round-trip stutter. Beyond the empirical issue, file_path is also just bad API design: the tool is already namespaced as file_read / file_edit_*, so the file_ prefix on the parameter is redundant. path is shorter, natural, and what models default to.

This PR makes path the canonical schema field. Legacy file_path is accepted via preprocessor for backward compat with older transcripts.

Implementation

  • Schema: field file_pathpath in all 4 file tool Zod schemas; inverted preprocessor
  • Handlers: args.file_pathargs.path (types auto-propagate via z.infer<>)
  • Consumers: new shared extractToolFilePath() utility replaces 5 duplicated inline implementations; Zod preprocessor delegates to it too
  • Hook env vars: MUX_TOOL_INPUT_PATH is canonical; MUX_TOOL_INPUT_FILE_PATH emitted as legacy alias via LEGACY_ENV_ALIASES table
  • Auto-gen: docs/hooks/tools.mdx regenerated
  • Tests/Storybook: mechanical renames across ~20 files

Generated with mux • Model: anthropic:claude-opus-4-6 • Thinking: xhigh • Cost: $17.91

Agents frequently emit { path: ... } instead of { file_path: ... } for
file tools, causing avoidable tool-call validation failures and retries.

Schema changes:
- Add normalizeFilePathAlias preprocess to file_read, file_edit_replace_string,
  file_edit_replace_lines, and file_edit_insert schemas
- Canonical file_path always wins; path is only used as fallback
- Alias field is dropped from parsed output to keep stored args canonical

Consumer hardening (for older transcripts with raw path):
- FileEditToolCall.tsx: check path fallback for display
- toolFormatters.ts: extractFilePathArg helper with multi-key fallback
- extractEditedFiles.ts: extractFilePath helper with path fallback
- tokenStatsCalculator.ts: extractFilePathValue with path fallback

Tests:
- 16 new parameterized schema tests (alias acceptance, canonical preference,
  invalid file_path rejection, missing both keys)
- 2 new legacy path alias tests for extractEditedFiles
The z.preprocess normalization handles the alias silently — no need to
mention it in model-facing .describe() strings or leak it into generated
docs.
Make `path` the canonical schema field for file tools (file_read,
file_edit_insert, file_edit_replace_string, file_edit_replace_lines).
This matches what models naturally emit and what JSON schema shows them.

- Rename FILE_EDIT_FILE_PATH constant → FILE_TOOL_PATH
- Invert normalizer: legacy file_path → canonical path
- Update all 4 handler files to use args.path
- Update all 5 consumer files to check path first, file_path fallback
- Env var changes from MUX_TOOL_INPUT_FILE_PATH → MUX_TOOL_INPUT_PATH
Mechanical rename of file_path → path in tool input objects across:
- toolDefinitions.test.ts (inverted alias tests)
- file_read/edit test files (~30 occurrences)
- code_execution.integration.test.ts
- extractEditedFiles, tokenStatsCalculator, transcriptShare tests
- streamManager, compactionHandler, hooks, typeGenerator tests
- agentSession.postCompactionAttachments test
- All storybook files (~16 occurrences)
Auto-generated via make fmt. Env var tables now show
MUX_TOOL_INPUT_PATH instead of MUX_TOOL_INPUT_FILE_PATH.
Use type assertion for legacy file_path/filePath fields since
the canonical type now only has path from the Zod schema.
@ammar-agent ammar-agent force-pushed the fix/file-path-alias-normalization branch from 23e0fbf to bf716d5 Compare February 10, 2026 15:08
@ammar-agent ammar-agent changed the title 🤖 fix: normalize path → file_path alias for file tools 🤖 refactor: make path the canonical field for file tools Feb 10, 2026
Deduplicate 5 inline/private implementations of the same
path → file_path → filePath fallback logic into one shared
utility at src/common/utils/tools/toolInputFilePath.ts.

Consumers updated:
- FileEditToolCall.tsx (6→1 line)
- FileReadToolCall.tsx (3→1 line)
- toolFormatters.ts (7→1 line)
- extractEditedFiles.ts (removed 16-line interface + function)
- tokenStatsCalculator.ts (removed 12-line function)
Eliminate duplicated path/file_path resolution logic by having the
Zod preprocessor delegate to the shared extractToolFilePath utility.
Also improves the normalizer to handle the camelCase filePath legacy
key, and documents the unknown→unknown signature constraint.
After the file_path → path rename, the flattener only emits
MUX_TOOL_INPUT_PATH. Existing hooks referencing the old name
would silently get nothing.

Add a LEGACY_ENV_ALIASES table so the flattener also emits
MUX_TOOL_INPUT_FILE_PATH as an alias when PATH is present.
Tested with both positive and negative cases.
@ammario ammario merged commit 6b30acb into main Feb 11, 2026
23 checks passed
@ammario ammario deleted the fix/file-path-alias-normalization branch February 11, 2026 16:11
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.

2 participants