mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
minimizing scaffold context usage experiment
This commit is contained in:
@@ -193,55 +193,30 @@ impl ServerHandler for DeveloperServer {
|
||||
|
||||
let base_instructions = match os {
|
||||
"windows" => formatdoc! {r#"
|
||||
The developer extension gives you the capabilities to edit code files and run shell commands,
|
||||
and can be used to solve a wide range of problems.
|
||||
|
||||
You can use the shell tool to run Windows commands (PowerShell or CMD).
|
||||
When using paths, you can use either backslashes or forward slashes.
|
||||
|
||||
Use the shell tool as needed to locate files or interact with the project.
|
||||
|
||||
Leverage `analyze` through `return_last_only=true` subagents for deep codebase understanding with lean context
|
||||
- delegate analysis, retain summaries
|
||||
|
||||
Your windows/screen tools can be used for visual debugging. You should not use these tools unless
|
||||
prompted to, but you can mention they are available if they are relevant.
|
||||
|
||||
operating system: {os}
|
||||
current directory: {cwd}
|
||||
{container_info}
|
||||
Developer: edit code, run shell, analyze codebases.
|
||||
OS: {os} | CWD: {cwd}{container_info}
|
||||
Shell: PowerShell/CMD. Use forward slashes in paths.
|
||||
Analyze: delegate via return_last_only=true subagents.
|
||||
Screen/windows tools available for debugging.
|
||||
"#,
|
||||
os=os,
|
||||
cwd=cwd.to_string_lossy(),
|
||||
container_info=if in_container { "container: true" } else { "" },
|
||||
container_info=if in_container { " | container" } else { "" },
|
||||
},
|
||||
_ => {
|
||||
let shell_info = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
|
||||
|
||||
formatdoc! {r#"
|
||||
The developer extension gives you the capabilities to edit code files and run shell commands,
|
||||
and can be used to solve a wide range of problems.
|
||||
|
||||
You can use the shell tool to run any command that would work on the relevant operating system.
|
||||
Use the shell tool as needed to locate files or interact with the project.
|
||||
|
||||
Leverage `analyze` through `return_last_only=true` subagents for deep codebase understanding with lean context
|
||||
- delegate analysis, retain summaries
|
||||
|
||||
Your windows/screen tools can be used for visual debugging. You should not use these tools unless
|
||||
prompted to, but you can mention they are available if they are relevant.
|
||||
|
||||
Always prefer ripgrep (rg -C 3) to grep.
|
||||
|
||||
operating system: {os}
|
||||
current directory: {cwd}
|
||||
shell: {shell}
|
||||
{container_info}
|
||||
Developer: edit code, run shell, analyze codebases.
|
||||
OS: {os} | CWD: {cwd} | Shell: {shell}{container_info}
|
||||
Analyze: delegate via return_last_only=true subagents.
|
||||
Screen/windows tools available for debugging.
|
||||
Use rg only, not grep/find/ls -r.
|
||||
"#,
|
||||
os=os,
|
||||
cwd=cwd.to_string_lossy(),
|
||||
shell=shell_info,
|
||||
container_info=if in_container { "container: true" } else { "" },
|
||||
container_info=if in_container { " | container" } else { "" },
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -260,117 +235,40 @@ impl ServerHandler for DeveloperServer {
|
||||
// Check if editor model exists and augment with custom llm editor tool description
|
||||
let editor_description = if let Some(ref editor) = self.editor_model {
|
||||
formatdoc! {r#"
|
||||
|
||||
Additional Text Editor Tool Instructions:
|
||||
|
||||
Perform text editing operations on files.
|
||||
The `command` parameter specifies the operation to perform. Allowed options are:
|
||||
- `view`: View the content of a file.
|
||||
- `write`: Create or overwrite a file with the given content
|
||||
- `str_replace`: Replace text in one or more files.
|
||||
- `insert`: Insert text at a specific line location in the file.
|
||||
- `undo_edit`: Undo the last edit made to a file.
|
||||
|
||||
To use the write command, you must specify `file_text` which will become the new content of the file. Be careful with
|
||||
existing files! This is a full overwrite, so you must include everything - not just sections you are modifying.
|
||||
|
||||
To use the insert command, you must specify both `insert_line` (the line number after which to insert, 0 for beginning, -1 for end)
|
||||
and `new_str` (the text to insert).
|
||||
|
||||
To use the str_replace command to edit multiple files, use the `diff` parameter with a unified diff.
|
||||
To use the str_replace command to edit one file, you must specify both `old_str` and `new_str` - the `old_str` needs to exactly match one
|
||||
unique section of the original file, including any whitespace. Make sure to include enough context that the match is not
|
||||
ambiguous. The entire original string will be replaced with `new_str`
|
||||
|
||||
When possible, batch file edits together by using a multi-file unified `diff` within a single str_replace tool call.
|
||||
|
||||
{}
|
||||
|
||||
TEXT_EDITOR:
|
||||
Commands: view|write|str_replace|insert|undo_edit
|
||||
⚠️ write=full overwrite (include all content)
|
||||
str_replace: diff for multi-file, or old_str+new_str (exact match incl. whitespace, avoid ambiguous)
|
||||
insert: insert_line (0=start, -1=end) + new_str
|
||||
Batch edits: use unified diff
|
||||
{}
|
||||
"#, editor.get_str_replace_description()}
|
||||
} else {
|
||||
formatdoc! {r#"
|
||||
|
||||
Additional Text Editor Tool Instructions:
|
||||
|
||||
Perform text editing operations on files.
|
||||
|
||||
The `command` parameter specifies the operation to perform. Allowed options are:
|
||||
- `view`: View the content of a file.
|
||||
- `write`: Create or overwrite a file with the given content
|
||||
- `str_replace`: Replace text in one or more files.
|
||||
- `insert`: Insert text at a specific line location in the file.
|
||||
- `undo_edit`: Undo the last edit made to a file.
|
||||
|
||||
To use the write command, you must specify `file_text` which will become the new content of the file. Be careful with
|
||||
existing files! This is a full overwrite, so you must include everything - not just sections you are modifying.
|
||||
|
||||
To use the str_replace command to edit multiple files, use the `diff` parameter with a unified diff.
|
||||
To use the str_replace command to edit one file, you must specify both `old_str` and `new_str` - the `old_str` needs to exactly match one
|
||||
unique section of the original file, including any whitespace. Make sure to include enough context that the match is not
|
||||
ambiguous. The entire original string will be replaced with `new_str`
|
||||
|
||||
When possible, batch file edits together by using a multi-file unified `diff` within a single str_replace tool call.
|
||||
|
||||
To use the insert command, you must specify both `insert_line` (the line number after which to insert, 0 for beginning, -1 for end)
|
||||
and `new_str` (the text to insert).
|
||||
|
||||
|
||||
TEXT_EDITOR:
|
||||
Commands: view|write|str_replace|insert|undo_edit
|
||||
⚠️ write=full overwrite (include all content)
|
||||
str_replace: diff for multi-file, or old_str+new_str (exact match incl. whitespace, avoid ambiguous)
|
||||
insert: insert_line (0=start, -1=end) + new_str
|
||||
Batch edits: use unified diff
|
||||
"#}
|
||||
};
|
||||
|
||||
// Create comprehensive shell tool instructions
|
||||
let common_shell_instructions = indoc! {r#"
|
||||
Additional Shell Tool Instructions:
|
||||
Execute a command in the shell.
|
||||
|
||||
This will return the output and error concatenated into a single string, as
|
||||
you would see from running on the command line. There will also be an indication
|
||||
of if the command succeeded or failed.
|
||||
|
||||
Avoid commands that produce a large amount of output, and consider piping those outputs to files.
|
||||
|
||||
**Important**: Each shell command runs in its own process. Things like directory changes or
|
||||
sourcing files do not persist between tool calls. So you may need to repeat them each time by
|
||||
stringing together commands.
|
||||
"#};
|
||||
|
||||
let windows_specific = indoc! {r#"
|
||||
**Important**: For searching files and code:
|
||||
|
||||
Preferred: Use ripgrep (`rg`) when available - it respects .gitignore and is fast:
|
||||
- To locate a file by name: `rg --files | rg example.py`
|
||||
- To locate content inside files: `rg 'class Example'`
|
||||
|
||||
Alternative Windows commands (if ripgrep is not installed):
|
||||
- To locate a file by name: `dir /s /b example.py`
|
||||
- To locate content inside files: `findstr /s /i "class Example" *.py`
|
||||
|
||||
Note: Alternative commands may show ignored/hidden files that should be excluded.
|
||||
|
||||
- Multiple commands: Use && to chain commands, avoid newlines
|
||||
- Example: `cd example && dir` or `activate.bat && pip install numpy`
|
||||
|
||||
**Important**: Use forward slashes in paths (e.g., `C:/Users/name`) to avoid
|
||||
escape character issues with backslashes, i.e. \n in a path could be
|
||||
mistaken for a newline.
|
||||
"#};
|
||||
|
||||
let unix_specific = indoc! {r#"
|
||||
If you need to run a long lived command, background it - e.g. `uvicorn main:app &` so that
|
||||
this tool does not run indefinitely.
|
||||
|
||||
**Important**: Use ripgrep - `rg` - exclusively when you need to locate a file or a code reference,
|
||||
other solutions may produce too large output because of hidden files! For example *do not* use `find` or `ls -r`
|
||||
- List files by name: `rg --files | rg <filename>`
|
||||
- List files that contain a regex: `rg '<regex>' -l`
|
||||
|
||||
- Multiple commands: Use && to chain commands, avoid newlines
|
||||
- Example: `cd example && ls` or `source env/bin/activate && pip install numpy`
|
||||
"#};
|
||||
|
||||
// Condensed shell tool instructions
|
||||
let shell_tool_desc = match os {
|
||||
"windows" => format!("{}{}", common_shell_instructions, windows_specific),
|
||||
_ => format!("{}{}", common_shell_instructions, unix_specific),
|
||||
"windows" => indoc! {r#"
|
||||
SHELL: stdout+stderr string | New process each call (no persist) | Max 400KB
|
||||
Chain: && | Large output: pipe to files
|
||||
Search (prefer rg): `rg --files|rg name`, `rg 'pattern'`
|
||||
Alt Win: `dir /s /b file`, `findstr /s /i "text" *.py` (may show hidden)
|
||||
⚠️ Use forward slashes (C:/Users) to avoid \n escape issues
|
||||
"#},
|
||||
_ => indoc! {r#"
|
||||
SHELL: stdout+stderr string | New process each call (no persist) | Max 400KB
|
||||
Chain: && | Background: cmd & | Large output: pipe to files
|
||||
Search (rg ONLY, no find/ls -r): `rg --files|rg name`, `rg 'pattern' -l`
|
||||
Examples: `cd dir && ls`, `source venv && pip install`
|
||||
"#},
|
||||
};
|
||||
|
||||
// Return base instructions directly when no hints are found
|
||||
@@ -574,7 +472,7 @@ impl DeveloperServer {
|
||||
/// of the screen_capture tool.
|
||||
#[tool(
|
||||
name = "list_windows",
|
||||
description = "List all available window titles that can be used with screen_capture. Returns a list of window titles that can be used with the window_title parameter of the screen_capture tool."
|
||||
description = "Get available window titles for screen_capture."
|
||||
)]
|
||||
pub async fn list_windows(&self) -> Result<CallToolResult, ErrorData> {
|
||||
let windows = Window::all().map_err(|_| {
|
||||
@@ -606,7 +504,7 @@ impl DeveloperServer {
|
||||
/// Only one of display or window_title should be specified.
|
||||
#[tool(
|
||||
name = "screen_capture",
|
||||
description = "Capture a screenshot of a specified display or window. You can capture either: 1. A full display (monitor) using the display parameter 2. A specific window by its title using the window_title parameter. Only one of display or window_title should be specified."
|
||||
description = "Screenshot: display# XOR window_title (use only one)."
|
||||
)]
|
||||
pub async fn screen_capture(
|
||||
&self,
|
||||
|
||||
@@ -12,14 +12,7 @@ pub const PLATFORM_MANAGE_SCHEDULE_TOOL_NAME: &str = "platform__manage_schedule"
|
||||
pub fn read_resource_tool() -> Tool {
|
||||
Tool::new(
|
||||
PLATFORM_READ_RESOURCE_TOOL_NAME.to_string(),
|
||||
indoc! {r#"
|
||||
Read a resource from an extension.
|
||||
|
||||
Resources allow extensions to share data that provide context to LLMs, such as
|
||||
files, database schemas, or application-specific information. This tool searches for the
|
||||
resource URI in the provided extension, and reads in the resource content. If no extension
|
||||
is provided, the tool will search all extensions for the resource.
|
||||
"#}.to_string(),
|
||||
"Read extension resource (files/schemas/data). Searches URI in extension or all if none specified.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"required": ["uri"],
|
||||
@@ -40,15 +33,7 @@ pub fn read_resource_tool() -> Tool {
|
||||
pub fn list_resources_tool() -> Tool {
|
||||
Tool::new(
|
||||
PLATFORM_LIST_RESOURCES_TOOL_NAME.to_string(),
|
||||
indoc! {r#"
|
||||
List resources from an extension(s).
|
||||
|
||||
Resources allow extensions to share data that provide context to LLMs, such as
|
||||
files, database schemas, or application-specific information. This tool lists resources
|
||||
in the provided extension, and returns a list for the user to browse. If no extension
|
||||
is provided, the tool will search all extensions for the resource.
|
||||
"#}
|
||||
.to_string(),
|
||||
"List extension resources. Returns browsable list. Searches all if no extension specified.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -68,10 +53,7 @@ pub fn list_resources_tool() -> Tool {
|
||||
pub fn search_available_extensions_tool() -> Tool {
|
||||
Tool::new(
|
||||
PLATFORM_SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME.to_string(),
|
||||
"Searches for additional extensions available to help complete tasks.
|
||||
Use this tool when you're unable to find a specific feature or functionality you need to complete your task, or when standard approaches aren't working.
|
||||
These extensions might provide the exact tools needed to solve your problem.
|
||||
If you find a relevant one, consider using your tools to enable it.".to_string(),
|
||||
"Find missing functionality/extensions. Enable found items via manage_extensions.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"required": [],
|
||||
@@ -89,11 +71,7 @@ pub fn search_available_extensions_tool() -> Tool {
|
||||
pub fn manage_extensions_tool() -> Tool {
|
||||
Tool::new(
|
||||
PLATFORM_MANAGE_EXTENSIONS_TOOL_NAME.to_string(),
|
||||
"Tool to manage extensions and tools in goose context.
|
||||
Enable or disable extensions to help complete tasks.
|
||||
Enable or disable an extension by providing the extension name.
|
||||
"
|
||||
.to_string(),
|
||||
"Enable or disable extensions. Actions: enable|disable.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"required": ["action", "extension_name"],
|
||||
@@ -114,22 +92,7 @@ pub fn manage_extensions_tool() -> Tool {
|
||||
pub fn manage_schedule_tool() -> Tool {
|
||||
Tool::new(
|
||||
PLATFORM_MANAGE_SCHEDULE_TOOL_NAME.to_string(),
|
||||
indoc! {r#"
|
||||
Manage scheduled recipe execution for this goose instance.
|
||||
|
||||
Actions:
|
||||
- "list": List all scheduled jobs
|
||||
- "create": Create a new scheduled job from a recipe file
|
||||
- "run_now": Execute a scheduled job immediately
|
||||
- "pause": Pause a scheduled job
|
||||
- "unpause": Resume a paused job
|
||||
- "delete": Remove a scheduled job
|
||||
- "kill": Terminate a currently running job
|
||||
- "inspect": Get details about a running job
|
||||
- "sessions": List execution history for a job
|
||||
- "session_content": Get the full content (messages) of a specific session
|
||||
"#}
|
||||
.to_string(),
|
||||
"Schedule recipes (this goose). Jobs: list|create[file]|delete. Control: run_now|pause|unpause|kill[proc]. View: inspect[job]|sessions|content.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"required": ["action"],
|
||||
|
||||
@@ -21,7 +21,7 @@ pub const DYNAMIC_TASK_TOOL_NAME_PREFIX: &str = "dynamic_task__create_task";
|
||||
pub fn create_dynamic_task_tool() -> Tool {
|
||||
Tool::new(
|
||||
DYNAMIC_TASK_TOOL_NAME_PREFIX.to_string(),
|
||||
"Create tasks with instructions or prompt. For simple tasks, only include the instructions field. Extensions control: omit field = use all current extensions; empty array [] = no extensions; array with names = only those extensions. Specify extensions as shortnames (the prefixes for your tools). Specify return_last_only as true and have your subagent summarize its work in its last message to conserve your own context. Optional: title, description, extensions, settings, retry, response schema, context, activities. Arrays for multiple tasks.".to_string(),
|
||||
"Create tasks: req instructions|prompt. Ext: omit=all []=none [names]=only. return_last_only→summary. Opt: title/desc/settings/retry/response/context/activities. Multi→array.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -2,7 +2,6 @@ use super::platform_tools::{
|
||||
PLATFORM_LIST_RESOURCES_TOOL_NAME, PLATFORM_MANAGE_EXTENSIONS_TOOL_NAME,
|
||||
PLATFORM_READ_RESOURCE_TOOL_NAME, PLATFORM_SEARCH_AVAILABLE_EXTENSIONS_TOOL_NAME,
|
||||
};
|
||||
use indoc::indoc;
|
||||
use rmcp::model::{Tool, ToolAnnotations};
|
||||
use rmcp::object;
|
||||
|
||||
@@ -11,18 +10,7 @@ pub const ROUTER_LLM_SEARCH_TOOL_NAME: &str = "router__llm_search";
|
||||
pub fn llm_search_tool() -> Tool {
|
||||
Tool::new(
|
||||
ROUTER_LLM_SEARCH_TOOL_NAME.to_string(),
|
||||
indoc! {r#"
|
||||
Searches for relevant tools based on the user's messages.
|
||||
Format a query to search for the most relevant tools based on the user's messages.
|
||||
Pay attention to the keywords in the user's messages, especially the last message and potential tools they are asking for.
|
||||
This tool should be invoked when the user's messages suggest they are asking for a tool to be run.
|
||||
Use the extension_name parameter to filter tools by the appropriate extension.
|
||||
For example, if the user is asking to list the files in the current directory, you filter for the "developer" extension.
|
||||
Example: {"User": "list the files in the current directory", "Query": "list files in current directory", "Extension Name": "developer", "k": 5}
|
||||
Extension name is not optional, it is required.
|
||||
The returned result will be a list of tool names, descriptions, and schemas from which you, the agent can select the most relevant tool to invoke.
|
||||
"#}
|
||||
.to_string(),
|
||||
"Search tools by user intent. Focus on keywords, especially last message. Required: extension_name to filter (e.g., \"developer\" for file ops). Returns tool names/descriptions/schemas for selection.".to_string(),
|
||||
object!({
|
||||
"type": "object",
|
||||
"required": ["query", "extension_name"],
|
||||
|
||||
@@ -16,21 +16,7 @@ pub const SUBAGENT_EXECUTE_TASK_TOOL_NAME: &str = "subagent__execute_task";
|
||||
pub fn create_subagent_execute_task_tool() -> Tool {
|
||||
Tool::new(
|
||||
SUBAGENT_EXECUTE_TASK_TOOL_NAME,
|
||||
"Only use the subagent__execute_task tool when you execute sub recipe task or dynamic task.
|
||||
EXECUTION STRATEGY DECISION:
|
||||
1. If the tasks are created with execution_mode, use the execution_mode.
|
||||
2. Execute tasks sequentially unless user explicitly requests parallel execution. PARALLEL: User uses keywords like 'parallel', 'simultaneously', 'at the same time', 'concurrently'
|
||||
|
||||
IMPLEMENTATION:
|
||||
- Sequential execution: Call this tool multiple times, passing exactly ONE task per call
|
||||
- Parallel execution: Call this tool once, passing an ARRAY of all tasks
|
||||
|
||||
EXAMPLES:
|
||||
User Intent Based:
|
||||
- User: 'get weather and tell me a joke' → Sequential (2 separate tool calls, 1 task each)
|
||||
- User: 'get weather and joke in parallel' → Parallel (1 tool call with array of 2 tasks)
|
||||
- User: 'run these simultaneously' → Parallel (1 tool call with task array)
|
||||
- User: 'do task A then task B' → Sequential (2 separate tool calls)",
|
||||
"Execute tasks. Mode: task's mode>SEQ(default)>PAR(if parallel/simultaneous/concurrent). SEQ: multi-call/1-task. PAR: 1-call/array.",
|
||||
object!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -47,16 +47,17 @@ impl TodoClient {
|
||||
instructions: Some(indoc! {r#"
|
||||
Task Management
|
||||
|
||||
Use todo_read and todo_write for tasks with 2+ steps, multiple files/components, or uncertain scope.
|
||||
Use todo_write for tasks with 2+ steps, multiple files/components, or uncertain scope.
|
||||
Your TODO content is automatically available in your context.
|
||||
|
||||
Workflow:
|
||||
- Start: read → write checklist
|
||||
- During: read → update progress
|
||||
- Start: write initial checklist
|
||||
- During: update progress
|
||||
- End: verify all complete
|
||||
|
||||
Warning: todo_write overwrites entirely; always todo_read first (skipping is an error)
|
||||
Warning: todo_write overwrites entirely; always include ALL content you want to keep
|
||||
|
||||
Keep items short, specific, action-oriented. Not using the todo tools for complex tasks is an error.
|
||||
Keep items short, specific, action-oriented. Not using the todo tool for complex tasks is an error.
|
||||
|
||||
Template:
|
||||
- [ ] Implement feature X
|
||||
@@ -157,14 +158,7 @@ impl TodoClient {
|
||||
vec) or automatic
|
||||
links using angle brackets (e.g., <http://example.com/>).
|
||||
- For code examples, use fenced code blocks by placing triple backticks (` ``` `) before and after the code. Include the
|
||||
language identifier after the opening backticks (e.g., ` ```python `) to enable syntax highlighting.
|
||||
- Ensure clarity, conciseness, and proper formatting to enhance readability and usability.
|
||||
## Response Format
|
||||
|
||||
Use Markdown formatting:
|
||||
- Headers for structure
|
||||
- Bullet points for lists
|
||||
- Links: `[text](url)` or `<url>`
|
||||
- Code blocks: ` ```language ` with syntax highlighting
|
||||
|
||||
Reference in New Issue
Block a user