MCPcopy Index your code
hub / github.com/codehamr/codehamr / runRaw

Function runRaw

internal/tools/bash.go:135–191  ·  view source on GitHub ↗
(parent context.Context, call chmctx.ToolCall)

Source from the content-addressed store, hash-verified

133}
134
135func runRaw(parent context.Context, call chmctx.ToolCall) string {
136 // A truncated/oversized tool call leaves llm.resolve()'s _parse_error
137 // sentinel where real args should be. Without this guard the call falls
138 // through to an empty path/cmd and returns a misleading "(empty path)",
139 // hiding that the server cut the arguments at its output-token limit, the
140 // failure that makes a model re-emit the same too-large write for minutes.
141 // Name the real cause and the recovery so it self-corrects in one step.
142 if msg, ok := call.Arguments["_parse_error"].(string); ok {
143 return fmt.Sprintf("(tool arguments were not valid JSON: %s, most likely the "+
144 "content was too large and the server truncated the call at its output-token "+
145 "limit. Do NOT retry the same whole-file write. Build the file in chunks with "+
146 "bash heredoc append: `cat > path <<'EOF'` … `EOF` for the first part, then "+
147 "repeated `cat >> path <<'EOF'` … `EOF` for each next part, then verify with "+
148 "`wc -c path`.)", msg)
149 }
150 switch call.Name {
151 case BashName:
152 cmd, _ := call.Arguments["cmd"].(string)
153 // Default 2m, overridable per call up to 1h. Clamp seconds BEFORE the
154 // Duration multiply: 1e18 would overflow int64 into a negative duration,
155 // and 0.5 would truncate to 0 and cancel before the shell runs, so
156 // floor at 1.
157 timeout := 2 * time.Minute
158 if secs, ok := call.Arguments["timeout_seconds"].(float64); ok && secs > 0 {
159 secs = min(max(secs, 1), maxBashTimeoutSeconds)
160 timeout = time.Duration(secs) * time.Second
161 }
162 return Bash(parent, cmd, timeout)
163 case WriteFileName:
164 path, _ := call.Arguments["path"].(string)
165 // A missing/non-string content (valid JSON, so no _parse_error; schema
166 // `required` is not enforced by open-source backends) must not decode
167 // to "" and silently truncate an existing file to 0 bytes behind a
168 // success-shaped result. An explicit `"content": ""` still writes.
169 content, ok := call.Arguments["content"].(string)
170 if !ok {
171 return `(missing content argument: the call carried no string "content", refusing to write - resend with the full content; an intentionally empty file needs an explicit "content": "")`
172 }
173 return WriteFile(path, content)
174 case EditFileName:
175 path, _ := call.Arguments["path"].(string)
176 oldString, _ := call.Arguments["old_string"].(string)
177 // Same guard as write_file's content: a dropped new_string must not
178 // decode to "" and silently delete the matched text. An explicit
179 // `"new_string": ""` still deletes.
180 newString, ok := call.Arguments["new_string"].(string)
181 if !ok {
182 return `(missing new_string argument: the call carried no string "new_string", refusing to edit - resend it; deleting the match needs an explicit "new_string": "")`
183 }
184 return EditFile(path, oldString, newString)
185 case ReadFileName:
186 path, _ := call.Arguments["path"].(string)
187 return ReadFile(path)
188 default:
189 return fmt.Sprintf("(unknown tool: %s)", call.Name)
190 }
191}
192

Callers 2

ExecuteFunction · 0.85

Calls 4

BashFunction · 0.85
WriteFileFunction · 0.85
EditFileFunction · 0.85
ReadFileFunction · 0.85

Tested by 1