mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-13 07:11:55 +00:00
refactor: add shell-specific guidance to each tool prompt
This commit is contained in:
parent
3e26c3ae83
commit
51ebba2975
5 changed files with 58 additions and 23 deletions
|
|
@ -1,7 +1,13 @@
|
|||
import { createShellTool } from "./util"
|
||||
|
||||
export const BashTool = createShellTool(
|
||||
"bash",
|
||||
"Bash",
|
||||
"use a single Bash call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`).",
|
||||
)
|
||||
export const BashTool = createShellTool({
|
||||
id: "bash",
|
||||
shellName: "Bash",
|
||||
chaining:
|
||||
"use a single Bash call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`).",
|
||||
guidance: `# Bash shell notes
|
||||
- This is a POSIX-compatible shell. Standard Unix conventions apply.
|
||||
- Use double quotes for variable interpolation, single quotes for literal strings.
|
||||
- Use \`$(...)\` for command substitution (not backticks).
|
||||
- Redirect stderr with \`2>&1\` or \`2>/dev/null\`.`,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,17 @@
|
|||
import { createShellTool } from "./util"
|
||||
|
||||
export const PowershellTool = createShellTool(
|
||||
"powershell",
|
||||
"Windows PowerShell",
|
||||
"avoid '&&' in this shell because Windows PowerShell 5.1 does not support it. Use PowerShell conditionals such as `cmd1; if ($?) { cmd2 }`",
|
||||
)
|
||||
export const PowershellTool = createShellTool({
|
||||
id: "powershell",
|
||||
shellName: "Windows PowerShell 5.1",
|
||||
chaining:
|
||||
"avoid '&&' in this shell because Windows PowerShell 5.1 does not support it. Use PowerShell conditionals such as `cmd1; if ($?) { cmd2 }` when later commands must depend on earlier success.",
|
||||
guidance: `# Windows PowerShell 5.1 shell notes
|
||||
- This is Windows PowerShell 5.1 (legacy), NOT PowerShell 7+. It does NOT support \`&&\` or \`||\` pipeline chain operators.
|
||||
- For conditional chaining use: \`cmd1; if ($?) { cmd2 }\`
|
||||
- Use double quotes for interpolated strings (\`"Hello $name"\`), single quotes for verbatim strings.
|
||||
- Cmdlets use Verb-Noun naming (e.g., \`Get-ChildItem\`, \`Set-Content\`). Common aliases like \`ls\`, \`cat\`, \`rm\` resolve to cmdlets with different behavior than Unix equivalents.
|
||||
- Use \`$(...)\` for subexpressions. Use \`@(...)\` for array expressions.
|
||||
- To call a native executable whose path contains spaces, use the call operator: \`& "path/to/exe" args\`.
|
||||
- Escape special characters with backtick (\\\`) not backslash.
|
||||
- Some modern PowerShell features (ternary operator, null-coalescing, etc.) are NOT available in 5.1.`,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,15 @@
|
|||
import { createShellTool } from "./util"
|
||||
|
||||
export const PwshTool = createShellTool(
|
||||
"pwsh",
|
||||
"PowerShell Core",
|
||||
"use a single PowerShell call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`).",
|
||||
)
|
||||
export const PwshTool = createShellTool({
|
||||
id: "pwsh",
|
||||
shellName: "PowerShell 7+",
|
||||
chaining:
|
||||
"use a single PowerShell call with '&&' to chain them together (e.g., `git add . && git commit -m \"message\" && git push`).",
|
||||
guidance: `# PowerShell 7+ (pwsh) shell notes
|
||||
- This is PowerShell 7+ (Core), a cross-platform shell. It supports pipeline chain operators (\`&&\` and \`||\`).
|
||||
- Use double quotes for interpolated strings (\`"Hello $name"\`), single quotes for verbatim strings.
|
||||
- Cmdlets use Verb-Noun naming (e.g., \`Get-ChildItem\`, \`Set-Content\`). Common aliases like \`ls\`, \`cat\`, \`rm\` are available but resolve to cmdlets.
|
||||
- Use \`$(...)\` for subexpressions. Use \`@(...)\` for array expressions.
|
||||
- To call a native executable whose path contains spaces, use the call operator: \`& "path/to/exe" args\`.
|
||||
- Escape special characters with backtick (\\\`) not backslash.`,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ All commands run in ${directory} by default. Use the \`workdir\` parameter if yo
|
|||
|
||||
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
|
||||
|
||||
${guidance}
|
||||
|
||||
Before executing the command, please follow these steps:
|
||||
|
||||
1. Directory Verification:
|
||||
|
|
|
|||
|
|
@ -80,13 +80,17 @@ export async function resolvePath(text: string, root: string, shell: string) {
|
|||
return path.resolve(root, text)
|
||||
}
|
||||
|
||||
export function formatShellDescription(template: string, opts: { name: string; shellName: string; chaining: string }) {
|
||||
export function formatShellDescription(
|
||||
template: string,
|
||||
opts: { name: string; shellName: string; chaining: string; guidance: string },
|
||||
) {
|
||||
return template
|
||||
.replaceAll("${directory}", Instance.directory)
|
||||
.replaceAll("${os}", process.platform)
|
||||
.replaceAll("${shell}", opts.name)
|
||||
.replaceAll("${shellName}", opts.shellName)
|
||||
.replaceAll("${chaining}", opts.chaining)
|
||||
.replaceAll("${guidance}", opts.guidance)
|
||||
.replaceAll("${maxLines}", String(Truncate.MAX_LINES))
|
||||
.replaceAll("${maxBytes}", String(Truncate.MAX_BYTES))
|
||||
}
|
||||
|
|
@ -102,16 +106,21 @@ export type ShellType = "bash" | "pwsh" | "powershell"
|
|||
|
||||
const DEFAULT_TIMEOUT = Flag.OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS || 2 * 60 * 1000
|
||||
|
||||
export function createShellTool(id: ShellType, shellName: string, chaining: string) {
|
||||
const log = Log.create({ service: `${id}-tool` })
|
||||
export function createShellTool(opts: { id: ShellType; shellName: string; chaining: string; guidance: string }) {
|
||||
const log = Log.create({ service: `${opts.id}-tool` })
|
||||
|
||||
return Tool.define(id, async () => {
|
||||
return Tool.define(opts.id, async () => {
|
||||
const shell = Shell.acceptable()
|
||||
const name = Shell.name(shell)
|
||||
log.info(`${id} tool using shell`, { shell, name })
|
||||
log.info(`${opts.id} tool using shell`, { shell, name })
|
||||
|
||||
return {
|
||||
description: formatShellDescription(DESCRIPTION, { name, shellName, chaining }),
|
||||
description: formatShellDescription(DESCRIPTION, {
|
||||
name,
|
||||
shellName: opts.shellName,
|
||||
chaining: opts.chaining,
|
||||
guidance: opts.guidance,
|
||||
}),
|
||||
parameters: z.object({
|
||||
command: z.string().describe("The command to execute"),
|
||||
timeout: z.number().describe("Optional timeout in milliseconds").optional(),
|
||||
|
|
@ -138,11 +147,11 @@ export function createShellTool(id: ShellType, shellName: string, chaining: stri
|
|||
command: params.command,
|
||||
cwd,
|
||||
shell,
|
||||
shellType: id,
|
||||
shellType: opts.id,
|
||||
})
|
||||
if (!Instance.containsPath(cwd)) scan.dirs.add(cwd)
|
||||
|
||||
await askPermission(ctx, scan, id)
|
||||
await askPermission(ctx, scan, opts.id)
|
||||
|
||||
return ShellRunner.run(
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue