Skip to content

feat: track and display LLM model name in session info#581

Merged
squishykid merged 7 commits intomainfrom
feat/model-in-session-info
Mar 3, 2026
Merged

feat: track and display LLM model name in session info#581
squishykid merged 7 commits intomainfrom
feat/model-in-session-info

Conversation

@peyton-alt
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings March 2, 2026 21:08
@cursor
Copy link

cursor bot commented Mar 2, 2026

PR Summary

Medium Risk
Plumbs a new model field through agent hook payloads, lifecycle dispatch, and persisted session state, so regressions could affect session initialization/turn-end transitions if any agent/plugin sends unexpected data. Changes are additive and model is optional, limiting blast radius.

Overview
Tracks LLM model identifiers across the lifecycle. Adds Event.Model and populates it for Cursor and OpenCode turn-start/turn-end hook events.

Persists and updates model info in session state. ManualCommitStrategy.InitializeSession now accepts model, stores it as State.ModelName, updates it on subsequent turns (without overwriting with empty values), and transitionSessionTurnEnd can also backfill the model at idle.

Surfaces model in CLI output and plugin payloads. entire status now prints Agent (model) · <session> when available, and the OpenCode plugin tracks the latest assistant modelID and includes it in hook payloads; tests are updated/added for model parsing and persistence.

Written by Cursor Bugbot for commit ecf2d26. Configure here.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end tracking of the LLM model identifier through agent lifecycle hooks into persisted session state, and surfaces it in entire status so users can see which model is being used for an active session.

Changes:

  • Extend lifecycle events and OpenCode/Cursor hook parsing to capture a model field.
  • Persist model_name in session state and update it across turns (including at turn end).
  • Display the model name in the active session listing and add/adjust relevant unit tests.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
File Description
cmd/entire/cli/strategy/phase_wiring_test.go Updates InitializeSession calls for new parameter and adds tests asserting ModelName persistence/update semantics.
cmd/entire/cli/strategy/phase_prepare_commit_msg_test.go Updates InitializeSession calls to match new signature.
cmd/entire/cli/strategy/manual_commit_test.go Updates InitializeSession calls to match new signature in long-running strategy tests.
cmd/entire/cli/strategy/manual_commit_staging_test.go Updates InitializeSession calls to match new signature in staging attribution tests.
cmd/entire/cli/strategy/manual_commit_session.go Extends session initialization to accept a model string and store it in ModelName.
cmd/entire/cli/strategy/manual_commit_hooks.go Extends InitializeSession to accept a model string and update state.ModelName when non-empty.
cmd/entire/cli/strategy/manual_commit_git.go Updates internal fallback initialization calls for the new initializeSession signature.
cmd/entire/cli/status.go Renders model name alongside agent label in the “Active Sessions” display when available.
cmd/entire/cli/session/state.go Adds persisted ModelName field (model_name) to session state JSON.
cmd/entire/cli/lifecycle.go Propagates event.Model into InitializeSession and into turn-end transition updates; logs model in lifecycle logs.
cmd/entire/cli/agent/event.go Adds Model field to normalized agent lifecycle Event.
cmd/entire/cli/agent/opencode/types.go Extends OpenCode turn-start/turn-end hook payload types to include model.
cmd/entire/cli/agent/opencode/lifecycle.go Parses model from OpenCode turn-start and turn-end hook inputs into agent.Event.Model.
cmd/entire/cli/agent/opencode/lifecycle_test.go Adds unit tests verifying model parsing on OpenCode turn-start (and empty-model behavior).
cmd/entire/cli/agent/opencode/entire_plugin.ts Tracks the last assistant model and includes it in OpenCode turn-start/turn-end hook payloads.
cmd/entire/cli/agent/cursor/lifecycle.go Includes parsed Cursor hook model field in the emitted lifecycle event.
cmd/entire/cli/agent/cursor/lifecycle_test.go Adds unit tests verifying model parsing on Cursor turn-start (and empty-model behavior).
Comments suppressed due to low confidence (6)

cmd/entire/cli/status.go:310

  • The new status line includes the raw model name in parentheses. Model identifiers can be long and may push the line past the intended terminal width; consider truncating the displayed model (similar to how FirstPrompt is truncated) or otherwise constraining it for consistent status formatting.
			// Line 1: Agent (model) · shortID
			if st.ModelName != "" {
				fmt.Fprintf(w, "%s %s %s %s\n",
					sty.render(sty.agent, agentLabel),
					sty.render(sty.dim, "("+st.ModelName+")"),
					sty.render(sty.dim, "·"),
					shortID)

cmd/entire/cli/status.go:316

  • The status output now conditionally renders the model name, but there is no unit test asserting the new “Agent (model) · shortID” format. Since cmd/entire/cli/status_test.go already covers writeActiveSessions, add a test case with State.ModelName set to ensure this behavior is exercised.
			// Line 1: Agent (model) · shortID
			if st.ModelName != "" {
				fmt.Fprintf(w, "%s %s %s %s\n",
					sty.render(sty.agent, agentLabel),
					sty.render(sty.dim, "("+st.ModelName+")"),
					sty.render(sty.dim, "·"),
					shortID)
			} else {
				fmt.Fprintf(w, "%s %s %s\n",
					sty.render(sty.agent, agentLabel),
					sty.render(sty.dim, "·"),
					shortID)
			}

cmd/entire/cli/strategy/manual_commit_session.go:195

  • The doc comment for initializeSession lists agentType/transcriptPath/userPrompt but the function signature now also takes a model parameter. Update the comment to describe what the model argument represents and how it’s persisted (ModelName).
// A partial state may exist if the concurrent session warning was shown.
// agentType is the human-readable name of the agent (e.g., "Claude Code").
// transcriptPath is the path to the live transcript file (for mid-session commit detection).
// userPrompt is the user's prompt text (stored truncated as FirstPrompt for display).
func (s *ManualCommitStrategy) initializeSession(ctx context.Context, repo *git.Repository, sessionID string, agentType types.AgentType, transcriptPath string, userPrompt string, model string) (*SessionState, error) {

cmd/entire/cli/strategy/manual_commit_hooks.go:1609

  • InitializeSession’s parameter docs don’t mention the new model argument. Please document what the model string represents (LLM model identifier) and the update behavior (only overwrites when non-empty).
// agentType is the human-readable name of the agent (e.g., "Claude Code").
// transcriptPath is the path to the live transcript file (for mid-session commit detection).
// userPrompt is the user's prompt text (stored truncated as FirstPrompt for display).
func (s *ManualCommitStrategy) InitializeSession(ctx context.Context, sessionID string, agentType types.AgentType, transcriptPath string, userPrompt string, model string) error {

cmd/entire/cli/agent/event.go:82

  • The Event.Model field comment says it’s populated on TurnStart, but the Cursor/OpenCode implementations also populate Model on TurnEnd events. Update the comment to reflect that Model may be present on both TurnStart and TurnEnd when the agent provides it.
	// Model is the LLM model identifier (e.g., "claude-sonnet-4-20250514").
	// Populated on TurnStart events when the agent provides model info.
	Model string

cmd/entire/cli/agent/opencode/types.go:21

  • The comment on turnEndRaw says it “extends sessionInfoRaw”, but the struct doesn’t embed or reference sessionInfoRaw. Either embed sessionInfoRaw (anonymous field) or adjust the comment to avoid implying inheritance/embedding.
// turnEndRaw matches the JSON payload for turn-end (session idle).
// Extends sessionInfoRaw with model info captured during the turn.
type turnEndRaw struct {
	SessionID string `json:"session_id"`
	Model     string `json:"model"`
}

@peyton-alt peyton-alt marked this pull request as ready for review March 3, 2026 01:36
@peyton-alt peyton-alt requested a review from a team as a code owner March 3, 2026 01:36
@khaong
Copy link
Contributor

khaong commented Mar 3, 2026

bugbot run

@khaong
Copy link
Contributor

khaong commented Mar 3, 2026

I think it's a good idea to keep the model name for claude and gemini as well - i.e. opus-4.6 or gemini-flash-3.1-preview

I'll see if it's easy to add on or will put in a follow up

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

squishykid and others added 3 commits March 3, 2026 16:08
Validates that the Model field from the SessionStart hook is properly
parsed and included in the normalized lifecycle Event.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Entire-Checkpoint: 008b9c5fcce9
- Add sessionStartRaw type with Model field for SessionStart hook
- Parse Model from SessionStart event in parseSessionStart
- Log model in handleLifecycleSessionStart
- Extract persistEventMetadataToState helper to handle event->state metadata
- Refactor transitionSessionTurnEnd to accept full event instead of just model
- Persist model to session state on both session start and turn end

This enables tracking which Claude model was used for each session,
improving visibility into model selection and usage patterns.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Entire-Checkpoint: a83d9e34d525
@squishykid
Copy link
Member

I think it's a good idea to keep the model name for claude and gemini as well - i.e. opus-4.6 or gemini-flash-3.1-preview

I'll see if it's easy to add on or will put in a follow up

I think we don't need to extract gemini, because the model name is included in the transcript.

@squishykid squishykid merged commit 2b55da7 into main Mar 3, 2026
3 checks passed
@squishykid squishykid deleted the feat/model-in-session-info branch March 3, 2026 16:08
@peyton-alt
Copy link
Contributor Author

peyton-alt commented Mar 3, 2026

I think it's a good idea to keep the model name for claude and gemini as well - i.e. opus-4.6 or gemini-flash-3.1-preview

I'll see if it's easy to add on or will put in a follow up

I think we don't need to extract gemini, because the model name is included in the transcript.

Same with claude code, has model in transcript on every assistant message. And looks like copilot has in transcript also.

There isn't anywhere in UI where we see it, but we can consider if we'd want this anywhere. Unless we still want this additional visibility in json and entire status, for example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants