agent no. from backend

3clyp50 committed Dec 30, 2025 at 04:45 UTC ced8f87e8ea4e899d79235d8f5b9a1b3173091f1
3 files changed +20 -20
python/helpers/log.py
+7
@@ -136,10 +136,16 @@ class LogItem:
136 duration_ms: Optional[int] = None # Duration until next step (set by Log.log)
137 tokens_in: int = 0 # Input tokens consumed
138 tokens_out: int = 0 # Output tokens generated
139 + agent_number: int = 0 # Agent number (0 = main agent, 1+ = subordinate agents)
140
141 def __post_init__(self):
142 self.guid = self.log.guid
143 self.timestamp = time.time() # Record creation time
144 + # Capture agent number from context if available
145 + if self.log.context and self.log.context.streaming_agent:
146 + self.agent_number = self.log.context.streaming_agent.number
147 + else:
148 + self.agent_number = 0 # Default to main agent
149
150 def update(
151 self,
@@ -202,6 +208,7 @@ class LogItem:
208 "duration_ms": self.duration_ms, # Duration until next step
209 "tokens_in": self.tokens_in, # Input tokens
210 "tokens_out": self.tokens_out, # Output tokens
211 + "agent_number": self.agent_number, # Agent number for identifying main/subordinate agents
212 }
213
214
webui/index.js
+4 -3
@@ -185,8 +185,8 @@ async function updateUserTime() {
185 updateUserTime();
186 setInterval(updateUserTime, 1000);
187
188 -function setMessage(id, type, heading, content, temp, kvps = null, timestamp = null, durationMs = null, tokensIn = 0, tokensOut = 0) {
189 - const result = msgs.setMessage(id, type, heading, content, temp, kvps, timestamp, durationMs, tokensIn, tokensOut);
188 +function setMessage(id, type, heading, content, temp, kvps = null, timestamp = null, durationMs = null, tokensIn = 0, tokensOut = 0, agentNumber = 0) {
189 + const result = msgs.setMessage(id, type, heading, content, temp, kvps, timestamp, durationMs, tokensIn, tokensOut, agentNumber);
190 const chatHistoryEl = document.getElementById("chat-history");
191 if (preferencesStore.autoScroll && chatHistoryEl) {
192 chatHistoryEl.scrollTop = chatHistoryEl.scrollHeight;
@@ -314,7 +314,8 @@ export async function poll() {
314 log.timestamp,
315 log.duration_ms,
316 log.tokens_in,
317 - log.tokens_out
317 + log.tokens_out,
318 + log.agent_number || 0 // Agent number for identifying main/subordinate agents
319 );
320 }
321 afterMessagesUpdate(response.logs);
webui/js/messages.js
+9 -17
@@ -17,19 +17,7 @@ const PROCESS_TYPES = ['agent', 'tool', 'code_exe', 'browser', 'info', 'hint', '
17 // Main types that should always be visible (not collapsed)
18 const MAIN_TYPES = ['user', 'response', 'error', 'rate_limit'];
19
20 -/**
21 - * Check if a response is from the main agent (A0)
22 - * Subordinate agents (A1, A2, ...) responses should be treated as process steps
23 - */
24 -function isMainAgentResponse(heading) {
25 - if (!heading) return true; // Default to main agent
26 - // Check for subordinate agent patterns like "A1:", "A2:", etc.
27 - const match = heading.match(/\bA(\d+):/);
28 - if (!match) return true; // No agent marker = main agent
29 - return match[1] === "0"; // Only A0 is the main agent
30 -}
31 -
32 -export function setMessage(id, type, heading, content, temp, kvps = null, timestamp = null, durationMs = null, tokensIn = 0, tokensOut = 0) {
20 +export function setMessage(id, type, heading, content, temp, kvps = null, timestamp = null, durationMs = null, tokensIn = 0, tokensOut = 0, agentNumber = 0) {
21 // Check if this is a process type message
22 const isProcessType = PROCESS_TYPES.includes(type);
23 const isMainType = MAIN_TYPES.includes(type);
@@ -64,7 +52,8 @@ export function setMessage(id, type, heading, content, temp, kvps = null, timest
52 }
53
54 // For subordinate agent responses (A1, A2, ...), treat as a process step instead of main response
67 - if (type === "response" && !isMainAgentResponse(heading)) {
55 + // agentNumber: 0 = main agent, 1+ = subordinate agents
56 + if (type === "response" && agentNumber !== 0) {
57 if (processStepElement) {
58 updateProcessStep(processStepElement, id, "agent", heading, content, kvps, durationMs, tokensIn, tokensOut);
59 return processStepElement;
@@ -1118,8 +1107,11 @@ function createProcessGroup(id) {
1107 group.classList.add("process-group");
1108 group.setAttribute("data-group-id", groupId);
1109
1121 - // Default to collapsed state - don't add 'expanded' class
1122 - // (Users can expand manually by clicking)
1110 + // Check initial expansion state from store (respects user preference)
1111 + const initiallyExpanded = processGroupStore.isGroupExpanded(groupId);
1112 + if (initiallyExpanded) {
1113 + group.classList.add('expanded');
1114 + }
1115
1116 // Create header
1117 const header = document.createElement("div");
@@ -1724,7 +1716,7 @@ function markProcessGroupComplete(group, responseTitle) {
1716 const statusEl = group.querySelector(".group-status");
1717 if (statusEl) {
1718 statusEl.innerHTML = '<span class="badge-icon material-symbols-outlined">check_circle</span>END';
1727 - statusEl.className = "status-badge status-response group-status"; // No status-active
1719 + statusEl.className = "status-badge status-end group-status"; // No status-active
1720 }
1721
1722 // Remove status-active from all step badges (stop spinners)