Skip to content

Commit a631efe

Browse files
authored
enhance(cli, config): Support interactive tool mode switching (#372)
Users can now interactively toggle between different run and result modes when prompted to execute a tool. This allows switching from "Ask" to "Edit" or "Unattended" modes on the fly, providing better control over the tool execution flow without restarting the session. A new skip functionality has been added, allowing users to bypass tool execution entirely. When skipping, users can optionally provide reasoning through their configured editor, which is then communicated back to the assistant to maintain conversation context. It is now also possible, after seeing the tool call arguments provided by the LLM, and having the run mode set to "ask", to allow the tool to run, but modify the response after, even if by default response mode is set to "Unattended". This allows for providing more context to the LLM after the tool call, essentially injecting a "user turn" into the conversation. Additionally, local tools can now return a structured `Outcome::Error` to distinguish between transient and permanent failures. A transient failure is reported back to the LLM for correction, while a permanent failure stops the conversation and is reported back to the user. Finally, the CLI now respects the `InlineResults::Off` configuration to suppress tool result rendering when desired. --------- Signed-off-by: Jean Mertz <git@jeanmertz.com>
1 parent 5544148 commit a631efe

File tree

5 files changed

+293
-134
lines changed

5 files changed

+293
-134
lines changed

crates/jp_cli/src/cmd/query/event.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,7 @@ impl StreamEventHandler {
167167
};
168168

169169
self.tool_call_responses.push(response.clone());
170-
return build_tool_call_response(
171-
&cfg.style,
172-
&response,
173-
&tool_config,
174-
handler,
175-
);
170+
return Ok(None);
176171
}
177172
}
178173
}
@@ -205,6 +200,20 @@ impl StreamEventHandler {
205200
self.tool_call_responses.push(result.clone());
206201
return build_tool_call_response(&cfg.style, &result, &tool_config, handler);
207202
}
203+
Err(ToolError::Skipped { reason }) => {
204+
self.tool_call_responses.push(ToolCallResponse {
205+
id: call.id.clone(),
206+
result: {
207+
let mut msg = "Tool execution skipped by user.".to_string();
208+
if let Some(reason) = reason {
209+
msg.push_str(&format!("\n\n{reason}"));
210+
}
211+
Ok(msg)
212+
},
213+
});
214+
215+
return Ok(None);
216+
}
208217
Err(ToolError::NeedsInput { question }) => {
209218
// Check answers in priority order:
210219
// 1. Turn-level persisted answers
@@ -353,7 +362,9 @@ fn build_tool_call_response(
353362
_ => content.lines().count(),
354363
};
355364

356-
if handler.render_tool_calls {
365+
if handler.render_tool_calls
366+
&& !matches!(tool_config.style().inline_results, InlineResults::Off)
367+
{
357368
let mut intro = "\nTool call result".to_owned();
358369
match tool_config.style().inline_results {
359370
InlineResults::Truncate(TruncateLines { lines }) if lines < content.lines().count() => {

crates/jp_config/src/conversation/tool.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,9 @@ pub enum RunMode {
872872

873873
/// Open an editor to edit the tool call before running it.
874874
Edit,
875+
876+
/// Skip running the tool.
877+
Skip,
875878
}
876879

877880
/// How to deliver the results of the tool to the assistant.
@@ -887,6 +890,9 @@ pub enum ResultMode {
887890

888891
/// Open an editor to edit the tool call result before delivering it.
889892
Edit,
893+
894+
/// Skip delivering the results of the tool call.
895+
Skip,
890896
}
891897

892898
/// Tool configuration with global defaults.

crates/jp_llm/src/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ pub enum ToolError {
152152
error: serde_json::Error,
153153
},
154154

155+
#[error("Tool call failed: {0}")]
156+
ToolCallFailed(String),
157+
155158
#[error("Failed to open editor to edit tool call")]
156159
OpenEditorError {
157160
arguments: serde_json::Value,
@@ -183,6 +186,9 @@ pub enum ToolError {
183186
#[error("Needs input: {question:?}")]
184187
NeedsInput { question: jp_tool::Question },
185188

189+
#[error("Skipped tool execution")]
190+
Skipped { reason: Option<String> },
191+
186192
#[error("Serialization error")]
187193
Serde(#[from] serde_json::Error),
188194

0 commit comments

Comments
 (0)