refactor(import): centralize imported-Kind checks and token merge · Entire

refactor(import): centralize imported-Kind checks and token merge

e139821→main·

computermode·1w ago·9 files·+84 added/-47 removed

- Add Kind.IsImported() alongside IsReview/IsInvestigate and route all imported special-cases (staleness, orphan cleanup, resume filter, list/info labels, JSON field) through it, killing the scattered string-literal checks. - Add types.AddTokenUsage (canonical, nil-safe, recursive) and use it in the importer instead of a hand-rolled fold. - Drop the single-use pluralizeImportedSessions helper and a redundant local.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Sessions

01KX4F2HAMHPF9FYCTD17VN18RView transcript

[?
Fix Imported Sessions Handling in CLIClaude Code·Opus 4.8·8 steps](/content/gh/entireio/cli/session/91fa7c44-6634-48ab-ae5f-d394502f50d5#timeline-01KX4F2HAMHPF9FYCTD17VN18R/index.html)

Changes

9

15 unmodified lines

// SubagentTokens contains token usage from spawned subagents (if any)
SubagentTokens *TokenUsage `json:"subagent_tokens,omitempty"`
}

// AddTokenUsage returns the sum of a and b, recursing into subagent usage.
// Either operand may be nil (treated as zero); the result is nil only when both
// are. Neither input is mutated.
func AddTokenUsage(a, b *TokenUsage) *TokenUsage {
    if a == nil && b == nil {
        return nil
    }
    sum := &TokenUsage{}
    var aSub, bSub *TokenUsage
    if a != nil {
        sum.InputTokens = a.InputTokens
        sum.CacheCreationTokens = a.CacheCreationTokens
        sum.CacheReadTokens = a.CacheReadTokens
        sum.OutputTokens = a.OutputTokens
        sum.APICallCount = a.APICallCount
        aSub = a.SubagentTokens
    }
    if b != nil {
        sum.InputTokens += b.InputTokens
        sum.CacheCreationTokens += b.CacheCreationTokens
        sum.CacheReadTokens += b.CacheReadTokens
        sum.OutputTokens += b.OutputTokens
        sum.APICallCount += b.APICallCount
        bSub = b.SubagentTokens
    }
    sum.SubagentTokens = AddTokenUsage(aSub, bSub)
    return sum
}

Mcmd/entire/cli/agent/types/token_usage.go+29

package types

import "testing"

func TestAddTokenUsage(t *testing.T) {
    t.Parallel()

if got := AddTokenUsage(nil, nil); got != nil {
        t.Errorf("AddTokenUsage(nil, nil) = %+v, want nil", got)
    }

only := &TokenUsage{InputTokens: 3}
    if got := AddTokenUsage(nil, only); got == nil || got.InputTokens != 3 {
        t.Errorf("AddTokenUsage(nil, x) = %+v, want a copy of x", got)
    }
    if got := AddTokenUsage(only, nil); got == only {
        t.Error("AddTokenUsage must not return an input pointer (would alias caller state)")
    }

a := &TokenUsage{InputTokens: 1, OutputTokens: 2, APICallCount: 1, SubagentTokens: &TokenUsage{InputTokens: 10}}
    b := &TokenUsage{InputTokens: 4, OutputTokens: 5, APICallCount: 2, SubagentTokens: &TokenUsage{InputTokens: 20}}
    got := AddTokenUsage(a, b)
    if got.InputTokens != 5 || got.OutputTokens != 7 || got.APICallCount != 3 {
        t.Errorf("top-level sum = %+v", got)
    }
    if got.SubagentTokens == nil || got.SubagentTokens.InputTokens != 30 {
        t.Errorf("subagent sum = %+v, want InputTokens 30", got.SubagentTokens)
    }
    if a.InputTokens != 1 || a.SubagentTokens.InputTokens != 10 {
        t.Error("AddTokenUsage mutated an input")
    }
}

Acmd/entire/cli/agent/types/token_usage_test.go+32

package types_test

import "testing"

func TestCountImportedSessions(t *testing.T) {
    states := []*SessionState{{Kind: KindImported}, {Kind: KindImported}, {Kind: KindNormal}}
    if got := countImportedSessions(states); got != 2 {
        t.Fatalf("countImportedSessions = %d, want 2", got)
    }
    if got := pluralizeImportedSessions(1); got != "1 imported session is" {
        t.Errorf("singular = %q", got)
    }
    if got := pluralizeImportedSessions(3); got != "3 imported sessions are" {
        t.Errorf("plural = %q", got)
    }
}

Code snippets that represent significant logic and testing flows are preserved as requested.