Skip to content

Add AI browser prompt api#33

Merged
ScriptSmith merged 5 commits into
mainfrom
prompt-api
May 4, 2026
Merged

Add AI browser prompt api#33
ScriptSmith merged 5 commits into
mainfrom
prompt-api

Conversation

@ScriptSmith
Copy link
Copy Markdown
Owner

No description provided.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 29, 2026

Greptile Summary

This PR wires up Chrome's on-device Prompt API as a browser/* model provider: a window-side bridge relays calls from the service worker (which can't access globalThis.LanguageModel), the SW intercepts /v1/models, /v1/responses, and /v1/chat/completions for browser/ models, and the setup wizard gains a BrowserAiCard that tracks download state. Tool use is polyfilled via system-prompt injection plus responseConstraint schema enforcement since the native tools option is not yet accepted by Chrome.

All previously flagged issues — role: \"tool\" message mapping, tool_calls field in chat completions, event.loaded fraction semantics, the silent no-op download callback, and the stale availability cache — have been addressed in this revision.

Confidence Score: 5/5

Safe to merge — only P2 findings remain; no runtime crashes or data-loss paths identified

All previously flagged P1 issues (tool message drops, tool_calls field, availability cache staleness, no-op download callback) are resolved. The two remaining findings are P2: an incorrect null-output serialization in tool results and a transient wizard-flash when browser AI is already downloaded, neither of which blocks core functionality.

ui/src/service-worker/browser-ai.ts (null output serialization at line 788) and ui/src/components/WasmSetup/WasmSetupGuard.tsx (availability initialisation timing)

Important Files Changed

Filename Overview
ui/src/service-worker/browser-ai.ts New 1400-line SW module implementing Responses and Chat Completions APIs over the Prompt API bridge; tool-call polyfill via responseConstraint is well-structured; null output serialization in inputToMessages produces wrong markup (P2)
ui/src/services/browser-ai/bridge.ts Window-side bridge relaying Prompt API calls from the SW via MessageChannel; abort handling, session lifecycle, cumulative-vs-delta streaming heuristic, and download-progress forwarding all look correct; event.loaded documented as 0-1 fraction
ui/src/components/WasmSetup/WasmSetupGuard.tsx Orchestrates browser AI state, bridge installation, download flow, and availability-cache invalidation; transient wizard flash possible when availability resolves after the model-list query (P2)
ui/src/components/WasmSetup/WasmSetup.tsx Refactors BrowserAiProp into a bundled optional to eliminate the silent no-op fallback; BrowserAiCard correctly wired in WelcomeStep and ProvidersStep
ui/src/components/WasmSetup/BrowserAiCard.tsx New UI card for browser AI state (supported/downloadable/downloading/ready/unavailable); progress bar uses downloadProgress * 100 consistently with the 0-1 bridge value
ui/src/service-worker/sw.ts Adds BROWSER_AI_AVAILABILITY_CHANGED message handler and routes browser-AI requests through maybeHandleBrowserAi before the WASM gateway; /v1/models augmentation calls gateway exactly once
ui/src/services/browser-ai/availability.ts UA-based model detection (Edge -> Phi-4-Mini, Chrome/Brave -> Gemini Nano) and availability polling; Edge guard runs before Chrome regex so Edge UA is not misclassified
ui/src/services/browser-ai/types.ts Type declarations for the Prompt API; event.loaded documented as 0-1 fraction with spec link
ui/src/services/browser-ai/index.ts Barrel re-exports for the browser-ai service module
ui/src/components/ModelPicker/model-utils.ts Adds 'Browser AI' to PROVIDER_LABELS; trivial change
ui/src/pages/providers/shared.tsx Adds sky-500 colour entry for the browser provider; trivial change
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
ui/src/service-worker/browser-ai.ts:788-790
**Null tool output serialized as `""` not as empty string**

`JSON.stringify(item.output ?? "")` handles a `null`/`undefined` `output` field by substituting `""`, then JSON-encodes it to the literal `"\"\""` (two double-quote characters). The injected markup becomes `<tool_result name="tool">""</tool_result>`, which the model reads as the string `""` rather than an empty result. A `null` output should produce an empty tag body.

```suggestion
      const output =
        typeof item.output === "string"
          ? item.output
          : item.output != null
            ? JSON.stringify(item.output)
            : "";
```

### Issue 2 of 2
ui/src/components/WasmSetup/WasmSetupGuard.tsx:344-374
**Transient wizard flash when Browser AI is already downloaded**

`browserAi` state is initialised with `availability: "unavailable"` regardless of the actual on-device state. If the model list query settles before the `getAvailability()` promise (which talks to the bridge), `needsOnboarding` will briefly be `true` — opening the wizard — even when the browser AI model is already ready. Once `getAvailability()` resolves, `browserAiCounts` becomes true and the modal closes, but the flash is visible.

Consider initialising `availability` via a synchronous check if the API exposes one, or at minimum ensure `isLoading` stays true until both the model-list query and the availability check have settled.

Reviews (3): Last reviewed commit: "Review fixes" | Re-trigger Greptile

Comment thread ui/src/service-worker/browser-ai.ts
@ScriptSmith
Copy link
Copy Markdown
Owner Author

@greptile-apps

Comment thread ui/src/service-worker/browser-ai.ts
@ScriptSmith
Copy link
Copy Markdown
Owner Author

@greptile-apps

@ScriptSmith ScriptSmith merged commit 2e0089e into main May 4, 2026
18 of 21 checks passed
@ScriptSmith ScriptSmith deleted the prompt-api branch May 4, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant