Implement tracking of outstanding LLM and Tool calls

This commit implements a listener pattern between ant.convo and the Agent for tracking outstanding calls.

* Added fields to the Agent struct to track outstanding LLM calls and Tool calls
* Implemented the listener methods to properly track and update these fields
* Added methods to retrieve the counts and names
* Updated the State struct in loophttp.go to expose this information
* Added a unit test to verify the tracking functionality
* Created UI components with lightbulb and wrench icons to display call status
* Added numerical indicators that always show when there are active calls

Co-Authored-By: sketch <hello@sketch.dev>
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index e1b76ad..3ef540b 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -50,14 +50,16 @@
 }
 
 type State struct {
-	MessageCount  int                  `json:"message_count"`
-	TotalUsage    *ant.CumulativeUsage `json:"total_usage,omitempty"`
-	InitialCommit string               `json:"initial_commit"`
-	Title         string               `json:"title"`
-	Hostname      string               `json:"hostname"`    // deprecated
-	WorkingDir    string               `json:"working_dir"` // deprecated
-	OS            string               `json:"os"`          // deprecated
-	GitOrigin     string               `json:"git_origin,omitempty"`
+	MessageCount         int                  `json:"message_count"`
+	TotalUsage           *ant.CumulativeUsage `json:"total_usage,omitempty"`
+	InitialCommit        string               `json:"initial_commit"`
+	Title                string               `json:"title"`
+	Hostname             string               `json:"hostname"`    // deprecated
+	WorkingDir           string               `json:"working_dir"` // deprecated
+	OS                   string               `json:"os"`          // deprecated
+	GitOrigin            string               `json:"git_origin,omitempty"`
+	OutstandingLLMCalls  int                  `json:"outstanding_llm_calls"`
+	OutstandingToolCalls []string             `json:"outstanding_tool_calls"`
 
 	OutsideHostname   string `json:"outside_hostname,omitempty"`
 	InsideHostname    string `json:"inside_hostname,omitempty"`
@@ -349,20 +351,22 @@
 		w.Header().Set("Content-Type", "application/json")
 
 		state := State{
-			MessageCount:      serverMessageCount,
-			TotalUsage:        &totalUsage,
-			Hostname:          s.hostname,
-			WorkingDir:        getWorkingDir(),
-			InitialCommit:     agent.InitialCommit(),
-			Title:             agent.Title(),
-			OS:                agent.OS(),
-			OutsideHostname:   agent.OutsideHostname(),
-			InsideHostname:    s.hostname,
-			OutsideOS:         agent.OutsideOS(),
-			InsideOS:          agent.OS(),
-			OutsideWorkingDir: agent.OutsideWorkingDir(),
-			InsideWorkingDir:  getWorkingDir(),
-			GitOrigin:         agent.GitOrigin(),
+			MessageCount:         serverMessageCount,
+			TotalUsage:           &totalUsage,
+			Hostname:             s.hostname,
+			WorkingDir:           getWorkingDir(),
+			InitialCommit:        agent.InitialCommit(),
+			Title:                agent.Title(),
+			OS:                   agent.OS(),
+			OutsideHostname:      agent.OutsideHostname(),
+			InsideHostname:       s.hostname,
+			OutsideOS:            agent.OutsideOS(),
+			InsideOS:             agent.OS(),
+			OutsideWorkingDir:    agent.OutsideWorkingDir(),
+			InsideWorkingDir:     getWorkingDir(),
+			GitOrigin:            agent.GitOrigin(),
+			OutstandingLLMCalls:  agent.OutstandingLLMCallCount(),
+			OutstandingToolCalls: agent.OutstandingToolCalls(),
 		}
 
 		// Create a JSON encoder with indentation for pretty-printing