Closed Bug 2058590 Opened 1 month ago Closed 24 days ago

improve perceived performance of search the web showing exa tool call when it starts instead of when it finishes

Categories

(Core :: Machine Learning: Frontend, enhancement)

enhancement

Tracking

()

VERIFIED FIXED
155 Branch
Tracking Status
firefox154 --- wontfix
firefox155 --- verified

People

(Reporter: Mardak, Assigned: chloezhou)

References

Details

(Whiteboard: [aiasst])

Attachments

(1 file)

bug 2046622 and bug 2044385 hooked up exa to the log with tools generally added to the action log with bug 2037612, but i believe given how this bug 2046183 tool call ends up basically doing internal tool calls to getPageContent, the actual llm tool call doesn't appear until all pages are fetched

https://searchfox.org/firefox-main/rev/4b4e59946a3db5ddf42ea730fc44c22a99877303/browser/components/aiwindow/models/search/SearchWorkflow.sys.mjs#408,495

agent summarized Timeline

  1. Tool detected — no Exa UI yet

In Chat.sys.mjs, once the model requests a tool:

  conversation.addAssistantMessage("function", {
    tool_calls: [lastToolCall],
  });

  lazy.AIWindow.chatStore?.updateConversation(conversation).catch(() => {});

That only writes the assistant function / tool_calls message and persists it. addAssistantMessage does not emit message-update, so the chat content never builds an action-log card at this point.

  1. Tool runs — can take a long time, still no Exa card

search_the_web goes through runSearchTheWeb (awaited fully):

      if (featureGatedHandler) {
        result = await featureGatedHandler(
          toolParams,
          conversation,
          signal
        );

runSearchTheWeb does, in order:

  1. Exa retrieval (ExaSearchProvider.search)
  2. Bounded page reads (GetPageContent, up to 3 pages, 15s timeout each by default)
  3. Grounded answer generation (another model call)

All of that finishes before control returns to Chat.sys.mjs.

While this is going on, the user only sees the generic assistant loader (assistantIsLoading / isGenerating), not the Exa action log.

  1. Tool completes — action log appears

Only then:

      const content = { tool_call_id: id, body: result, name: toolName };
      conversation.addToolCallMessage(content);

addToolCallMessage is what emits the UI event:

addToolCallMessage(content, toolOpts = new ToolRoleOpts()) {
...
// Emit tool messages so the renderer can display them
// in the action log
if (message) {
this.emit("chat-conversation:message-update", message);
}

The content comment matches that:

/**

  • Handle tool role messages produced when a toolcall completes
  1. Action-log payload is built from the completed tool message

In ai-window.mjs, only role === "tool" messages get an action log:

if (newMessage.role === "tool") {
  const cfg = lazy.getActionLogConfigForTool(
    newMessage.content?.name,
    newMessage.content?.body
  );
  ...
  newMessage.actionLog = {
    uiType: lazy.ACTION_LOG_UI_TYPE,
    pendingLabel: cfg.pendingLabel,
    row: lazy.buildActionLogRow(...),
  };
}

Exa’s labels live in ToolActionLog.sys.mjs:

SEARCH_THE_WEB,
{
  label: { l10nId: "action-log-searched-web-with-exa" },
  pendingLabel: { l10nId: "action-log-searching-web-with-exa" },
  link: { ... },
},

What pendingLabel actually means

It does not mean “tool is in flight.”

#renderActionLogGroup uses pendingLabel while the turn is still incomplete (assistantIsLoading), and “completed N steps” once generation ends:

#renderActionLogGroup(toolMsgs, isComplete) {
const finalMessage = {
l10nId: "action-log-completed-steps",
l10nArgs: { count: toolMsgs.length },
};
const summary = isComplete
? finalMessage
: toolMsgs[toolMsgs.length - 1]?.pendingLabel;

So the sequence is:

│ Phase │ User sees │
│ Exa + page fetches + answer gen │ Generic spinner (chat-assistant-loader default) │
│ Tool result message added │ Action log with “Searching the web with Exa” (pendingLabel) │
│ Final assistant text finishes │ Action log summary flips to “Completed N steps” │

pendingLabel only covers the gap between tool completion and final reply streaming, not the long Exa/page-fetch work itself.

Related: showSearchingIndicator

showSearchingIndicator(true, query) is only used on the search handoff path after a second search_the_web (#continueAfterToolResult), not at the start of the first Exa-backed run.

───

Bottom line: yes — Exa tool UI is post-completion. There is no start-of-tool emission for search_the_web. To show it earlier, you’d want something like emitting a pending tool/action-log when the assistant function/tool_calls message is added (or right before await runSearchTheWeb), then updating/replacing that row when addToolCallMessage runs with the real result.

The tool-result message that builds the action-log card was only added once search_the_web's handler fully resolved (Exa retrieval, page reads, answer generation), so the "Searching the web with Exa" card appeared only at the very end. Emit the tool message up front with a placeholder body so the pending row renders during the work, then reconcile it in place on completion via the new ChatConversation.updateToolCallMessage.

Assignee: nobody → chzhou
Status: NEW → ASSIGNED
Blocks: 2062513
Blocks: 2062514
Status: ASSIGNED → RESOLVED
Closed: 24 days ago
Resolution: --- → FIXED
Target Milestone: --- → 155 Branch
QA Whiteboard: [qa-triage-done-c156/b155]

Verified as fixed in our latest Beta 155.0b2

Status: RESOLVED → VERIFIED
QA Whiteboard: [qa-triage-done-c156/b155] → [qa-triage-done-c156/b155][qa-ver-done-c156/b155]
QA Contact: rdoghi

the code depends on bug 2046612 which has an open regression bug 2057151 so not attempting uplift

No longer blocks: 2062514
Depends on: 2046612
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: