← back to Exo
feat: add Firefox AI sidebar (?q=) support to dashboard (#1814)
10ef7ec9e89c25cb3b38f85648292ed8c7e82fea · 2026-03-30 12:02:35 +0200 · ArvidSU
This PR builds on https://github.com/exo-explore/exo/pull/1677 to enable
custom prompts sent from Firefox `browser.ml.chat` to EXO dashboard
using URL parameters in sidebar for summary and other browser
interactions. See "Summarize page" example below.
## Summary
- Parse `?q=<encoded prompt>` URL parameter on page load and auto-submit
it as a chat message
- Clean up the URL with `history.replaceState` to prevent re-submission
on refresh
- Defer auto-send until both cluster state and model list are loaded so
model auto-selection works correctly
## Context
Firefox's built-in AI sidebar (`about:config: browser.ml.chat.enabled`)
integrates with chat providers by appending the user's prompt as
`?q=<URL-encoded prompt>`. Previously the exo dashboard ignored this
parameter. Users can now configure `http://localhost:52415` as a Firefox
AI chatbot provider.
See: https://support.mozilla.org/en-US/kb/ai-chatbot
## Technical notes
- Frontend-only change in `dashboard/src/routes/+page.svelte`
- Uses a Svelte `$effect` that reacts to `pendingFirefoxQuery`, `data`
(cluster state), and `models.length` — fires exactly once when all three
are ready
- If no model is selected, `handleAutoSend` auto-picks the best
available model; if no model fits memory, a toast is shown
- If a model is selected but not running, the message is queued until
the model loads
## Testing
```
http://localhost:52415/?q=Hello+world
http://localhost:52415/?q=Summarize+this+page%3A+%5Bpage+title%5D+%5Bpage+url%5D
```
<img width="2056" height="1329" alt="image"
src="https://github.com/user-attachments/assets/74463eb4-ca1a-400d-806a-c19ba93147b9"
/>
Files touched
M dashboard/src/routes/+page.svelte
Diff
commit 10ef7ec9e89c25cb3b38f85648292ed8c7e82fea
Author: ArvidSU <45108382+ArvidSU@users.noreply.github.com>
Date: Mon Mar 30 12:02:35 2026 +0200
feat: add Firefox AI sidebar (?q=) support to dashboard (#1814)
This PR builds on https://github.com/exo-explore/exo/pull/1677 to enable
custom prompts sent from Firefox `browser.ml.chat` to EXO dashboard
using URL parameters in sidebar for summary and other browser
interactions. See "Summarize page" example below.
## Summary
- Parse `?q=<encoded prompt>` URL parameter on page load and auto-submit
it as a chat message
- Clean up the URL with `history.replaceState` to prevent re-submission
on refresh
- Defer auto-send until both cluster state and model list are loaded so
model auto-selection works correctly
## Context
Firefox's built-in AI sidebar (`about:config: browser.ml.chat.enabled`)
integrates with chat providers by appending the user's prompt as
`?q=<URL-encoded prompt>`. Previously the exo dashboard ignored this
parameter. Users can now configure `http://localhost:52415` as a Firefox
AI chatbot provider.
See: https://support.mozilla.org/en-US/kb/ai-chatbot
## Technical notes
- Frontend-only change in `dashboard/src/routes/+page.svelte`
- Uses a Svelte `$effect` that reacts to `pendingFirefoxQuery`, `data`
(cluster state), and `models.length` — fires exactly once when all three
are ready
- If no model is selected, `handleAutoSend` auto-picks the best
available model; if no model fits memory, a toast is shown
- If a model is selected but not running, the message is queued until
the model loads
## Testing
```
http://localhost:52415/?q=Hello+world
http://localhost:52415/?q=Summarize+this+page%3A+%5Bpage+title%5D+%5Bpage+url%5D
```
<img width="2056" height="1329" alt="image"
src="https://github.com/user-attachments/assets/74463eb4-ca1a-400d-806a-c19ba93147b9"
/>
---
dashboard/src/routes/+page.svelte | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/dashboard/src/routes/+page.svelte b/dashboard/src/routes/+page.svelte
index 751ba51d..965482e6 100644
--- a/dashboard/src/routes/+page.svelte
+++ b/dashboard/src/routes/+page.svelte
@@ -265,6 +265,7 @@
let mounted = $state(false);
let localNodeId = $state<string | null>(null);
+ let pendingFirefoxQuery = $state<string | null>(null); // ?q= param deferred until state loads
// ── Onboarding wizard state ──
const ONBOARDING_COMPLETE_KEY = "exo-onboarding-complete";
@@ -1309,6 +1310,20 @@
return;
}
+ // Firefox AI sidebar integration: handle ?q= query parameter
+ // Firefox's built-in AI sidebar (about:config: browser.ml.chat.enabled) sends
+ // the user's prompt as ?q=<URL-encoded prompt> to the configured provider URL.
+ // See: https://support.mozilla.org/en-US/kb/ai-chatbot
+ const queryParam = params.get("q");
+ if (queryParam) {
+ // Clean up the URL to prevent re-submission on page refresh
+ window.history.replaceState({}, "", window.location.pathname);
+ // Defer the auto-send until cluster state is loaded (topologyData,
+ // instances, availableMemory) so that model auto-selection works
+ // correctly. The $effect below will pick this up once data is ready.
+ pendingFirefoxQuery = queryParam;
+ }
+
// Check server-side onboarding state (persisted in ~/.exo)
try {
const res = await fetch("/onboarding");
@@ -1329,6 +1344,18 @@
}
});
+ // Deferred Firefox AI sidebar auto-send: wait for cluster state and model
+ // list before submitting. Both data (from /state polling) and models (from
+ // the async /models fetch in onMount) must be loaded for handleAutoSend to
+ // correctly auto-select a model.
+ $effect(() => {
+ if (pendingFirefoxQuery && data && models.length > 0) {
+ const query = pendingFirefoxQuery;
+ pendingFirefoxQuery = null;
+ handleChatSend(query);
+ }
+ });
+
async function fetchModels() {
try {
const response = await fetch("/models");
← 1e51dc89 chore: bump exo-version with release version (#1807)
·
back to Exo
·
feat: /state/paths (#1796) c6c5a3e7 →