Skip to content

Commit 1d95c60

Browse files
authored
Merge pull request #26 from comet-ml/codex/hook-performance-cleanup
[codex] Fix hook flush overhead
2 parents 7e55a33 + 1f6bd0d commit 1d95c60

5 files changed

Lines changed: 57 additions & 17 deletions

File tree

src/count_tokens.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bytes"
55
"encoding/json"
6+
"fmt"
67
"net/http"
78
"os"
89
"os/exec"
@@ -238,6 +239,9 @@ var countTokensHTTP = func(payload []byte, headers map[string]string) (int, erro
238239
return 0, err
239240
}
240241
defer resp.Body.Close()
242+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
243+
return 0, fmt.Errorf("count_tokens: %s", resp.Status)
244+
}
241245
var out struct {
242246
InputTokens int `json:"input_tokens"`
243247
}

src/count_tokens_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"encoding/json"
5+
"errors"
56
"os"
67
"strings"
78
"testing"
@@ -110,6 +111,26 @@ func TestRunTokenCountPassBudgetAndBaseline(t *testing.T) {
110111
_ = spent
111112
}
112113

114+
func TestRunTokenCountPassDoesNotCacheHTTPError(t *testing.T) {
115+
resetTokenCache(t)
116+
t.Setenv("ANTHROPIC_API_KEY", "test-key")
117+
118+
old := countTokensHTTP
119+
countTokensHTTP = func(payload []byte, headers map[string]string) (int, error) {
120+
return 0, errors.New("count_tokens: 401 Unauthorized")
121+
}
122+
defer func() { countTokensHTTP = old }()
123+
124+
text := strings.Repeat("uncached prompt body\n", 20)
125+
entries := []TranscriptEntry{userPromptEntry(text)}
126+
if spent := runTokenCountPass(entries, 2); spent != 0 {
127+
t.Fatalf("spent = %d, want 0 after HTTP error", spent)
128+
}
129+
if _, ok := tokenCacheGet(defaultCountModel + "|" + sha256hex(text)); ok {
130+
t.Error("failed count_tokens response should not populate cache")
131+
}
132+
}
133+
113134
func jsonReadFile(path string) ([]byte, error) {
114135
return os.ReadFile(path)
115136
}

src/dryrun_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,15 @@ func TestTraceNameResolution(t *testing.T) {
120120
}
121121
}
122122

123+
func TestSpansHaveUsage(t *testing.T) {
124+
if spansHaveUsage([]Span{{Name: "Read"}, {Name: "Edit"}}) {
125+
t.Fatal("tool-only spans should not require context snapshot work")
126+
}
127+
if !spansHaveUsage([]Span{{Name: "Thinking", Usage: map[string]int{"total_tokens": 12}}}) {
128+
t.Fatal("LLM spans with usage should require context snapshot work")
129+
}
130+
}
131+
123132
// TestToolResultDebug enumerates every tool_use → tool_result pair and
124133
// flags any tool_use whose result the extractor isn't seeing.
125134
func TestToolResultDebug(t *testing.T) {

src/main.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -622,13 +622,15 @@ func flush(state *State) {
622622
// billed tokens to categories with a single-row query, no JOIN back
623623
// to trace.cc.context_runtime. See context_snapshot.go for the
624624
// accuracy tradeoff.
625-
if snapshot := buildContextSnapshot(state); snapshot != nil {
626-
for i := range spans {
627-
if spans[i].Usage == nil {
628-
continue
625+
if spansHaveUsage(spans) {
626+
if snapshot := buildContextSnapshot(state); snapshot != nil {
627+
for i := range spans {
628+
if spans[i].Usage == nil {
629+
continue
630+
}
631+
cc := ensureCCMap(&spans[i])
632+
cc["context_snapshot"] = snapshot
629633
}
630-
cc := ensureCCMap(&spans[i])
631-
cc["context_snapshot"] = snapshot
632634
}
633635
}
634636

@@ -638,6 +640,15 @@ func flush(state *State) {
638640
}
639641
}
640642

643+
func spansHaveUsage(spans []Span) bool {
644+
for _, span := range spans {
645+
if span.Usage != nil {
646+
return true
647+
}
648+
}
649+
return false
650+
}
651+
641652
// findSlug returns the best per-session identifier available on the
642653
// transcript. Historic shape: per-entry `slug` (session-stable kebab-case).
643654
// Claude Code 2.1.150+ shape: dedicated `type:"ai-title"` events carrying

src/metrics.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,10 @@ type EditAggregate struct {
1515
LinesOverwritten int
1616
}
1717

18-
// aggregateEdits walks transcript entries from state.StartLine forward and
19-
// returns counts for Edit/Write/MultiEdit tool calls Claude made in this trace.
20-
func aggregateEdits(state *State) *EditAggregate {
18+
// aggregateEdits walks transcript entries and returns counts for
19+
// Edit/Write/MultiEdit tool calls Claude made in this trace.
20+
func aggregateEdits(entries []TranscriptEntry) *EditAggregate {
2121
agg := &EditAggregate{Files: map[string]struct{}{}}
22-
entries, err := ReadTranscript(state.Transcript, state.StartLine)
23-
if err != nil {
24-
return agg
25-
}
26-
2722
for _, entry := range entries {
2823
if entry.Type != "assistant" || entry.Message == nil {
2924
continue
@@ -184,12 +179,14 @@ func postTraceMetrics(state *State) {
184179
}
185180

186181
metrics := map[string]interface{}{}
182+
fullEntries, _ := ReadTranscript(state.Transcript, 0)
183+
turnEntries, _ := ReadTranscript(state.Transcript, state.StartLine)
187184

188185
var repo, branch string
189186
var commits, insC, delC int
190187
var agg *EditAggregate
191188
if cwd != "" && git(cwd, "rev-parse", "--is-inside-work-tree") == "true" {
192-
agg = aggregateEdits(state)
189+
agg = aggregateEdits(turnEntries)
193190

194191
repo = repoName(cwd)
195192
branch = git(cwd, "branch", "--show-current")
@@ -224,8 +221,6 @@ func postTraceMetrics(state *State) {
224221
debugLog("postTraceMetrics: skipping git block (cwd=%q not a git work tree)", cwd)
225222
}
226223

227-
fullEntries, _ := ReadTranscript(state.Transcript, 0)
228-
turnEntries, _ := ReadTranscript(state.Transcript, state.StartLine)
229224
for domain, snap := range domainSnapshotsFromEntries(fullEntries, turnEntries) {
230225
if snap != nil {
231226
metrics[domain] = snap

0 commit comments

Comments
 (0)