Add suggest_next_prompt tool for Bedrock prompt suggestions
This commit is contained in:
@@ -615,7 +615,8 @@ pub fn extract_system_prompt(request: &api::Request) -> Option<String> {
|
||||
prompt.push_str("- `apply_file_diffs`: Apply search/replace edits to files.\n");
|
||||
prompt.push_str("- `grep`: Search for patterns in files. Pass all patterns in one call.\n");
|
||||
prompt.push_str("- `file_glob`: Find files matching glob patterns. Pass all patterns in one call.\n");
|
||||
prompt.push_str("- `get_tool_documentation`: Get detailed documentation for any tool or system capabilities.\n\n");
|
||||
prompt.push_str("- `get_tool_documentation`: Get detailed documentation for any tool or system capabilities.\n");
|
||||
prompt.push_str("- `suggest_next_prompt`: After completing a task, suggest a follow-up action the user might want.\n\n");
|
||||
|
||||
prompt.push_str("## Guidelines\n");
|
||||
prompt.push_str("- ALWAYS use tools to explore the codebase before answering questions about code.\n");
|
||||
@@ -742,6 +743,18 @@ fn tool_definition_for_name(name: &str) -> ToolDefinition {
|
||||
"required": ["patterns"]
|
||||
}),
|
||||
},
|
||||
"suggest_next_prompt" => ToolDefinition {
|
||||
name: "suggest_next_prompt".to_string(),
|
||||
description: "After completing a task, suggest a relevant follow-up prompt the user might want to try next. Use this to suggest a natural next step based on what was just accomplished.".to_string(),
|
||||
input_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"prompt": { "type": "string", "description": "The suggested prompt text that will be sent to the agent if the user accepts" },
|
||||
"label": { "type": "string", "description": "Short display label for the suggestion chip (keep under 40 chars)" }
|
||||
},
|
||||
"required": ["prompt", "label"]
|
||||
}),
|
||||
},
|
||||
_ => ToolDefinition {
|
||||
name: name.to_string(),
|
||||
description: format!("Tool: {}", name),
|
||||
@@ -760,6 +773,7 @@ fn default_tool_definitions() -> Vec<ToolDefinition> {
|
||||
tool_definition_for_name("apply_file_diffs"),
|
||||
tool_definition_for_name("grep"),
|
||||
tool_definition_for_name("file_glob"),
|
||||
tool_definition_for_name("suggest_next_prompt"),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -832,6 +846,18 @@ fn extract_tool_call_info(tool_call: &api::message::ToolCall) -> (String, serde_
|
||||
"file_glob".to_string(),
|
||||
serde_json::json!({ "patterns": glob.patterns }),
|
||||
),
|
||||
api::message::tool_call::Tool::SuggestPrompt(sp) => {
|
||||
let (prompt, label) = match &sp.display_mode {
|
||||
Some(api::message::tool_call::suggest_prompt::DisplayMode::PromptChip(chip)) => {
|
||||
(chip.prompt.clone(), chip.label.clone())
|
||||
}
|
||||
_ => (String::new(), String::new()),
|
||||
};
|
||||
(
|
||||
"suggest_next_prompt".to_string(),
|
||||
serde_json::json!({ "prompt": prompt, "label": label }),
|
||||
)
|
||||
}
|
||||
_ => ("unknown_tool".to_string(), serde_json::json!({})),
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -588,6 +588,28 @@ fn build_tool_call_message(
|
||||
},
|
||||
))
|
||||
}
|
||||
"suggest_next_prompt" => {
|
||||
let prompt = input
|
||||
.get("prompt")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
let label = input
|
||||
.get("label")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
Some(api::message::tool_call::Tool::SuggestPrompt(
|
||||
api::message::tool_call::SuggestPrompt {
|
||||
is_trigger_irrelevant: false,
|
||||
display_mode: Some(
|
||||
api::message::tool_call::suggest_prompt::DisplayMode::PromptChip(
|
||||
api::message::tool_call::suggest_prompt::PromptChip { prompt, label },
|
||||
),
|
||||
),
|
||||
},
|
||||
))
|
||||
}
|
||||
_ => {
|
||||
log::warn!("[bedrock] Unknown tool name: {tool_name}, emitting as text");
|
||||
None
|
||||
|
||||
@@ -184,6 +184,25 @@ Get detailed usage documentation for any available tool.
|
||||
## When to use
|
||||
Call this tool when you need detailed guidance on how to use a specific tool effectively, especially for complex operations like file editing or understanding the permission model."#;
|
||||
|
||||
const SUGGEST_NEXT_PROMPT_DOC: &str = r#"# suggest_next_prompt
|
||||
|
||||
Suggest a follow-up action the user might want after completing the current task.
|
||||
|
||||
## When to Use
|
||||
- After completing a task successfully
|
||||
- When there's a natural next step (e.g., "run tests" after writing code, "commit changes" after editing files)
|
||||
- Only call this ONCE at the end of your response, alongside your final text output
|
||||
|
||||
## Parameters
|
||||
- `prompt`: The full prompt text that will be sent to the agent if the user clicks the suggestion
|
||||
- `label`: A short display label (under 40 characters) shown as a clickable chip
|
||||
|
||||
## Guidelines
|
||||
- Keep labels concise and action-oriented (e.g., "Run tests", "Commit changes", "Deploy")
|
||||
- The prompt should be specific enough to be useful without further clarification
|
||||
- Only suggest actions that are relevant to what was just accomplished
|
||||
- Do NOT suggest prompts when the conversation is exploratory or the user is asking questions"#;
|
||||
|
||||
pub fn get_tool_documentation(tool_name: &str) -> Option<String> {
|
||||
match tool_name {
|
||||
"capabilities" => Some(CAPABILITIES_DOC.to_string()),
|
||||
@@ -193,6 +212,7 @@ pub fn get_tool_documentation(tool_name: &str) -> Option<String> {
|
||||
"grep" => Some(GREP_DOC.to_string()),
|
||||
"file_glob" => Some(FILE_GLOB_DOC.to_string()),
|
||||
"get_tool_documentation" => Some(GET_TOOL_DOCUMENTATION_DOC.to_string()),
|
||||
"suggest_next_prompt" => Some(SUGGEST_NEXT_PROMPT_DOC.to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user