MCPcopy Create free account
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 content := chmctx.Truncate(raw)
134 // Truncate keeps head+tail and drops the middle, which is exactly where a
135 // failing assertion or a stack trace sits. Spill the whole result to a file
136 // and name it, so recovering the dropped middle is one grep instead of
137 // re-running the command that produced it with narrower flags.
138 if len(content) < len(raw) {
139 if path := spillOutput(raw); path != "" {
140 content += fmt.Sprintf("\n(full %d-byte output saved to %s - grep or read that file instead of re-running the command)", len(raw), path)
141 }
142 }
143 return chmctx.Message{
144 Role: chmctx.RoleTool,
145 Content: content,
146 ToolCallID: call.ID,
147 ToolName: call.Name,
148 }
149}
150
151// spillOutput writes an over-budget tool result to a temp file and returns its
152// path. Best effort: on failure the model keeps the truncated view it would
153// have had anyway. Cleanup belongs to the OS tmp reaper - each file is already
154// bounded by bash's own capture ceiling.
155func spillOutput(s string) string {
156 f, err := os.CreateTemp("", "codehamr-out-*.txt")
157 if err != nil {
158 return ""
159 }
160 defer f.Close()
161 if _, err := f.WriteString(s); err != nil {
162 os.Remove(f.Name())
163 return ""
164 }
165 return f.Name()
166}
167
168// intArg coerces a numeric tool argument. Weak local tool-call parsers emit
169// integers as JSON numbers or as bare strings; both must mean the same thing,
170// or read_file's continuation note ("continue with offset=451") silently
171// re-reads the head forever and the model loops on a file it can never finish.
172func intArg(args map[string]any, key string) int {
173 switch v := args[key].(type) {
174 case float64:
175 return int(v)
176 case string:
177 v = strings.TrimSpace(v)
178 if n, err := strconv.Atoi(v); err == nil {
179 return n
180 }
181 // "451.0": the same integer wearing a float's clothes. Dropping it to 0
182 // hands read_file the head window again, with the same continuation note
183 // - a success every time, so no failure streak can ever form.
184 if f, err := strconv.ParseFloat(v, 64); err == nil {
185 return int(f)
186 }
187 }
188 return 0
189}
190
191// boolArg coerces a boolean tool argument, for the same reason as intArg. A
192// string "true" silently read as false would make write_file OVERWRITE where

Callers 2

ExecuteFunction · 0.85

Calls 4

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

Tested by 1