← Back to PRs

#17538: feat(sessions): add resolvedModel field

by Facens open 2026-02-15 21:37 View on GitHub →
gateway commands agents size: M
## Summary - Adds `resolvedModel` field to `SessionEntry` for tracking the actual model resolved by the provider (e.g. when using `openrouter/auto`, the resolved model is `anthropic/claude-haiku-4.5`) - Threads `resolvedModel` through the write path: `run.ts` → `agent-runner.ts` → `session-run-accounting.ts` → `session-usage.ts` → `sessions.json` - Displays `resolvedModel` in TUI footer and Telegram response usage when it differs from the configured model - Read-side propagation is **automatic** — one string added to `SESSION_STATUS_FIELD_NAMES` (from PR #17530) **Depends on:** #17530 (centralize session status fields) and pi-mono PR (for `lastAssistant.resolvedModel` source data) ## Files changed | File | Change | |------|--------| | `src/config/sessions/types.ts` | Add `resolvedModel?: string` to `SessionEntry` | | `src/config/sessions/session-status.ts` | Add `"resolvedModel"` to `SESSION_STATUS_FIELD_NAMES` — auto-propagates to ALL consumers | | `src/agents/pi-embedded-runner/types.ts` | Add `resolvedModel?: string` to `EmbeddedPiAgentMeta` | | `src/agents/pi-embedded-runner/run.ts` | Set `agentMeta.resolvedModel` from `lastAssistant` | | `src/auto-reply/reply/session-usage.ts` | Add `resolvedModel` param, persist in both patch paths | | `src/auto-reply/reply/session-run-accounting.ts` | Pass `resolvedModel` through | | `src/auto-reply/reply/agent-runner.ts` | Pass `resolvedModel` to persistence + show in Telegram footer | | `src/tui/tui.ts` | Show `→ resolvedModel` in TUI footer when differs from model | | `src/agents/tools/sessions-list-tool.ts` | Add defensive extraction for `resolvedModel` | | `src/auto-reply/reply/session-usage.test.ts` | Add 2 tests for `resolvedModel` persistence | ## Data flow ``` pi-ai output (lastAssistant.resolvedModel — from pi-mono PR) → run.ts: agentMeta.resolvedModel → agent-runner.ts: persistRunSessionUsage({ resolvedModel }) → session-run-accounting.ts: pass-through → session-usage.ts: patch.resolvedModel = params.resolvedModel ?? entry.resolvedModel → sessions.json via mergeSessionEntry READ side (automatic via SESSION_STATUS_FIELD_NAMES): pickSessionStatus() extracts it → all consumers get it via spread → TUI: applySessionStatusFields → SessionInfo → updateFooter displays it ``` ## Display format - **TUI footer**: `openrouter/openrouter/auto → anthropic/claude-haiku-4.5` - **Telegram**: `Usage: 10k in / 1k out · est $0.001 · openrouter/auto → anthropic/claude-haiku-4.5 · session agent:main:main` ## Test plan - [x] New tests for `resolvedModel` persistence and preservation - [x] `pnpm build` — clean - [x] `pnpm check` (format + tsgo + lint) — clean - [x] `pnpm test` — all 815 test files, 6018 tests pass ## Contribution checklist - [x] Local validation: `pnpm build && pnpm check && pnpm test` — all passing - [x] Focused scope: single feature (resolvedModel tracking and display) - [x] Clear "what" + "why" in description - [x] AI-assisted (Claude Code) — fully tested, code reviewed and understood by author 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR adds a `resolvedModel` field to track the actual model resolved by providers (e.g. when `openrouter/auto` resolves to `anthropic/claude-haiku-4.5`). The feature is well-structured: - **Type additions**: `resolvedModel` added to `SessionEntry` and `EmbeddedPiAgentMeta` - **Centralized status fields**: New `session-status.ts` module with `SESSION_STATUS_FIELD_NAMES`, `pickSessionStatus`, and `applySessionStatusFields` — a clean refactor that eliminates repetitive field-by-field extraction across multiple consumers - **Write path**: Threads `resolvedModel` from pi-ai output through `run.ts` → `agent-runner.ts` → `session-run-accounting.ts` → `session-usage.ts` → `sessions.json` - **Display**: Shows `model → resolvedModel` in TUI footer and Telegram usage line when the resolved model differs from the configured model - **Tests**: Good coverage for the new persistence logic and session-status utilities **Issue found:** - In `session-usage.ts`, `resolvedModel` uses `params.resolvedModel ?? entry.resolvedModel` in both patch paths. This causes stale `resolvedModel` values to persist when switching from a resolving provider (e.g. `openrouter/auto`) to a direct model (e.g. `openai/gpt-4`), since `params.resolvedModel` will be `undefined` and the fallback preserves the old value. This differs from `model`/`modelProvider` which are always populated on every run. <h3>Confidence Score: 3/5</h3> - Mostly safe to merge but has a stale-data bug in resolvedModel persistence that would cause incorrect display after model switches. - The centralized session-status refactor is clean and well-tested. The resolvedModel threading is correct end-to-end except for the persistence fallback in session-usage.ts which preserves stale resolvedModel values when switching to a non-resolving provider. The bug is user-facing (incorrect TUI footer and Telegram usage display) but not destructive. - Pay close attention to `src/auto-reply/reply/session-usage.ts` — the `params.resolvedModel ?? entry.resolvedModel` pattern on lines 96 and 119 causes stale values to persist across model switches. <sub>Last reviewed commit: 4f46d8a</sub> <!-- greptile_other_comments_section --> <sub>(4/5) You can add custom instructions or style guidelines for the agent [here](https://app.greptile.com/review/github)!</sub> <!-- /greptile_comment -->

Most Similar PRs