diff --git a/README.md b/README.md
index b29a8b9..aade1e2 100644
--- a/README.md
+++ b/README.md
@@ -2,20 +2,31 @@
Synapse is a Vite + React + TypeScript application that turns complex content into accessible experiences using Chrome's built-in AI APIs. The application provides interactive demos and practical implementations of Chrome's Rewriter, Translator, and Prompt APIs with robust error handling, streaming support, and production-ready service wrappers.
-## Getting Started
+## Prerequisites
+
+- Node.js 18+ (LTS recommended) and npm 9+
+- Chrome Canary/Dev 130+ with the Chrome Built-in AI origin trial enabled
+- Valid Origin Trial token configured in `.env` (`VITE_CHROME_AI_ORIGIN_TRIAL_TOKEN`)
+- `chrome://flags/#optimization-guide-on-device-model` set to **Enabled**
+
+## Setup
1. **Install dependencies**
```bash
npm install
```
-2. **Configure Chrome AI origin trial**
- - Request a token from [Chrome Origin Trials](https://developer.chrome.com/origintrials/#/trials/active).
- - Create a `.env` file based on `.env.example` and paste the token in `VITE_CHROME_AI_ORIGIN_TRIAL_TOKEN`.
-3. **Run the dev server**
+2. **Create environment file**
+ ```bash
+ cp .env.example .env
+ ```
+3. **Configure Chrome AI origin trial**
+ - Request a token from [Chrome Origin Trials](https://developer.chrome.com/origintrials/#/trials/active)
+ - Paste the token into `.env` under `VITE_CHROME_AI_ORIGIN_TRIAL_TOKEN`
+4. **Run the dev server**
```bash
npm run dev
```
-4. **Open in Chrome Canary** at the URL printed in the terminal (default `http://localhost:5173`). Ensure the matching origin trial flag is enabled.
+5. **Open in Chrome Canary/Dev** at the printed URL (default `http://localhost:5173`). Ensure the origin trial flag remains enabled and the token is valid for the local domain.
## User Documentation
@@ -119,6 +130,8 @@ npm run test:e2e:ui # E2E interactive mode
- **Local storage:** Namespaced helpers (`createLocalStorageNamespace`) and `preferencesStorage` wrapper
- **Chrome AI readiness:** Origin trial token support via `` tag with comprehensive capability detection
+For diagrams and deeper explanations of each layer, read [`docs/architecture.md`](docs/architecture.md).
+
## Project Structure
```
@@ -162,7 +175,9 @@ Each demo includes:
- Browser compatibility checks
- Comprehensive diagnostics
-## Scripts
+## Developer Workflow
+
+Use the npm scripts below while iterating. Build and lint commands should pass before you open a pull request.
- `npm run dev` – Start Vite dev server.
- `npm run build` – Type-check and build for production.
@@ -524,3 +539,8 @@ You can verify our privacy claims by:
- Implement Writer & Proofreader API demos
- Integrate state management (Zustand) for cross-component state
- Add visual regression testing (Percy/Chromatic)
+
+## Additional Documentation
+- [`docs/architecture.md`](docs/architecture.md) – Layer breakdown, data flow, and diagrams.
+- [`docs/chrome-ai-apis.md`](docs/chrome-ai-apis.md) – Chrome AI service contracts, initialization steps, and troubleshooting.
+- [`docs/adr`](docs/adr) – Architecture decision records for foundational choices.
\ No newline at end of file
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..5cf6f9b
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,82 @@
+# Architecture Overview
+
+Synapse is a single-page application built with Vite, React, and TypeScript. The frontend keeps all business logic on the client and wraps Chrome's built-in AI APIs with a resilient service layer that exposes ergonomic hooks to the UI. This document explains how the pieces fit together so new contributors can reason about data flow quickly.
+
+## High-Level Flow
+
+```mermaid
+graph TD
+ subgraph UI
+ Routes[React Router
Route Tree]
+ Components[UI Components
Pages & Layouts]
+ end
+ subgraph State
+ Hooks[Custom React Hooks]
+ Storage[Preferences Storage
Local Storage Namespace]
+ end
+ subgraph Services
+ Wrapper[Chrome AI Service Layer]
+ Utils[Validation & Sanitization
File Processing Utilities]
+ Errors[Global Error Reporting]
+ end
+ subgraph Platform
+ ChromeAPIs[Chrome Built-in AI APIs
Prompt · Rewriter · Translator · Writing Tools]
+ end
+
+ Routes --> Components
+ Components --> Hooks
+ Hooks --> Wrapper
+ Wrapper --> ChromeAPIs
+ ChromeAPIs --> Wrapper
+ Wrapper --> Hooks
+ Hooks --> Components
+ Hooks --> Storage
+ Utils --> Wrapper
+ Wrapper --> Errors
+```
+
+### Layers
+
+- **Routing & Layout (`src/routes`, `src/components/layout`)**: `AppLayout` composes global chrome (header/footer) while `React Router` v7 mounts feature pages such as the Workspace and Demos hub. Each route is wrapped in the `RouteErrorBoundary` to surface Chrome AI failures.
+- **UI Components (`src/components`)**: Feature-specific components (file uploaders, writing tool panes) depend on hooks for state and never call Chrome AI APIs directly.
+- **Hooks (`src/hooks`)**: Hooks encapsulate state management, orchestration, and side-effects. They call service classes, expose request state, and consolidate analytics / logging. Examples include `useWritingTools`, `useRewriter`, and `useContentExtraction`.
+- **Service Layer (`src/lib/chrome-ai/services`)**: TypeScript classes (`PromptService`, `RewriterService`, `TranslatorService`, `WritingToolsService`) manage API sessions, retries, streaming, and structured outputs. They depend on shared utilities for validation (`src/lib/chrome-ai/utils`) and sanitize user-provided input before passing it to the browser APIs.
+- **Error Handling (`src/lib/errors`)**: Central utilities (`reportError`, `registerGlobalHandlers`, `AppErrorBoundary`) normalize errors from Chrome AI APIs, chunking pipelines, and network calls. Services wrap low-level exceptions into domain-specific error classes with actionable messages.
+- **Platform Integration (`src/lib/chrome-ai`)**: Capability detection, origin trial injection, and browser compatibility messaging reside here. `detectChromeAiCapabilities` and `browserCompatibility` helpers drive the badges and warnings rendered in the UI.
+
+## Workspace Data Flow
+
+1. **Input Acquisition**
+ Users provide text by typing, uploading TXT/PDF/DOCX files, or extracting content from URLs. `useTextInput`, `useFileUpload`, and `useContentExtraction` own these flows. File uploads run through MIME checks, magic number validation, and asynchronous extraction (PDF.js, Mammoth) before sanitized text hits application state.
+
+2. **Capability Negotiation**
+ When a user triggers an AI operation, hooks call `detectChromeAiCapabilities` to verify the requested API is available. Results feed UI affordances (disabled buttons, tooltips) and error boundaries.
+
+3. **Service Invocation**
+ Hooks call the corresponding service method (`RewriterService.simplify`, `TranslatorService.translateStream`, `PromptService.prompt`, etc.). Services:
+ - Initialize the Chrome AI session on demand (with retries and progress monitoring).
+ - Validate input length / content and sanitize untrusted strings.
+ - Stream results back via async iterators where available, emitting partial responses to the UI.
+
+4. **Result Presentation**
+ Hooks update React state with incremental or final payloads. Components render formatted diffs, translation tables, or streaming transcripts while showing timing/status indicators. Errors are surfaced through standardized toasts and inline callouts.
+
+5. **Persistence & Preferences**
+ `preferencesStorage` (namespaced local storage) keeps track of user theme, last-used writing tool, and workspace settings. Hooks read/write preferences via the helper to avoid key collisions.
+
+## Build & Deployment Pipeline
+
+- **Vite + TypeScript** compile client code to ES modules served by the dev server or bundled for production (`npm run build`).
+- **Tailwind CSS** generates scoped utility classes via PostCSS. Theme tokens are configured in `tailwind.config.js`.
+- **ESLint & TypeScript** enforce code quality (`npm run lint`). Build scripts fail fast on type errors because `tsc -b` runs before bundling.
+- **Service Worker** registration happens in production builds to allow future offline support, but the worker is optional during local development.
+
+## Key Architectural Decisions
+
+Existing Architecture Decision Records live under `docs/adr`. Review them before making cross-cutting changes:
+
+- `0001-foundational-stack.md` – Explains the Vite + React + Tailwind selection.
+- `0002-error-handling-and-storage.md` – Details the shared error reporting surface and local-storage namespacing pattern.
+
+Refer to the [Chrome AI API Integration Guide](./chrome-ai-apis.md) for protocol-level details, request lifecycles, and troubleshooting flow charts.
+
diff --git a/docs/chrome-ai-apis.md b/docs/chrome-ai-apis.md
new file mode 100644
index 0000000..ff9a8d5
--- /dev/null
+++ b/docs/chrome-ai-apis.md
@@ -0,0 +1,76 @@
+# Chrome AI API Integration Guide
+
+This document dives into how Synapse integrates Chrome's built-in AI APIs so you can extend or debug the service layer confidently. The application uses the Origin Trial versions of the Prompt, Rewriter, Translator, Language Detector, Writer, and Proofreader APIs (where available).
+
+## Browser Requirements
+
+- **Chrome 130+ (Canary/Dev/Beta)** with the "Built-in AI" origin trial token applied through the `` tag injected at runtime by `injectChromeAiOriginTrial`.
+- **Origin Trial Token** stored in `.env` as `VITE_CHROME_AI_ORIGIN_TRIAL_TOKEN`. Tokens are domain-specific and expire; generate a new one from the [Chrome Origin Trials dashboard](https://developer.chrome.com/origintrials/#/trials/active) as needed.
+- **Feature Flags**: Ensure the matching Chrome flag is enabled (`chrome://flags/#optimization-guide-on-device-model`). The docs site surfaces compatibility warnings when detection fails.
+
+## Capability Detection
+
+All entry points check API availability via `detectChromeAiCapabilities` and `detectChromeAiAvailabilityStatus` (`src/lib/chrome-ai/capabilities.ts`). These helpers:
+
+1. Inspect the global `self` object to confirm each API is present.
+2. Call the `availability()` methods exposed by Chrome to verify the model is either `available` or `downloadable`.
+3. Emit semantic booleans used by UI badges and guard clauses in the hooks.
+
+When you add new integrations, extend the detection maps so the UI can reflect their state automatically.
+
+## Service Layer Overview
+
+Each Chrome API is wrapped with a dedicated service class that normalizes inputs, handles retries, and exposes streaming iterators where supported. Services live in `src/lib/chrome-ai/services` and share common utilities:
+
+- **Validation** (`utils/validator.ts`) ensures character counts and banned content rules are respected before hitting the API.
+- **Sanitization** (`utils/sanitizer.ts`) strips untrusted HTML and zero-width characters to avoid model hallucination issues.
+- **Retry Logic** (`utils/retryHandler.ts`) replays transient failures (e.g., `MODEL_NOT_READY`) with exponential backoff.
+- **Error Types** (`errors/*.ts`) wrap native exceptions in domain-specific errors surfaced by the UI and error telemetry.
+
+### Prompt API (`PromptService`)
+
+- **Initialization**: `PromptService.initialize` creates a `LanguageModel` session. Optional hooks configure `initialPrompts`, `temperature`, `topK`, expected input/output schemas, and download monitoring callbacks.
+- **Prompting**: `prompt` sends a single message and returns the response string. Use `promptStream` to iterate over streaming chunks (async generator). The service tracks conversation history, so successive calls preserve context unless you call `reset`.
+- **Session Management**: `cloneSession` enables lightweight branching, while `destroy` tears down the model to release memory. Hooks call `destroy` on unmount to avoid leaking sessions in Chrome.
+
+### Rewriter API (`RewriterService`)
+
+- **Simplification & Tone**: `simplify`, `simplifyProgressively`, and `adjustTone` wrap the multi-level rewriting APIs. The service supports chunked inputs through `enableChunking`, retrying failed chunks automatically.
+- **Streaming**: `rewriteStream` exposes partial results so the UI can show incremental updates.
+- **Content Safety**: Input validation enforces length and banned phrase requirements before they are forwarded to Chrome.
+
+### Translator API (`TranslatorService`)
+
+- **Initialization**: `translator.initialize(sourceLang, targetLang)` returns a session configured for specific languages. The service auto-detects source language if `null` and exposes `setLanguages` to pivot during a session.
+- **Usage**: `translate` returns the full translation. `translateStream` yields incremental `TranslatorResponseChunk` payloads to power the UI's streaming table.
+- **Fallbacks**: When the API reports `downloadable`, the service surfaces progress events via the `monitor` callback and shows actionable messages in the UI.
+
+### Writing Tools (`WritingToolsService`)
+
+The writing tools facade composes both Prompt and Rewriter services to deliver higher-level operations:
+
+- **Proofreading**: Uses the Prompt API with structured output to return a `ProofreadResult` containing corrections, statistics, and diff-ready change objects.
+- **Tone Adjustment & Summaries**: Leverage the Rewriter API for tone transformations and summarization with chunked inputs.
+- **Key Points & Suggestions**: High-level prompts that transform model output into typed arrays for the UI to render (importance tagging, categories, priority).
+
+The service memoizes initialization via an internal promise so concurrent requests do not race. It sanitizes and validates inputs, then aggregates final responses from both underlying services.
+
+### Format & Image Analysis
+
+Supporting services (`FormatTransformService`, `ImageAnalysisService`) handle experimental APIs behind feature flags. They are structured the same way—initialize -> process -> stream—and are safe extension points for future Chrome releases.
+
+## Error Handling & Telemetry
+
+- `reportError` routes enriched error objects to console logging today, but it is built to integrate with telemetry providers. Always wrap low-level exceptions so we can react to specific Chrome error codes.
+- User-cancelled operations throw `AbortError` instances wrapped by custom error classes. Hooks translate these into friendly UI notifications.
+- Chrome often returns `downloadable` before the model finishes downloading. The service layer surfaces `AIModelDownloadProgress` events through optional `monitor` callbacks so the UI can display progress bars.
+
+## Debugging Tips
+
+1. **Inspect Capabilities**: Visit `/demos` and open DevTools → Console to see the structured capability object printed whenever detection runs.
+2. **Reset Sessions**: If you suspect a stale session, call the relevant service's `destroy()` method and initialize again.
+3. **Verbose Logging**: Temporarily add `console.debug` inside service catch blocks while iterating; the retry helper swallows some errors by design after max attempts.
+4. **Origin Trial Issues**: If every capability reports `unavailable`, confirm the token is valid, matches the hostname, and has not expired.
+
+Refer back to [docs/architecture.md](./architecture.md) for an overview of how these services connect to the rest of the application.
+
diff --git a/src/lib/chrome-ai/services/RewriterService.ts b/src/lib/chrome-ai/services/RewriterService.ts
index ffe9513..dc54547 100644
--- a/src/lib/chrome-ai/services/RewriterService.ts
+++ b/src/lib/chrome-ai/services/RewriterService.ts
@@ -591,6 +591,8 @@ export class RewriterService {
}
private mergeContextSegments(...segments: Array): string | undefined {
+ // Chrome's rewriter context becomes unstable beyond ~1k characters, so we clamp combined hints
+ // to keep prompts deterministic even when multiple sections contribute extra instructions.
const cleaned = segments
.map((segment) => segment?.trim())
.filter((segment): segment is string => Boolean(segment))
@@ -658,7 +660,8 @@ export class RewriterService {
options?: AIRewriteOptions,
onProgress?: (current: number, total: number) => void
): Promise {
- // Split into chunks
+ // Chrome's Rewriter API enforces payload caps (~8k tokens); chunkText() slices input into
+ // ordered segments with overlap so we can process long documents without hitting hard limits.
const chunks = chunkText(content)
const processedChunks: TextChunk[] = []
@@ -666,7 +669,7 @@ export class RewriterService {
for (let i = 0; i < chunks.length; i++) {
const chunk = chunks[i]
- // Build options with chunk context
+ // Preserve continuity by threading the previous chunk summary into the context payload.
const chunkOptions: AIRewriteOptions = {
...options,
context: this.mergeContextSegments(