remove maxSteps and ResetsCounter entirely
The step budget mechanism is gone. Agents run until they finish, are interrupted by the user, or (for sub-agents) hit the timeout. No replacement. The human is the kill switch.
This commit is contained in:
parent
da0ee4456f
commit
74ba5ae7ac
|
|
@ -30,8 +30,6 @@ type AgentConfig struct {
|
||||||
Tools *bool `json:"tools,omitempty"`
|
Tools *bool `json:"tools,omitempty"`
|
||||||
|
|
||||||
AutoLoad []string `json:"autoLoad,omitempty"`
|
AutoLoad []string `json:"autoLoad,omitempty"`
|
||||||
// MaxSteps caps the number of tool-call rounds per turn. 0 means unlimited.
|
|
||||||
MaxSteps int `json:"maxSteps,omitempty"`
|
|
||||||
CompactionModel string `json:"compactionModel,omitempty"`
|
CompactionModel string `json:"compactionModel,omitempty"`
|
||||||
// SystemPrompt overrides the embedded system prompt with a file path.
|
// SystemPrompt overrides the embedded system prompt with a file path.
|
||||||
SystemPrompt string `json:"systemPrompt,omitempty"`
|
SystemPrompt string `json:"systemPrompt,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -162,59 +162,31 @@ func (ag *Agent) run(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := backend.Message{ID: responseID, Role: "assistant", Content: content, Reasoning: reasoning, ToolCalls: toolCalls}
|
msg := backend.Message{ID: responseID, Role: "assistant", Content: content, Reasoning: reasoning, ToolCalls: toolCalls}
|
||||||
results, interrupted := ag.execToolCalls(ctx, toolCalls)
|
results, interrupted := ag.execToolCalls(ctx, toolCalls)
|
||||||
|
|
||||||
h.update(msg, results)
|
h.update(msg, results)
|
||||||
ag.save()
|
ag.save()
|
||||||
|
|
||||||
if interrupted {
|
if interrupted {
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
}
|
|
||||||
if len(toolCalls) == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if abort := ag.trackErrors(ctx, results, &errs, step); abort != nil {
|
|
||||||
return abort
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset step counter when an action-oriented tool succeeds.
|
|
||||||
if rt.ToolMeta != nil {
|
|
||||||
for _, r := range results {
|
|
||||||
if !r.IsError && rt.ToolMeta[r.Name].ResetsCounter {
|
|
||||||
step = 0
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if len(toolCalls) == 0 {
|
||||||
|
|
||||||
// Step budget warnings.
|
|
||||||
if rt.MaxSteps > 0 {
|
|
||||||
halfBudget := rt.MaxSteps / 2
|
|
||||||
if step == halfBudget {
|
|
||||||
h.update(backend.Message{
|
|
||||||
Role: "user",
|
|
||||||
Content: fmt.Sprintf("<system-step-budget-warning>\nYou have used %d/%d research steps without taking action. Consider making progress — write code, edit files, or run commands. Action tools reset this counter.\n</system-step-budget-warning>", step, rt.MaxSteps),
|
|
||||||
}, nil)
|
|
||||||
} else if step >= rt.MaxSteps-1 {
|
|
||||||
ag.emit(Event{Role: "maxsteps", Content: fmt.Sprintf("%d", step+1)})
|
|
||||||
h.update(backend.Message{
|
|
||||||
Role: "user",
|
|
||||||
Content: fmt.Sprintf("<system-step-budget-stop>\nStep budget exhausted (%d/%d steps used). Stop calling tools. Summarize what you have done and what remains, then stop.\n</system-step-budget-stop>", step+1, rt.MaxSteps),
|
|
||||||
}, nil)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_, compactErr := ag.autoCompact(ctx)
|
if abort := ag.trackErrors(ctx, results, &errs, step); abort != nil {
|
||||||
if compactErr != nil {
|
return abort
|
||||||
ag.emit(Event{Role: "error", Content: compactErr.Error()})
|
}
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
step++
|
_, compactErr := ag.autoCompact(ctx)
|
||||||
}
|
if compactErr != nil {
|
||||||
|
ag.emit(Event{Role: "error", Content: compactErr.Error()})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
step++
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,6 @@ type Runtime struct {
|
||||||
ToolMeta map[string]protocol.ToolInfo
|
ToolMeta map[string]protocol.ToolInfo
|
||||||
Exec toolExecutor
|
Exec toolExecutor
|
||||||
GenParams backend.GenerationParams
|
GenParams backend.GenerationParams
|
||||||
MaxSteps int
|
|
||||||
CompactionModel string
|
CompactionModel string
|
||||||
UserPrompt string // resolved user prompts, prepended to each turn's input
|
UserPrompt string // resolved user prompts, prepended to each turn's input
|
||||||
Messages []string
|
Messages []string
|
||||||
|
|
@ -179,7 +178,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
|
||||||
var agentPrompt string
|
var agentPrompt string
|
||||||
var userPrompt string
|
var userPrompt string
|
||||||
var genParams backend.GenerationParams
|
var genParams backend.GenerationParams
|
||||||
var maxSteps int
|
|
||||||
if cfg != nil {
|
if cfg != nil {
|
||||||
if resolved, err := resolvePrompt(cfg.Prompt, cwd, env); err != nil {
|
if resolved, err := resolvePrompt(cfg.Prompt, cwd, env); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "resolve prompt: %v\n", err)
|
fmt.Fprintf(os.Stderr, "resolve prompt: %v\n", err)
|
||||||
|
|
@ -192,7 +190,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
|
||||||
userPrompt = resolved
|
userPrompt = resolved
|
||||||
}
|
}
|
||||||
genParams = cfg.GenerationParams
|
genParams = cfg.GenerationParams
|
||||||
maxSteps = cfg.MaxSteps
|
|
||||||
}
|
}
|
||||||
genParams.CWD = cwd
|
genParams.CWD = cwd
|
||||||
|
|
||||||
|
|
@ -235,7 +232,6 @@ func BuildRuntime(cfg *AgentConfig, srv *toolclient.ToolsrvConn, cwd string, env
|
||||||
Exec: exec,
|
Exec: exec,
|
||||||
Preamble: preamble,
|
Preamble: preamble,
|
||||||
GenParams: genParams,
|
GenParams: genParams,
|
||||||
MaxSteps: maxSteps,
|
|
||||||
CompactionModel: compactionModel,
|
CompactionModel: compactionModel,
|
||||||
UserPrompt: userPrompt,
|
UserPrompt: userPrompt,
|
||||||
Messages: messages,
|
Messages: messages,
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
"lsp_rename",
|
"lsp_rename",
|
||||||
"lsp_completion"
|
"lsp_completion"
|
||||||
],
|
],
|
||||||
"maxSteps": 25,
|
|
||||||
"temperature": 0.5,
|
"temperature": 0.5,
|
||||||
"maxTokens": 16384
|
"maxTokens": 16384
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@
|
||||||
],
|
],
|
||||||
"backend": "openrouter",
|
"backend": "openrouter",
|
||||||
"model": "deepseek/deepseek-v4-flash",
|
"model": "deepseek/deepseek-v4-flash",
|
||||||
"maxSteps": 25,
|
|
||||||
"temperature": 0.4,
|
"temperature": 0.4,
|
||||||
"maxTokens": 16384
|
"maxTokens": 16384
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@
|
||||||
"code_rewrite",
|
"code_rewrite",
|
||||||
"code_dependencies"
|
"code_dependencies"
|
||||||
],
|
],
|
||||||
"maxSteps": 40,
|
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 16384
|
"maxTokens": 16384
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
"memory_recall",
|
"memory_recall",
|
||||||
"memory_remember"
|
"memory_remember"
|
||||||
],
|
],
|
||||||
"maxSteps": 20,
|
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 16384
|
"maxTokens": 16384
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,5 @@
|
||||||
"code_dependencies"
|
"code_dependencies"
|
||||||
],
|
],
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 8192,
|
"maxTokens": 8192
|
||||||
"maxSteps": 30
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
"lsp_rename",
|
"lsp_rename",
|
||||||
"lsp_completion"
|
"lsp_completion"
|
||||||
],
|
],
|
||||||
"maxSteps": 5,
|
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 4096
|
"maxTokens": 4096
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
"memory_recall",
|
"memory_recall",
|
||||||
"memory_remember"
|
"memory_remember"
|
||||||
],
|
],
|
||||||
"maxSteps": 20,
|
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 8192
|
"maxTokens": 8192
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
"file_grep",
|
"file_grep",
|
||||||
"file_write"
|
"file_write"
|
||||||
],
|
],
|
||||||
"maxSteps": 30,
|
|
||||||
"temperature": 0.3,
|
"temperature": 0.3,
|
||||||
"maxTokens": 8192
|
"maxTokens": 8192
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"description": "Replace text in a file. Has fuzzy matching (whitespace/indent flexible).",
|
"description": "Replace text in a file. Has fuzzy matching (whitespace/indent flexible).",
|
||||||
"outputFormat": "diff",
|
"outputFormat": "diff",
|
||||||
"resetsCounter": true,
|
|
||||||
"prompt": "## file_edit\n\nReplace text in a file. Has fuzzy matching (whitespace/indent flexible).\n\n**Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)\n\n```\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\")\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\", replace_all=\"true\")\n```\n\n**Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations \u2014 add surrounding context to disambiguate, or use `replace_all=true`.",
|
"prompt": "## file_edit\n\nReplace text in a file. Has fuzzy matching (whitespace/indent flexible).\n\n**Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)\n\n```\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\")\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\", replace_all=\"true\")\n```\n\n**Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations \u2014 add surrounding context to disambiguate, or use `replace_all=true`.",
|
||||||
"args": {
|
"args": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
{
|
{
|
||||||
"description": "Create or overwrite a file. Produces a unified diff.",
|
"description": "Create or overwrite a file. Produces a unified diff.",
|
||||||
"outputFormat": "diff",
|
"outputFormat": "diff",
|
||||||
"resetsCounter": true,
|
|
||||||
"prompt": "## file_write\n\nCreate or overwrite a file. Produces a unified diff.\n\n**Args**: `[path, content]`\n\n```\nfile_write(path=\"<ABSOLUTE_PATH_FROM_PWD>\", content=\"file content here\")\n```\n\n**Constraints**: Absolute paths only. Parent directory must exist.",
|
"prompt": "## file_write\n\nCreate or overwrite a file. Produces a unified diff.\n\n**Args**: `[path, content]`\n\n```\nfile_write(path=\"<ABSOLUTE_PATH_FROM_PWD>\", content=\"file content here\")\n```\n\n**Constraints**: Absolute paths only. Parent directory must exist.",
|
||||||
"args": {
|
"args": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
{
|
{
|
||||||
"description": "Execute a single bash command in a sandboxed environment.",
|
"description": "Execute a single bash command in a sandboxed environment.",
|
||||||
"resetsCounter": true,
|
|
||||||
"prompt": "Execute a single bash command in a sandboxed environment.\n\nUsage: {\"cmd\": \"your command here\"}\n\nSandbox prevents dangerous operations. Use for computation, builds, scripting.\ntimeout applies to each call (default: 30s). A non-zero exit is an error.",
|
"prompt": "Execute a single bash command in a sandboxed environment.\n\nUsage: {\"cmd\": \"your command here\"}\n\nSandbox prevents dangerous operations. Use for computation, builds, scripting.\ntimeout applies to each call (default: 30s). A non-zero exit is an error.",
|
||||||
"args": {
|
"args": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ type MetaFile struct {
|
||||||
Scope string `json:"scope,omitempty"`
|
Scope string `json:"scope,omitempty"`
|
||||||
OutputFormat string `json:"outputFormat,omitempty"`
|
OutputFormat string `json:"outputFormat,omitempty"`
|
||||||
Cmd string `json:"cmd,omitempty"`
|
Cmd string `json:"cmd,omitempty"`
|
||||||
ResetsCounter bool `json:"resetsCounter,omitempty"`
|
|
||||||
Variants []Variant `json:"variants,omitempty"`
|
Variants []Variant `json:"variants,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +34,6 @@ type Variant struct {
|
||||||
Scope string `json:"scope,omitempty"`
|
Scope string `json:"scope,omitempty"`
|
||||||
OutputFormat string `json:"outputFormat,omitempty"`
|
OutputFormat string `json:"outputFormat,omitempty"`
|
||||||
Cmd string `json:"cmd,omitempty"`
|
Cmd string `json:"cmd,omitempty"`
|
||||||
ResetsCounter bool `json:"resetsCounter,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadMetaFile reads and parses a .meta sidecar file for the given tool name.
|
// LoadMetaFile reads and parses a .meta sidecar file for the given tool name.
|
||||||
|
|
@ -86,9 +84,6 @@ func (m *MetaFile) Resolve() *MetaFile {
|
||||||
if v.Scope != "" {
|
if v.Scope != "" {
|
||||||
resolved.Scope = v.Scope
|
resolved.Scope = v.Scope
|
||||||
}
|
}
|
||||||
if v.ResetsCounter {
|
|
||||||
resolved.ResetsCounter = true
|
|
||||||
}
|
|
||||||
if v.Cmd != "" {
|
if v.Cmd != "" {
|
||||||
resolved.Cmd = v.Cmd
|
resolved.Cmd = v.Cmd
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +179,6 @@ func ToolInfoFromMeta(name string, m *MetaFile) protocol.ToolInfo {
|
||||||
Tier: tier,
|
Tier: tier,
|
||||||
Scope: resolved.Scope,
|
Scope: resolved.Scope,
|
||||||
OutputFormat: resolved.OutputFormat,
|
OutputFormat: resolved.OutputFormat,
|
||||||
ResetsCounter: resolved.ResetsCounter,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,14 @@ import "encoding/json"
|
||||||
|
|
||||||
// ToolInfo describes a tool provided by a server.
|
// ToolInfo describes a tool provided by a server.
|
||||||
type ToolInfo struct {
|
type ToolInfo struct {
|
||||||
Server string
|
Server string
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
InputSchema json.RawMessage
|
InputSchema json.RawMessage
|
||||||
Prompt string
|
Prompt string
|
||||||
Tier string
|
Tier string
|
||||||
Scope string
|
Scope string
|
||||||
OutputFormat string
|
OutputFormat string
|
||||||
ResetsCounter bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolResult is the structured result from a tool execution.
|
// ToolResult is the structured result from a tool execution.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue