#17530: refactor(sessions): centralize session status field extraction
gateway
commands
agents
size: M
Cluster:
Session Management Enhancements
## Summary
- Introduces `SESSION_STATUS_FIELD_NAMES` const array as single source of truth for the 12 common session status fields that were duplicated across ~8 consumer types
- Adds `pickSessionStatus(entry)` to extract common fields via spread and `applySessionStatusFields(target, source)` to conditionally merge them
- Refactors `GatewaySessionRow`, `SessionRow`, `SessionInfo`, `SessionInfoEntry`, and `SessionListRow` to extend the shared type instead of redeclaring each field
- Net removal of ~73 lines of duplicated type/extraction code
- Adding a new session status field now requires one string in the const array instead of touching ~8 files
## Files changed
| File | Change |
|------|--------|
| `src/config/sessions/session-status.ts` | **NEW** — const array, types, two utilities |
| `src/config/sessions/session-status.test.ts` | **NEW** — unit tests |
| `src/config/sessions.ts` | Barrel re-export |
| `src/gateway/session-utils.types.ts` | `GatewaySessionRow` extends `Partial<SessionStatusFields>` |
| `src/gateway/session-utils.ts` | `listSessionsFromStore` uses `pickSessionStatus` spread |
| `src/commands/sessions.ts` | `SessionRow` extends `Partial<SessionStatusFields>`, `toRows` uses `pickSessionStatus` |
| `src/tui/tui-types.ts` | `SessionInfo` extends `SessionStatusFieldsNullable` |
| `src/tui/tui-session-actions.ts` | `SessionInfoEntry` extends `SessionStatusFieldsNullable`, `applySessionInfo` uses `applySessionStatusFields` |
| `src/tui/tui-command-handlers.ts` | `null` → `undefined` for token field clearing (type alignment) |
| `src/agents/tools/sessions-helpers.ts` | `SessionListRow` extends `Partial<SessionStatusFields>` |
## Design decisions
- `model`/`modelProvider` intentionally excluded from shared fields — each consumer resolves them differently
- `SessionStatusFieldsNullable` variant handles JSON-RPC boundaries where `null` values appear
- `sessions-list-tool.ts` left unchanged — its defensive type-guarded extraction is correct for JSON-RPC boundary data
- `contextTokens` in `applySessionInfo` stays manual due to 3-way fallback logic
## Test plan
- [x] New unit tests for `pickSessionStatus` and `applySessionStatusFields`
- [x] `pnpm build` — clean
- [x] `pnpm check` (format + tsgo + lint) — clean
- [x] `pnpm test` — all 815 test files, 6016 tests pass
## Contribution checklist
- [x] Local validation: `pnpm build && pnpm check && pnpm test` — all passing
- [x] Focused scope: single refactoring theme (deduplicate session status fields)
- [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 centralizes 12 session status fields (`systemSent`, `abortedLastRun`, `thinkingLevel`, `verboseLevel`, `reasoningLevel`, `elevatedLevel`, `responseUsage`, `inputTokens`, `outputTokens`, `totalTokens`, `totalTokensFresh`, `contextTokens`) that were previously duplicated across ~8 consumer types into a single `SESSION_STATUS_FIELD_NAMES` const array with derived types and two extraction utilities (`pickSessionStatus`, `applySessionStatusFields`).
- Removes ~73 lines of duplicated type declarations and manual field extractions across `GatewaySessionRow`, `SessionRow`, `SessionInfo`, `SessionInfoEntry`, and `SessionListRow`
- `model`/`modelProvider` are correctly excluded from the shared set since each consumer resolves them differently
- The `null` → `undefined` change in `tui-command-handlers.ts` is safe — all consumers use loose equality (`== null`) or nullish coalescing (`??`)
- Computed overrides in `session-utils.ts` (`totalTokens`, `totalTokensFresh`) correctly appear after the `pickSessionStatus` spread
- The `contextTokens` 3-way fallback in `applySessionInfo` correctly runs after `applySessionStatusFields` and overrides as needed
- New unit tests cover edge cases including `null`/`undefined` inputs and falsy values (`false`, `0`)
<h3>Confidence Score: 5/5</h3>
- This PR is a clean, well-tested refactor that reduces duplication without changing observable behavior.
- Pure type-level and extraction-logic refactoring with no behavioral changes to runtime logic. Computed overrides (totalTokens, totalTokensFresh, contextTokens) are correctly preserved after the spread. The null-to-undefined change is safe given consumer patterns. New unit tests cover the utility functions thoroughly. All 10 changed files were reviewed and no issues were found.
- No files require special attention
<sub>Last reviewed commit: 928ea9e</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#17538: feat(sessions): add resolvedModel field
by Facens · 2026-02-15
76.7%
#15726: fix(sessions): use model contextWindow instead of agent contextToke...
by lailoo · 2026-02-13
75.4%
#16831: feat(status): group cron sessions for readability
by puritysb · 2026-02-15
75.1%
#22469: fix(gateway): avoid stale whatsapp labels on direct sessions
by loganprit · 2026-02-21
74.9%
#17897: refactor: extract firstDefined utility from telegram/line/slack
by iyoda · 2026-02-16
74.6%
#7537: fix(sessions): reset token counts on /new for channel sessions
by SoniAssist · 2026-02-02
74.5%
#21679: fix: Mission Control dashboard issues for agent status, stale sessi...
by thejawdoc · 2026-02-20
74.4%
#19412: fix(status): prefer configured contextTokens over session entry
by rafaelipuente · 2026-02-17
74.3%
#16542: fix(sessions): use atomic temp+rename write on Windows
by aldoeliacim · 2026-02-14
74.2%
#18179: CLI: add sessions --json-debug diagnostics
by p6l-richard · 2026-02-16
74.1%