(t *testing.T)
| 122 | } |
| 123 | |
| 124 | func TestNewHandler_EmitsRepairTelemetry(t *testing.T) { |
| 125 | var buf bytes.Buffer |
| 126 | prev := slog.Default() |
| 127 | slog.SetDefault(slog.New(slog.NewTextHandler(&buf, &slog.HandlerOptions{Level: slog.LevelInfo}))) |
| 128 | t.Cleanup(func() { slog.SetDefault(prev) }) |
| 129 | |
| 130 | type args struct { |
| 131 | Paths []string `json:"paths"` |
| 132 | } |
| 133 | handler := NewHandler(func(_ context.Context, _ args) (*ToolCallResult, error) { |
| 134 | return ResultSuccess("ok"), nil |
| 135 | }) |
| 136 | |
| 137 | _, err := handler(t.Context(), ToolCall{ |
| 138 | Type: "function", |
| 139 | Function: FunctionCall{ |
| 140 | Name: "read_multiple_files", |
| 141 | Arguments: `{"paths":"only.txt"}`, |
| 142 | }, |
| 143 | }) |
| 144 | require.NoError(t, err) |
| 145 | |
| 146 | out := buf.String() |
| 147 | assert.Contains(t, out, "tool_input_repaired") |
| 148 | assert.Contains(t, out, "tool=read_multiple_files") |
| 149 | // Track the exported aijson constant rather than the underlying string |
| 150 | // so the assertion follows the library if it ever renames the value. |
| 151 | assert.Contains(t, out, string(aijson.KindWrapInArray)) |
| 152 | } |
| 153 | |
| 154 | // TestNewHandler_NoTelemetryOnValidInput pins the hot-path contract: a |
| 155 | // well-formed tool call must NOT emit tool_input_repaired. Without this, |
nothing calls this directly
no test coverage detected