| 1 |
Prompt caching is defeated on every turn, for every provider — the system prompt's first line is a second-resolution timestamp, so no prefix ever matches. |
internal/prompt/builder.go:70 |
#920 |
| 2 |
Anthropic requests carry cache breakpoints on the system block and last tool only — never on message history, so long transcripts are re-charged in full each turn. |
internal/llm/anthropic.go:110-125 |
#921 |
| 3 |
reasoning_effort is silently ignored by the Anthropic client. The shipped default config already sets it on a kind: anthropic tier, so a no-op ships today. |
internal/llm/anthropic.go:106, config/default.yaml:46 |
#922 |
| 4 |
Anthropic assistant turns drop thinking blocks and signatures on the way back to the API. gemini-native already round-trips thoughtSignature correctly — Anthropic was simply never updated. |
internal/llm/anthropic.go:461, cf. internal/llm/gemini_native_convert.go:161 |
#922 |
| 5 |
Anthropic max_tokens is pinned at 4096 and cannot be raised: no tier field exists and the router never passes one. |
internal/llm/provider.go:373, internal/config/types.go:141, internal/tarsserver/helpers_llm_router.go:34 |
#923 |
| 6 |
anthropic-beta is a single hardcoded constant, occupying the only slot with a header that has since gone GA — 1M context, interleaved thinking, and extended cache TTL cannot be opted into. |
internal/llm/anthropic.go:16 |
#923 |
| 7 |
Cost accounting prices every Anthropic model through one anthropic/* wildcard at Sonnet rates. |
internal/usage/tracker_cost.go:33 |
#924 |
| 8 |
No tier carries a context window, so history budgeting and compaction do not change when a tier moves between a 200k and a 1M model. |
internal/config/llm_resolve.go:22 |
#925 |
| 9 |
Provider tests are per-provider and per-file, so capability divergence between providers is unobservable. |
internal/llm/*_test.go |
#926 |
| 10 |
Importing pkg/agentloop pulls 25 internal packages including modernc.org/sqlite and robfig/cron. pkg/llm alone pulls 4. The cause is internal/tool bundling app-specific tools with generic primitives. |
go list -deps ./pkg/agentloop |
#927 |
| 11 |
pkg/* is a pure type-alias facade over internal/*. pkg.go.dev cannot render fields of internal types, so the public API is effectively undocumented, and no gate exists to catch breaking changes. |
pkg/llm/exports.go |
#928, #929 |
| 12 |
pkg/* does not import internal/tarsserver at all — the server/core split already holds in the import direction. The real coupling problem is horizontal, not vertical. |
go list -deps ./pkg/... |
#930 |
Goal
Three related tracks, in dependency order:
pkg/*a real, documentable, dependency-light API surface that external consumers (e.g. linetta) can depend on.tars-app/tars-clirepositories, and narrow the application surface.Based on repository analysis at
d9f9861(v0.35.0).Findings That Motivate This Epic
Verified against the tree, not assumed:
internal/prompt/builder.go:70internal/llm/anthropic.go:110-125reasoning_effortis silently ignored by the Anthropic client. The shipped default config already sets it on akind: anthropictier, so a no-op ships today.internal/llm/anthropic.go:106,config/default.yaml:46gemini-nativealready round-tripsthoughtSignaturecorrectly — Anthropic was simply never updated.internal/llm/anthropic.go:461, cf.internal/llm/gemini_native_convert.go:161max_tokensis pinned at 4096 and cannot be raised: no tier field exists and the router never passes one.internal/llm/provider.go:373,internal/config/types.go:141,internal/tarsserver/helpers_llm_router.go:34anthropic-betais a single hardcoded constant, occupying the only slot with a header that has since gone GA — 1M context, interleaved thinking, and extended cache TTL cannot be opted into.internal/llm/anthropic.go:16anthropic/*wildcard at Sonnet rates.internal/usage/tracker_cost.go:33internal/config/llm_resolve.go:22internal/llm/*_test.gopkg/agentlooppulls 25 internal packages includingmodernc.org/sqliteandrobfig/cron.pkg/llmalone pulls 4. The cause isinternal/toolbundling app-specific tools with generic primitives.go list -deps ./pkg/agentlooppkg/*is a pure type-alias facade overinternal/*. pkg.go.dev cannot render fields of internal types, so the public API is effectively undocumented, and no gate exists to catch breaking changes.pkg/llm/exports.gopkg/*does not importinternal/tarsserverat all — the server/core split already holds in the import direction. The real coupling problem is horizontal, not vertical.go list -deps ./pkg/...Product Direction
Preserve:
Add:
cmd/→internal/app/*→internal/core/*→pkg/)Phases And Work Orders
reasoning_effort+ thinking round-trip)internal/toolinto core primitives and TARS app toolspkg/*aliases sopkgowns the exported typesDependency Order
max_tokens)Suggested Starting Point
#920 is a few lines and affects every turn of every session. Start there.
Roadmap Gates
cache_read_input_tokens.reasoning_effortor reports it as unsupported at resolve time — never silently.pkg/llmandpkg/agentlooprender usable docs on pkg.go.dev and pull no storage or scheduling dependencies.internal/core/*tointernal/app/*fails CI.Non-goals
tars-app/tars-cli/tars-console. See chore(arch): enforce layer boundaries in-repo and defer the multi-repo split #930 for the decision and the criteria under which it is revisited.Completion
go list -deps ./pkg/agentloopcontains no storage, scheduler, or server package.