Skip to content

Commit ade47ec

Browse files
committed
Models returning plans in json are now properly handled in the toolcall
1 parent 4d1199f commit ade47ec

1 file changed

Lines changed: 57 additions & 1 deletion

File tree

src/repl/tools.go

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,64 @@ func (r *REPL) executeToolNative(toolName string, args ...string) (string, error
316316
return out.String(), nil
317317
}
318318

319+
// planList is []string but tolerates LLMs that emit plan entries as objects,
320+
// numbers, or other non-string JSON values. Non-string elements are preserved
321+
// as their compact JSON encoding so downstream code can keep treating plan
322+
// entries as strings.
323+
type planList []string
324+
325+
func (p *planList) UnmarshalJSON(data []byte) error {
326+
trimmed := bytes.TrimSpace(data)
327+
if len(trimmed) == 0 || bytes.Equal(trimmed, []byte("null")) {
328+
*p = nil
329+
return nil
330+
}
331+
// Accept a single string or object as a one-element plan.
332+
if trimmed[0] != '[' {
333+
var one any
334+
if err := json.Unmarshal(data, &one); err != nil {
335+
return err
336+
}
337+
*p = planList{planEntryToString(one)}
338+
return nil
339+
}
340+
var raw []json.RawMessage
341+
if err := json.Unmarshal(data, &raw); err != nil {
342+
return err
343+
}
344+
out := make(planList, 0, len(raw))
345+
for _, item := range raw {
346+
var s string
347+
if err := json.Unmarshal(item, &s); err == nil {
348+
out = append(out, s)
349+
continue
350+
}
351+
var v any
352+
if err := json.Unmarshal(item, &v); err != nil {
353+
return err
354+
}
355+
out = append(out, planEntryToString(v))
356+
}
357+
*p = out
358+
return nil
359+
}
360+
361+
func planEntryToString(v any) string {
362+
switch t := v.(type) {
363+
case string:
364+
return t
365+
case nil:
366+
return ""
367+
}
368+
b, err := json.Marshal(v)
369+
if err != nil {
370+
return fmt.Sprintf("%v", v)
371+
}
372+
return string(b)
373+
}
374+
319375
type PlanResponse struct {
320-
Plan []string `json:"plan"`
376+
Plan planList `json:"plan"`
321377
CurrentPlanIndex int `json:"current_plan_index"`
322378
Progress string `json:"progress"`
323379
NextStep string `json:"next_step"`

0 commit comments

Comments
 (0)