[
https://issues.apache.org/jira/browse/CAMEL-26398?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Federico Mariani updated CAMEL-26398:
-------------------------------------
Description:
Found on main (4.24.0-SNAPSHOT, commit ffef175654d1); the line numbers below
are from that commit. The same code is in the 4.23.0 release.
h3. Reproduction
{{camel_validate_source}}, {{camel_write_file}}, {{camel_edit_file}} and
{{camel_get_files}} take a {{directory}} (absolute) and a {{file}} relative to
it. Models often pass the path in a different way:
{code}
camel_validate_source {"file":"/workspace/camel/routes.yaml"}
-> directory is required: the project directory with the source files
camel_validate_source
{"file":"/workspace/camel/main-route.yaml","directory":"/workspace"}
-> file must be a path relative to the directory /workspace, not
/workspace/camel/main-route.yaml
camel_validate_source {"file":"camel/book-orders.yaml"}
-> directory is required: the project directory with the source files
camel_validate_source {"file":"order-intake.yaml","directory":"/workspace"}
(the file is camel/order-intake.yaml)
-> No such file in the directory: order-intake.yaml
camel_write_file
{"directory":"/workspace/camel","file":"application.properties","content":"..."}
(camel/ not created yet)
-> No such directory: /workspace/camel
{code}
In each case the intended file is clear and inside the directory the agent
works in.
Eval evidence (200 trials on 4.24.0-SNAPSHOT): 21 failed calls (Claude Haiku
4.5: 13, DeepSeek V4.1 Flash: 5, GLM 5.3: 2, Claude Haiku 5.5: 1). Sonnet 5.5
had none.
||Shape||Calls||
|absolute {{file}}, no {{directory}}|7|
|relative {{file}}, no {{directory}}|5|
|absolute {{file}} and {{directory}}|2|
|{{file}} relative to the wrong directory (it is in a subdirectory)|2|
|YAML content passed as {{file}}|2|
|{{camel_write_file}} into a directory that does not exist yet|3|
Usually the next call fixed the arguments. In 2 of the validate episodes (Haiku
4.5), the agent stopped validating and edited the file instead. Both
{{camel_write_file}} episodes (DeepSeek) went on with {{mkdir -p}} in the shell
and the same call again. These tools are new in 4.24, so 4.22.1 has nothing to
compare with.
h3. Cause
* {{ToolContext.resolveDirectory}}
({{camel-jbang-core/.../commands/ai/ToolContext.java:159-169}}) needs
{{directory}} when the context has no default (an MCP server has none), and
rejects a directory that does not exist.
* {{AuthoringTools.resolveFile}}
({{commands/ai/AuthoringTools.java:2217-2234}}) rejects every absolute
{{file}}, even one that lies inside {{directory}}.
* {{camel_validate_source}} reads the file only at {{directory/file}}
({{AuthoringTools.java:192-205}}), and its "No such file" answer does not say
where a file of that name is.
* {{camel_write_file}} creates missing subdirectories of the file
({{Files.createDirectories(path.getParent())}}, {{AuthoringTools.java:1749}}),
but not a missing {{directory}}.
h3. Fix
The resolved file must always stay inside the resolved project directory; an
absolute path is never a way around that.
* Absolute {{file}}: accepted only when it lies inside the given {{directory}}.
Both are resolved with {{toRealPath()}}, so a symlink inside the project cannot
lead outside it; the file is then made relative. Anything else is refused, as
today. An absolute {{file}} is never used to derive the directory.
* No {{directory}}: still refused, but the message names what to pass ("pass
directory, the absolute project directory"). When the client sends exactly one
MCP root, that root can be the default directory, under the same containment
rule.
* {{camel_write_file}} (and only the write tool) creates a missing
{{directory}} only when it lies inside an existing project directory: the MCP
root when the client sends one. Without a root it stays an error, and the
message says to pass the existing project directory and put the subdirectory in
{{file}}, which is created already
({{"directory":"/workspace","file":"camel/application.properties"}}).
* "No such file in the directory": name a file of that name in a subdirectory
of the directory (e.g. "camel/order-intake.yaml exists"). When {{file}} has
several lines, say that the content goes in {{content}}.
was:
Found on main (4.24.0-SNAPSHOT, commit ffef175654d1); the line numbers below
are from that commit. The same code is in the 4.23.0 release.
h3. Reproduction
{{camel_validate_source}}, {{camel_write_file}}, {{camel_edit_file}} and
{{camel_get_files}} take a {{directory}} (absolute) and a {{file}} relative to
it. Models often pass the path in a different way:
{code}
camel_validate_source {"file":"/workspace/camel/routes.yaml"}
-> directory is required: the project directory with the source files
camel_validate_source
{"file":"/workspace/camel/main-route.yaml","directory":"/workspace"}
-> file must be a path relative to the directory /workspace, not
/workspace/camel/main-route.yaml
camel_validate_source {"file":"camel/book-orders.yaml"}
-> directory is required: the project directory with the source files
camel_validate_source {"file":"order-intake.yaml","directory":"/workspace"}
(the file is camel/order-intake.yaml)
-> No such file in the directory: order-intake.yaml
camel_write_file
{"directory":"/workspace/camel","file":"application.properties","content":"..."}
(camel/ not created yet)
-> No such directory: /workspace/camel
{code}
In each case the intended file is clear and inside the directory the agent
works in.
Eval evidence (200 trials on 4.24.0-SNAPSHOT): 21 failed calls (Claude Haiku
4.5: 13, DeepSeek V4.1 Flash: 5, GLM 5.3: 2, Claude Haiku 5.5: 1). Sonnet 5.5
had none.
||Shape||Calls||
|absolute {{file}}, no {{directory}}|7|
|relative {{file}}, no {{directory}}|5|
|absolute {{file}} and {{directory}}|2|
|{{file}} relative to the wrong directory (it is in a subdirectory)|2|
|YAML content passed as {{file}}|2|
|{{camel_write_file}} into a directory that does not exist yet|3|
Usually the next call fixed the arguments. In 2 of the validate episodes (Haiku
4.5), the agent stopped validating and edited the file instead. Both
{{camel_write_file}} episodes (DeepSeek) went on with {{mkdir -p}} in the shell
and the same call again. These tools are new in 4.24, so 4.22.1 has nothing to
compare with.
h3. Cause
* {{ToolContext.resolveDirectory}}
({{camel-jbang-core/.../commands/ai/ToolContext.java:159-169}}) needs
{{directory}} when the context has no default (an MCP server has none), and
rejects a directory that does not exist.
* {{AuthoringTools.resolveFile}}
({{commands/ai/AuthoringTools.java:2217-2234}}) rejects every absolute
{{file}}, even one that lies inside {{directory}}.
* {{camel_validate_source}} reads the file only at {{directory/file}}
({{AuthoringTools.java:192-205}}), and its "No such file" answer does not say
where a file of that name is.
* {{camel_write_file}} creates missing subdirectories of the file
({{Files.createDirectories(path.getParent())}}, {{AuthoringTools.java:1749}}),
but not a missing {{directory}}.
h3. Fix
* Absolute {{file}}: with no {{directory}}, take its parent as the directory.
With a {{directory}}, accept it when it lies inside the directory, and make it
relative.
* No {{directory}} and a relative {{file}}: use the client's MCP roots when
there is exactly one, else answer with the directory to pass. The working
directory of a stdio server, which clients usually start in the project, could
also be the default.
* {{camel_write_file}} (and only the write tool) creates a missing
{{directory}}, as it already does for subdirectories of {{file}}.
* "No such file in the directory": name a file of that name in a subdirectory
(e.g. "camel/order-intake.yaml exists"). When {{file}} has several lines, say
that the content goes in {{content}}.
* The path rules stay the same: the resolved file must stay inside the resolved
directory.
> camel-jbang-mcp - the file tools refuse an absolute file path, a call without
> directory, and a directory that does not exist yet
> --------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-26398
> URL: https://issues.apache.org/jira/browse/CAMEL-26398
> Project: Camel
> Issue Type: Improvement
> Components: camel-jbang, camel-jbang-mcp
> Affects Versions: 4.23.0
> Reporter: Federico Mariani
> Assignee: Federico Mariani
> Priority: Major
>
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)