Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 49 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,9 @@ const { isOpen, setOpen, lastContext } = useAskableKeyboardShortcut({

### Context sources

Register any combination of built-in sources — they're automatically composed into a single prompt string:
Sources expose app state the AI can't see in the DOM. Import from `@askable-ui/react/core` (or `vue/core`, `svelte/core`, etc.) for the essentials. Niche sources live in `@askable-ui/react/extended` and are fully tree-shakeable — they cost nothing if you don't import them.

**Core** (`@askable-ui/react/core`)

| Source hook | What it captures |
|---|---|
Expand All @@ -424,8 +426,38 @@ Register any combination of built-in sources — they're automatically composed
| `useAskableNavigationSource` | Current route, title, params, query, nav history |
| `useAskableDOMSource` | Any element: text, ARIA labels, data attributes |
| `useAskableStorageSource` | localStorage/sessionStorage items |
| `useAskableViewport` | Elements currently visible in the viewport |
| `useAskableHistory` | Navigation trail (last N focused elements) |
| `useAskableNotificationSource` | Active notifications, severity, messages |
| `useAskableCartSource` | Cart items, quantities, subtotal, tax, shipping, total |
| `useAskableMultistepSource` | Wizard/stepper — step name, index, progress, completion |

**Extended** (`@askable-ui/react/extended`)

| Source hook | What it captures |
|---|---|
| `useAskableScrollSource` | Scroll position, direction, progress percentage |
| `useAskableThemeSource` | Color scheme, contrast preference, motion preference |
| `useAskableWindowSource` | Window dimensions, device category, orientation |
| `useAskableLocaleSource` | Language, region, timezone, date format |
| `useAskableNetworkSource` | Connection type, effective speed, online status |
| `useAskableConnectionSource` | WebSocket/SSE connection status and protocol |
| `useAskableLoadingSource` | Named loading states (pending, success, error) |
| `useAskableSearchSource` | Query string, result count, filters, active status |
| `useAskableTabSource` | Active tab label, index, total tab count |
| `useAskableMediaSource` | Media title, playback state, position, duration |
| `useAskableSelectionSource` | Currently selected text or element |
| `useAskableClipboardSource` | Recent clipboard entries (type, preview, size) |
| `useAskableFocusSource` | Currently focused DOM element, role, ARIA label |
| `useAskableIdleSource` | User idle state and time since last interaction |
| `useAskableAnalyticsSource` | Recent analytics events (name, properties, timestamp) |
| `useAskableAbTestSource` | Active A/B test variants the user is enrolled in |
| `useAskableFeatureFlagSource` | Feature flag names and enabled/disabled values |
| `useAskablePermissionSource` | Browser permission states (camera, mic, notifications) |
| `useAskablePerformanceSource` | LCP, FID, CLS, TTFB, and custom timing metrics |
| `useAskableTimeSource` | Current time, timezone, business hours status |
| `useAskableBatterySource` | Battery level, charging state, estimated time |
| `useAskableGeolocationSource` | GPS coordinates and accuracy (with user permission) |

All sources are also available from the main entry point — the split is about clarity, not restriction.

---

Expand All @@ -446,11 +478,11 @@ Register any combination of built-in sources — they're automatically composed

| | Package | |
|---|---|---|
| React 18+ | `@askable-ui/react` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>`, region/text capture |
| Vue 3 | `@askable-ui/vue` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| Svelte 4 & 5 | `@askable-ui/svelte` | `createAskableStore()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| SolidJS | `@askable-ui/solid` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| Angular 16+ | `@askable-ui/angular` | `AskableService`, `AskablePageSourceService`, `AskableFormSourceService`, `AskableErrorSourceService`, `AskableUserSourceService`, `AskableNavigationSourceService`, `AskableAgentService`, `AskableDirective`, `AskableViewportService`, `AskableHistoryService` |
| React 18+ | `@askable-ui/react` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableCartSource()`, `useAskableMultistepSource()`, `useAskableScrollSource()`, `useAskableThemeSource()`, `useAskableWindowSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableTimeSource()`, `useAskableFocusSource()`, `useAskableTabSource()`, `useAskablePerformanceSource()`, `useAskableBatterySource()`, `useAskableGeolocationSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>`, region/text capture |
| Vue 3 | `@askable-ui/vue` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableCartSource()`, `useAskableMultistepSource()`, `useAskableScrollSource()`, `useAskableThemeSource()`, `useAskableWindowSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableTimeSource()`, `useAskableFocusSource()`, `useAskableTabSource()`, `useAskablePerformanceSource()`, `useAskableBatterySource()`, `useAskableGeolocationSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| Svelte 4 & 5 | `@askable-ui/svelte` | `createAskableStore()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableCartSource()`, `useAskableMultistepSource()`, `useAskableScrollSource()`, `useAskableThemeSource()`, `useAskableWindowSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableTimeSource()`, `useAskableFocusSource()`, `useAskableTabSource()`, `useAskablePerformanceSource()`, `useAskableBatterySource()`, `useAskableGeolocationSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| SolidJS | `@askable-ui/solid` | `useAskable()`, `useAskableAgent()`, `useAskableStream()`, `useAskableChat()`, `useAskableKeyboardShortcut()`, `useAskablePageSource()`, `useAskableFormSource()`, `useAskableTableSource()`, `useAskableErrorSource()`, `useAskableUserSource()`, `useAskableNavigationSource()`, `useAskableDOMSource()`, `useAskableStorageSource()`, `useAskableCartSource()`, `useAskableMultistepSource()`, `useAskableScrollSource()`, `useAskableThemeSource()`, `useAskableWindowSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableTimeSource()`, `useAskableFocusSource()`, `useAskableTabSource()`, `useAskablePerformanceSource()`, `useAskableBatterySource()`, `useAskableGeolocationSource()`, `useAskableViewport()`, `useAskableHistory()`, `<Askable>` |
| Angular 16+ | `@askable-ui/angular` | `AskableService`, `AskablePageSourceService`, `AskableFormSourceService`, `AskableErrorSourceService`, `AskableUserSourceService`, `AskableNavigationSourceService`, `AskableCartSourceService`, `AskableMultistepSourceService`, `AskableScrollSourceService`, `AskableThemeSourceService`, `AskableWindowSourceService`, `AskableLocaleSourceService`, `AskableNetworkSourceService`, `AskableTimeSourceService`, `AskableFocusSourceService`, `AskableTabSourceService`, `AskablePerformanceSourceService`, `AskableBatterySourceService`, `AskableGeolocationSourceService`, `AskableAgentService`, `AskableDirective`, `AskableViewportService`, `AskableHistoryService` |
| Qwik | `@askable-ui/qwik` | `useAskable()`, `<Askable>` for Qwik City apps |
| Web Component | `@askable-ui/web-component` | `<askable-context>` custom element, works in HTMX, Ember, vanilla HTML |
| React Native | `@askable-ui/react-native` | `useAskable()`, `<Askable>`, scroll view adapter |
Expand Down Expand Up @@ -735,6 +767,15 @@ Or open [`examples/vanilla-chat/index.html`](./examples/vanilla-chat/index.html)
- **Table awareness** — `useAskableTableSource()` exposes rows, visible page, selection, and table state for any table library
- **Error awareness** — `useAskableErrorSource()` captures validation errors and API failures; compatible with React Hook Form, Zod, VeeValidate
- **Page source** — `useAskablePageSource()` snapshots title, URL, headings, selected text, and links as a fallback for unannotated pages
- **Cart awareness** — `useAskableCartSource()` tracks ecommerce cart items, quantities, subtotal, discount, tax, shipping, and total; mutate with `addItem`, `removeItem`, `updateQuantity`, `setTotals`, `clearCart`
- **Wizard / stepper** — `useAskableMultistepSource()` tracks wizard progress: step name, index, total steps, completion percentage, and whether the flow is finished
- **Environment sources** — `useAskableScrollSource()`, `useAskableWindowSource()`, `useAskableThemeSource()`, `useAskableLocaleSource()`, `useAskableNetworkSource()`, `useAskableConnectionSource()`, `useAskablePermissionSource()` — the assistant knows the user's context without you describing it
- **Performance metrics** — `useAskablePerformanceSource()` exposes Core Web Vitals (LCP, FID, CLS, TTFB) and custom timing marks
- **Device sensors** — `useAskableBatterySource()` and `useAskableGeolocationSource()` for mobile-aware assistants
- **Time awareness** — `useAskableTimeSource()` provides current time, timezone, and configurable business hours status
- **Focus tracking** — `useAskableFocusSource()` reports the currently focused DOM element, ARIA role, and label
- **Navigation & tab state** — `useAskableTabSource()` for multi-tab UIs; `useAskableSearchSource()` for live search context
- **User behaviour** — `useAskableIdleSource()`, `useAskableAnalyticsSource()`, `useAskableAbTestSource()`, `useAskableFeatureFlagSource()` for session intelligence
- **Dev inspector** — `<AskableInspector />` overlay showing live context packets and source data
- **SSR safe** — defers to client lifecycle, no `window is not defined`
- **Zero runtime dependencies** in core
Expand Down
2 changes: 1 addition & 1 deletion examples/analytics-dashboard-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"start": "next start"
},
"dependencies": {
"@askable-ui/react": "^0.14.0",
"@askable-ui/react": "^0.15.0",
"@hookform/resolvers": "^3.9.1",
"@radix-ui/react-accordion": "1.2.12",
"@radix-ui/react-alert-dialog": "1.1.15",
Expand Down
2 changes: 1 addition & 1 deletion examples/angular-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@angular/platform-browser": "^19.2.0",
"@angular/platform-browser-dynamic": "^19.2.0",
"@angular/router": "^19.2.0",
"@askable-ui/angular": "^0.14.0",
"@askable-ui/angular": "^0.15.0",
"rxjs": "^7.8.1",
"zone.js": "^0.15.0"
},
Expand Down
2 changes: 1 addition & 1 deletion examples/mcp-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"dev": "node --watch server.js"
},
"dependencies": {
"@askable-ui/mcp": "^0.14.0",
"@askable-ui/mcp": "^0.15.0",
"express": "^4.21.0"
}
}
2 changes: 1 addition & 1 deletion examples/nextjs-app-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
},
"dependencies": {
"@ai-sdk/anthropic": "^1.2.12",
"@askable-ui/react": "^0.14.0",
"@askable-ui/react": "^0.15.0",
"ai": "^4.3.15",
"next": "^15.3.3",
"react": "^19.0.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/react-native-expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@askable-ui/core": "^0.14.0",
"@askable-ui/react-native": "^0.14.0",
"@askable-ui/core": "^0.15.0",
"@askable-ui/react-native": "^0.15.0",
"@react-navigation/native": "^7.2.5",
"@react-navigation/native-stack": "^7.16.0",
"expo": "^55.0.26",
Expand Down
2 changes: 1 addition & 1 deletion examples/solid-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"preview": "vite preview"
},
"dependencies": {
"@askable-ui/solid": "^0.14.0",
"@askable-ui/solid": "^0.15.0",
"solid-js": "^1.9.7"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@askable-ui/svelte": "^0.14.0",
"@askable-ui/svelte": "^0.15.0",
"svelte": "^5.0.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion examples/vercel-ai-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start": "next start"
},
"dependencies": {
"@askable-ui/react": "^0.14.0",
"@askable-ui/react": "^0.15.0",
"ai": "^4.3.16",
"@ai-sdk/openai": "^1.3.22",
"next": "^15.3.3",
Expand Down
2 changes: 1 addition & 1 deletion examples/vue-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@askable-ui/vue": "^0.14.0",
"@askable-ui/vue": "^0.15.0",
"vue": "^3.5.0"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "askable",
"version": "0.14.0",
"version": "0.15.0",
"private": true,
"workspaces": [
"packages/*"
Expand Down
12 changes: 10 additions & 2 deletions packages/angular/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/angular",
"version": "0.14.0",
"version": "0.15.0",
"description": "Angular service and directive to give AI assistants real-time context about what users see and select",
"type": "module",
"main": "./dist/index.js",
Expand All @@ -9,6 +9,14 @@
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./core": {
"import": "./dist/core.js",
"types": "./dist/core.d.ts"
},
"./extended": {
"import": "./dist/extended.js",
"types": "./dist/extended.d.ts"
}
},
"files": [
Expand Down Expand Up @@ -47,7 +55,7 @@
"@angular/core": ">=16.0.0"
},
"dependencies": {
"@askable-ui/core": "^0.14.0"
"@askable-ui/core": "^0.15.0"
},
"devDependencies": {
"@analogjs/vite-plugin-angular": "^1.18.3",
Expand Down
17 changes: 17 additions & 0 deletions packages/angular/src/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export { AskableService } from './askable.service.js';
export { AskableDirective } from './askable.directive.js';
export { AskableModule } from './askable.module.js';
export { AskableViewportService } from './askable-viewport.service.js';
export { AskableHistoryService } from './askable-history.service.js';
export { AskableAgentService } from './askable-agent.service.js';
export { useAskableCompose } from './use-askable-compose.js';
export { AskablePageSourceService } from './askable-page-source.service.js';
export { AskableFormSourceService } from './askable-form-source.service.js';
export { AskableErrorSourceService } from './askable-error-source.service.js';
export { AskableUserSourceService } from './askable-user-source.service.js';
export { AskableNavigationSourceService } from './askable-navigation-source.service.js';
export { AskableDOMSourceService } from './askable-dom-source.service.js';
export { AskableStorageSourceService } from './askable-storage-source.service.js';
export { AskableNotificationSourceService } from './askable-notification-source.service.js';
export { AskableCartSourceService } from './askable-cart-source.service.js';
export { AskableMultistepSourceService } from './askable-multistep-source.service.js';
22 changes: 22 additions & 0 deletions packages/angular/src/extended.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export { AskableMediaSourceService } from './askable-media-source.service.js';
export { AskableScrollSourceService } from './askable-scroll-source.service.js';
export { AskableSelectionSourceService } from './askable-selection-source.service.js';
export { AskableClipboardSourceService } from './askable-clipboard-source.service.js';
export { AskableNetworkSourceService } from './askable-network-source.service.js';
export { AskableThemeSourceService } from './askable-theme-source.service.js';
export { AskableWindowSourceService } from './askable-window-source.service.js';
export { AskableLocaleSourceService } from './askable-locale-source.service.js';
export { AskablePermissionSourceService } from './askable-permission-source.service.js';
export { AskableFeatureFlagSourceService } from './askable-feature-flag-source.service.js';
export { AskableAnalyticsSourceService } from './askable-analytics-source.service.js';
export { AskableAbTestSourceService } from './askable-ab-test-source.service.js';
export { AskableConnectionSourceService } from './askable-connection-source.service.js';
export { AskableLoadingSourceService } from './askable-loading-source.service.js';
export { AskableIdleSourceService } from './askable-idle-source.service.js';
export { AskableSearchSourceService } from './askable-search-source.service.js';
export { AskableTabSourceService } from './askable-tab-source.service.js';
export { AskablePerformanceSourceService } from './askable-performance-source.service.js';
export { AskableBatterySourceService } from './askable-battery-source.service.js';
export { AskableGeolocationSourceService } from './askable-geolocation-source.service.js';
export { AskableTimeSourceService } from './askable-time-source.service.js';
export { AskableFocusSourceService } from './askable-focus-source.service.js';
2 changes: 1 addition & 1 deletion packages/context/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/context",
"version": "0.14.0",
"version": "0.15.0",
"description": "Open Context packet types and schema for AI-native interfaces",
"type": "module",
"main": "./dist/index.js",
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/core",
"version": "0.14.0",
"version": "0.15.0",
"description": "Give AI assistants real-time context about what users see and select in your UI",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -45,7 +45,7 @@
"homepage": "https://askable-ui.com",
"license": "MIT",
"dependencies": {
"@askable-ui/context": "^0.14.0"
"@askable-ui/context": "^0.15.0"
},
"devDependencies": {
"jsdom": "^29.1.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/create-askable-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/create-app",
"version": "0.14.0",
"version": "0.15.0",
"description": "Scaffold an AI-native app with askable-ui — React, Vue, Svelte, or Next.js in one command",
"type": "module",
"bin": {
Expand Down
6 changes: 3 additions & 3 deletions packages/mcp/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/mcp",
"version": "0.14.0",
"version": "0.15.0",
"description": "MCP server and page bridge to expose UI context to Claude Desktop, Cursor, and any MCP client",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -43,8 +43,8 @@
"homepage": "https://askable-ui.com",
"license": "MIT",
"dependencies": {
"@askable-ui/context": "^0.14.0",
"@askable-ui/core": "^0.14.0",
"@askable-ui/context": "^0.15.0",
"@askable-ui/core": "^0.15.0",
"@modelcontextprotocol/sdk": "^1.29.0",
"zod": "^4.4.3"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/qwik/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@askable-ui/qwik",
"version": "0.14.0",
"version": "0.15.0",
"description": "Qwik hooks and components to give AI assistants real-time context about what users see and select",
"type": "module",
"main": "./dist/index.js",
Expand Down Expand Up @@ -46,7 +46,7 @@
"@builder.io/qwik": ">=1.0.0"
},
"dependencies": {
"@askable-ui/core": "^0.14.0"
"@askable-ui/core": "^0.15.0"
},
"devDependencies": {
"@builder.io/qwik": "^1.14.1",
Expand Down
Loading
Loading