webui: add model name to info popup k/v pairs

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s89edebe17dd6d6edk
diff --git a/cmd/sketch/main.go b/cmd/sketch/main.go
index 4d2423b..210db71 100644
--- a/cmd/sketch/main.go
+++ b/cmd/sketch/main.go
@@ -657,6 +657,7 @@
 		OutsideOS:         flags.outsideOS,
 		OutsideWorkingDir: flags.outsideWorkingDir,
 		WorkingDir:        wd,
+		Model:             flags.modelName,
 		// Ultimately this is a subtle flag because it's trying to distinguish
 		// between unsafe-on-host and inside sketch, and should probably be renamed/simplified.
 		InDocker:            flags.outsideHostname != "",
diff --git a/loop/agent.go b/loop/agent.go
index d1ff360..4adf80f 100644
--- a/loop/agent.go
+++ b/loop/agent.go
@@ -164,6 +164,9 @@
 
 	// TokenContextWindow returns the TokenContextWindow size of the model the agent is using.
 	TokenContextWindow() int
+
+	// ModelName returns the name of the model the agent is using.
+	ModelName() string
 }
 
 type CodingAgentMessageType string
@@ -481,6 +484,11 @@
 	return a.config.Service.TokenContextWindow()
 }
 
+// ModelName returns the name of the model the agent is using.
+func (a *Agent) ModelName() string {
+	return a.config.Model
+}
+
 // GetConvo returns the conversation interface for debugging purposes.
 func (a *Agent) GetConvo() ConvoInterface {
 	return a.convo
@@ -1090,6 +1098,8 @@
 	InDocker     bool
 	OneShot      bool
 	WorkingDir   string
+	// Model is the name of the LLM model being used
+	Model string
 	// Outside information
 	OutsideHostname   string
 	OutsideOS         string
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index cc183d3..dcb315f 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -159,6 +159,7 @@
 	DiffLinesRemoved     int                           `json:"diff_lines_removed"`              // Lines removed from sketch-base to HEAD
 	OpenPorts            []Port                        `json:"open_ports,omitempty"`            // Currently open TCP ports
 	TokenContextWindow   int                           `json:"token_context_window,omitempty"`
+	Model                string                        `json:"model,omitempty"` // Name of the model being used
 	SessionEnded         bool                          `json:"session_ended,omitempty"`
 	CanSendMessages      bool                          `json:"can_send_messages,omitempty"`
 	EndedAt              time.Time                     `json:"ended_at,omitempty"`
@@ -1386,6 +1387,7 @@
 		DiffLinesRemoved:     diffRemoved,
 		OpenPorts:            s.getOpenPorts(),
 		TokenContextWindow:   s.agent.TokenContextWindow(),
+		Model:                s.agent.ModelName(),
 	}
 }
 
diff --git a/loop/server/loophttp_test.go b/loop/server/loophttp_test.go
index 04a18ba..fa591b2 100644
--- a/loop/server/loophttp_test.go
+++ b/loop/server/loophttp_test.go
@@ -35,6 +35,7 @@
 	slug                     string
 	retryNumber              int
 	skabandAddr              string
+	model                    string
 }
 
 // TokenContextWindow implements loop.CodingAgent.
@@ -42,6 +43,11 @@
 	return 200000
 }
 
+// ModelName implements loop.CodingAgent.
+func (m *mockAgent) ModelName() string {
+	return m.model
+}
+
 func (m *mockAgent) NewIterator(ctx context.Context, nextMessageIdx int) loop.MessageIterator {
 	m.mu.RLock()
 	// Send existing messages that should be available immediately
@@ -293,6 +299,7 @@
 		branchName:               "sketch/test-branch",
 		branchPrefix:             "sketch/",
 		slug:                     "test-slug",
+		model:                    "fake-model",
 	}
 
 	// Add the initial messages before creating the server
@@ -428,6 +435,7 @@
 	mockAgent := &mockAgent{
 		workingDir:   t.TempDir(), // Use a temp directory
 		branchPrefix: "sketch/",
+		model:        "fake-model",
 	}
 
 	// Create the server with the mock agent
@@ -475,6 +483,7 @@
 	mockAgent := &mockAgent{
 		workingDir:   t.TempDir(), // Use a temp directory
 		branchPrefix: "sketch/",
+		model:        "fake-model",
 	}
 
 	// Create the server with the mock agent
@@ -514,6 +523,7 @@
 		messageCount: 0,
 		sessionID:    "test-session",
 		branchPrefix: "sketch/",
+		model:        "fake-model",
 	}
 
 	ctx := context.Background()
@@ -618,6 +628,7 @@
 		branchPrefix:  "test-",
 		workingDir:    "/tmp/test",
 		sessionID:     "test-session",
+		model:         "fake-model",
 		slug:          "test-slug",
 		skabandAddr:   "http://localhost:8080",
 	}
@@ -686,6 +697,7 @@
 	mockAgent := &mockAgent{
 		workingDir:   t.TempDir(),
 		branchPrefix: "sketch/",
+		model:        "fake-model",
 	}
 
 	// Create the server with the mock agent
@@ -771,6 +783,7 @@
 	mockAgent := &mockAgent{
 		workingDir:   t.TempDir(),
 		branchPrefix: "sketch/",
+		model:        "fake-model",
 	}
 
 	// Create the server with the mock agent
diff --git a/webui/src/types.ts b/webui/src/types.ts
index 217afe2..e4ee48c 100644
--- a/webui/src/types.ts
+++ b/webui/src/types.ts
@@ -104,6 +104,7 @@
 	diff_lines_removed: number;
 	open_ports?: Port[] | null;
 	token_context_window?: number;
+	model?: string;
 	session_ended?: boolean;
 	can_send_messages?: boolean;
 	ended_at?: string;
diff --git a/webui/src/web-components/sketch-container-status.ts b/webui/src/web-components/sketch-container-status.ts
index b7b0602..74f2226 100644
--- a/webui/src/web-components/sketch-container-status.ts
+++ b/webui/src/web-components/sketch-container-status.ts
@@ -772,6 +772,23 @@
                 )}/${formatNumber(this.state?.token_context_window || 0)}</span
               >
             </div>
+            ${this.state?.model
+              ? html`
+                  <div
+                    class="flex items-center whitespace-nowrap mr-2.5 text-xs"
+                  >
+                    <span
+                      class="text-xs text-gray-600 dark:text-gray-400 mr-1 font-medium"
+                      >Model:</span
+                    >
+                    <span
+                      id="modelName"
+                      class="text-xs font-semibold break-all text-gray-900 dark:text-gray-100"
+                      >${this.state?.model}</span
+                    >
+                  </div>
+                `
+              : ""}
             <div class="flex items-center whitespace-nowrap mr-2.5 text-xs">
               <span
                 class="text-xs text-gray-600 dark:text-gray-400 mr-1 font-medium"