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

Method run

internal/llm/llm.go:292–338  ·  view source on GitHub ↗
(parent context.Context, msgs []chmctx.Message, tools []Tool, out chan<- Event)

Source from the content-addressed store, hash-verified

290 })
291 if err != nil {
292 return ProbeResult{Budget: budget}, err
293 }
294 defer resp.Body.Close()
295 return ProbeResult{
296 ContextWindow: cloud.ContextWindowFromHeaders(resp.Header),
297 Budget: cloud.FromHeaders(resp.Header),
298 }, nil
299}
300
301// Chat streams an assistant response on the returned channel, closing it when
302// the stream ends. Reasoning runs at `high` effort by default; if the server
303// rejects the tools + reasoning_effort combo (newer OpenAI models do), postChat
304// drops reasoning_effort for this Client's lifetime so the model still works,
305// with tools but no reasoning. Staying on chat-completions is the product line;
306// we do not branch to /v1/responses to keep reasoning.
307func (c *Client) Chat(parent context.Context, messages []chmctx.Message, tools []Tool) <-chan Event {
308 out := make(chan Event, 32)
309 go c.run(parent, messages, tools, out)
310 return out
311}
312
313func (c *Client) run(parent context.Context, msgs []chmctx.Message, tools []Tool, out chan<- Event) {
314 defer close(out)
315 start := time.Now()
316
317 // Pre-stream retry: transient failures (proxy hiccups: 5xx, 429, LiteLLM's
318 // transient 404) are resent after a rising backoff instead of killing the
319 // turn. Only here, before any token has streamed — a mid-stream resend
320 // would duplicate content already in the transcript. Probe stays
321 // retry-free: its job is fast feedback on a misconfigured profile.
322 resp, errEvt := c.sendChat(parent, msgs, tools)
323 for attempt := 0; errEvt != nil && attempt < len(c.RetryBackoff) && retryable(errEvt.Err); attempt++ {
324 delay := c.RetryBackoff[attempt]
325 hint := fmt.Sprintf("retry %d/%d in %s", attempt+1, len(c.RetryBackoff), delay)
326 if !sendEvent(parent, out, Event{Kind: EventRetry, Content: hint, Err: errEvt.Err}) {
327 return
328 }
329 select {
330 case <-time.After(delay):
331 case <-parent.Done():
332 // Ctrl+C during the wait: unwind silently, exactly like a
333 // cancelled sendEvent — the TUI already aborted the turn.
334 return
335 }
336 resp, errEvt = c.sendChat(parent, msgs, tools)
337 }
338 if errEvt != nil {
339 sendEvent(parent, out, *errEvt)
340 return
341 }

Callers 1

ChatMethod · 0.95

Calls 6

sendChatMethod · 0.95
FromHeadersFunction · 0.92
ContextWindowFromHeadersFunction · 0.92
sendEventFunction · 0.85
readSSEFunction · 0.85
ResetMethod · 0.80

Tested by

no test coverage detected