feat: loading improvement

This commit is contained in:
Richard Tang
2026-03-06 17:35:17 -08:00
parent 5c87b4b194
commit 50ab55ded5
4 changed files with 32 additions and 11 deletions
@@ -609,10 +609,17 @@ Examples:
When the user greets you, respond concisely (under 10 lines) with worker \
status only:
1. State whether a worker[worker name] is loaded and whether it is running, staging, or not loaded.
2. If loaded, include one sentence on what the worker does (from Worker Profile).
1. Use plain, user-facing wording about load/run state; avoid internal phase \
labels ("staging phase", "building phase", "running phase") unless the user \
explicitly asks for phase details.
2. If loaded, prefer this format: "<worker_name> has been loaded. <one sentence \
on what it does from Worker Profile>."
3. Do NOT include identity details unless the user explicitly asks about identity.
4. THEN call ask_user to prompt them do NOT just write text.
5. Preferred loaded example:
local_business_extractor/*agent name*/ has been loaded. It finds local businesses on \
Google Maps, extracts contact details, and syncs them to Google Sheets.
ask_user("Do you want to run it?", ["Yes, run it", "Check credentials first", "Modify the worker"])
## When user ask identity and responsibility
@@ -670,7 +677,9 @@ NEVER call run_agent_with_input until the user has provided their input.
If NO worker is loaded, say so and offer to build one.
## When in staging phase (agent loaded, not running):
- Tell the user the agent is loaded and ready.
- Tell the user the agent is loaded and ready in plain language (for example, \
"<worker_name> has been loaded.").
- Avoid lead-ins like "A worker is loaded and ready in staging phase: ...".
- For tasks matching the worker's goal: ALWAYS ask the user for their \
specific input BEFORE calling run_agent_with_input(task). NEVER make up \
or assume what the user wants. Use ask_user to collect the task details \
+2 -1
View File
@@ -284,7 +284,8 @@ export default function ChatPanel({ messages, onSend, isWaiting, isWorkerWaiting
</div>
))}
{isWaiting && (
{/* Show typing indicator while waiting for first queen response (disabled + empty chat) */}
{(isWaiting || (disabled && threadMessages.length === 0)) && (
<div className="flex gap-3">
<div
className="flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center"
+16 -6
View File
@@ -977,12 +977,19 @@ export default function Workspace() {
// If no messages were actually restored, lift the intro suppression gate
if (restoredMsgs.length === 0 && !coldRestoreId) suppressIntroRef.current.delete(agentType);
// Mark queenReady immediately only when resuming a session that already
// has messages (live resume or cold restore). For a fresh session the
// queen still needs to process the thinking hook before its first
// response, so leave queenReady false and let the SSE handler flip it
// on the first queen event — this keeps the "Connecting to queen..."
// loading indicator visible until the queen actually responds.
const hasRestoredContent = restoredMsgs.length > 0 || !!coldRestoreId;
updateAgentState(agentType, {
sessionId: session.session_id,
displayName,
ready: true,
loading: false,
queenReady: true,
queenReady: !!(isResumedSession || hasRestoredContent),
...(isWorkerRunning ? { workerRunState: "running" } : {}),
});
} catch (err: unknown) {
@@ -1272,16 +1279,17 @@ export default function Workspace() {
// Backend event timestamp for correct queen/worker message ordering
const eventCreatedAt = event.timestamp ? new Date(event.timestamp).getTime() : Date.now();
// Mark queen as ready on the first queen SSE event
if (isQueen && !agentStates[agentType]?.queenReady) {
updateAgentState(agentType, { queenReady: true });
}
// Mark queen as ready on the first queen SSE event.
// Deferred to individual event handlers below so we can batch it with
// other state updates (e.g. queenIsTyping) and avoid a flash frame
// where queenReady=true but queenIsTyping=false.
const shouldMarkQueenReady = isQueen && !agentStates[agentType]?.queenReady;
switch (event.type) {
case "execution_started":
if (isQueen) {
turnCounterRef.current[turnKey] = currentTurn + 1;
updateAgentState(agentType, { isTyping: true, queenIsTyping: true });
updateAgentState(agentType, { isTyping: true, queenIsTyping: true, ...(shouldMarkQueenReady && { queenReady: true }) });
} else {
// Warn if prior LLM snapshots are being dropped (edge case: execution_completed never arrived)
const priorSnapshots = agentStates[agentType]?.llmSnapshots || {};
@@ -1835,6 +1843,8 @@ export default function Workspace() {
}
default:
// Fallback: ensure queenReady is set even for unexpected first events
if (shouldMarkQueenReady) updateAgentState(agentType, { queenReady: true });
break;
}
},
@@ -19,7 +19,8 @@ You are a browser agent. Your job: Search Google Maps for the provided query and
## Workflow
1. browser_start
2. browser_open(url="https://www.google.com/maps")
3. Use browser_type or browser_click to search for the "query" in memory.
3. use the url query to search for the keyword
3.1 alternatively, use browser_type or browser_click to search for the "query" in memory.'
4. browser_wait(seconds=3)
5. browser_snapshot to find the list of results.
6. For each relevant result, extract: