OpenRouter crows; log which model answered each flight

- ChatBrain speaks OpenAI-style chat completions (OpenRouter now)
- CROWS_PROVIDER picks anthropic or openrouter; default model
  openrouter/free; CROWS_MODEL overrides
- Flight log records the model that actually answered
- Token budgets fall back to a length estimate if usage is missing
- start.command reads either key from .env

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UQnSw4RRWp8uqpj3nsnnXF
This commit is contained in:
SmokeyandClaude Opus 5.5 committed 2026-10-27 16:23:59 -06:00
1 parent 69ecabcb8c
commit 73cf298fee
5 files changed
+247 -26

No files matched your search

+3 -2
View File
@@ -144,14 +144,15 @@ func (f *Flock) ask(ctx context.Context, w Watcher, crow, system, prompt string,
cctx, cancel := context.WithTimeout(ctx, f.g.CrowTimeout)
defer cancel()
start := time.Now()
text, tokens, err := f.brain.Ask(cctx, system, prompt)
var model string
text, tokens, err := f.brain.Ask(withModelSlot(cctx, &model), system, prompt)
for _, b := range budgets {
b.Add(tokens)
}
if errors.Is(err, context.DeadlineExceeded) {
err = fmt.Errorf("%s timed out after %s and was dropped", crow, f.g.CrowTimeout)
}
e := Event{Kind: "flight", Crow: crow, Tokens: tokens, Ms: time.Since(start).Milliseconds(), Output: text}
e := Event{Kind: "flight", Crow: crow, Model: model, Tokens: tokens, Ms: time.Since(start).Milliseconds(), Output: text}
if err != nil {
e.Error = err.Error()
}