feat: new context source hooks, streaming chat, and framework parity#337
Open
vamgan wants to merge 95 commits into
Open
feat: new context source hooks, streaming chat, and framework parity#337vamgan wants to merge 95 commits into
vamgan wants to merge 95 commits into
Conversation
…lback safety - capture.ts: call removeAffordance() before re-rendering the selection affordance so repeated captures with once:false don't accumulate DOM nodes - mcp/index.ts: add requireRedacted option that blocks forwarding packets where privacy.redacted===false, preventing unredacted data reaching the MCP client; add corresponding tests - useAskableScrollView.ts: wrap selectVisible/getMeta/getText callbacks in try/catch so a consumer-thrown exception cannot halt scroll sync
…n exceptions - context.ts subscribe(): add try/catch around the sync subscriber callback to match the existing protection in subscribeAsync(); prevents a throwing subscriber from crashing the observer chain - selection.ts: move destroy() before onCapture invocation and wrap the callback in try/catch so an exception in user code never leaves selection listeners dangling - capture.ts: remove duplicate removeAffordance() call introduced during the previous commit; single call is sufficient and idempotent
…h try/catch - capture.ts: guard onCapture, onCancel, and onSubmit callbacks so a consumer exception cannot propagate into internal pointer/key event handlers or leave the DOM in an inconsistent state - selection.ts: guard onCancel so a throwing consumer cannot leave the cancel path half-executed; matches the onCapture fix from the previous commit
…wn exceptions Wrap the user-supplied affordance render function in try/catch so an exception does not interrupt the post-capture flow or leave internal state inconsistent.
…la demo README: - New punchy headline: "Your LLM doesn't know what the user is looking at. Fix that in two lines." - Lead with "What the AI receives" — shows actual promptContext output upfront - Before/after comparison showing the problem (stale system prompt) vs the solution - Prominent MCP section with 3-line setup and Claude Desktop config - Better organized sections: capture modes, integrations table, framework quick starts - Links to vanilla-chat example as zero-install demo examples/vanilla-chat/index.html: - Zero-install single-file demo that opens directly in any browser - Full analytics dashboard (3 KPI cards, 4-row deal table) with data-askable - Real-time "What the AI sees" panel showing live promptContext - Mock AI chat that generates context-accurate responses from the actual data - Copy context button, keyboard navigation, beautiful dark-mode design - Loads @askable-ui/core from CDN — no build step site/www/index.html: - Updated page title and OG/Twitter meta tags with sharper copy - Hero eyebrow: "Claude Desktop · Cursor · CopilotKit · any LLM" (was generic) - Hero body paragraph: problem-first framing (no screenshots, no guessing) - Nav: added MCP link, removed redundant Patterns/Integrations links - Integrations section: added Claude Desktop and Cursor as MCP client cards (5 total) - New MCP section with code examples, Claude Desktop config, and feature cards - CTA: "Your AI. Your UI. Finally connected." + Live demo link added - Footer: MCP guide and Live demo links added
Minimal Vue 3 + Vite demo showing the core askable-ui pattern: - <Askable :meta="..."> keeps data-askable in sync with reactive props - useAskable() composable returns promptContext ref that auto-updates - Live "What the AI sees" panel showing the actual context string - Mock AI chat demonstrating how specific and accurate responses become when the AI has real context (NRR/pipeline/deals with actual values) Includes README with real-LLM wiring instructions for OpenAI/Anthropic.
… links - vanilla-chat/README.md: explains zero-install approach, how CDN import works, and shows how to connect to a real LLM API (OpenAI/Anthropic) - README.md: fix @askable/react → @askable-ui/react import typo - README.md: expand Live links section with Vue, React Native, analytics dashboard, and vanilla examples with one-liner descriptions
…ophy, and good first issues
Exposes all [data-askable] elements currently visible in the viewport as reactive React state via IntersectionObserver + MutationObserver. - Standalone hook — no dependency on useAskable - Optional root, threshold, and scope filter options - promptContext string ready for direct LLM injection - Full test suite (6 cases)
Port of the React hook to Vue 3 — reactive ref tracking all visible [data-askable] elements via IntersectionObserver + MutationObserver. Supports root, threshold, and scope filter options. Includes 5 tests.
Minimal Next.js 15 app showing the 4-step askable-ui + Vercel AI SDK
integration: annotate → useAskable() → body:{uiContext} → system prompt.
Works with any AI SDK provider. Includes full README with cross-framework
usage notes (LangChain, raw OpenAI SDK).
Also adds useAskableViewport to the Vue and React README examples tables.
Svelte 5: useAskableViewport() runes composable exported via @askable-ui/svelte/useAskableViewport.svelte Svelte 4: createAskableViewportStore() exported from the main @askable-ui/svelte entrypoint Same IntersectionObserver + MutationObserver approach as the React and Vue implementations, completing cross-framework parity.
Tracks the last N focused elements as a navigation trail with: - history: AskableFocus[] (newest first, capped at maxEntries) - current: AskableFocus | null - promptContext: formatted trail string for LLM injection - Deduplication of consecutive identical entries (opt-out via dedupe:false) - 8 tests covering trail ordering, dedupe, cap, clear, and prompt format
Vue 3: useAskableHistory() composable (5 tests) Svelte 5: useAskableHistory() runes composable via useAskableHistory.svelte Svelte 4: createAskableHistoryStore() exported from main entrypoint All three match the React implementation: navigation trail, dedupe, maxEntries cap, promptContext string for LLM injection.
Updates the frameworks table and adds new sections for viewport context and navigation history hooks in the Capture modes section.
Composes focus, viewport, history, and any other context sources into one prompt-ready string. Sections with empty values are automatically skipped. Used in the vercel-ai-sdk example to show all three streams combined into a single system prompt injection. 5 tests covering section filtering, separator, and fallback.
Surfaces useAskableViewport, useAskableHistory, useAskableCompose in the landing page package cards and adds a Composing context streams section to the README.
Cast focus.meta to a typed object without runtime overhead.
Zero-cost cast for TypeScript users who control their data-askable schemas.
interface KpiMeta { metric: string; value: string; delta: string }
const typed = asMeta<KpiMeta>(focus);
typed.meta.value // → string, not unknown
asMeta<T>() and TypedAskableFocus<T> are now importable directly from @askable-ui/react, @askable-ui/vue, and @askable-ui/svelte. Adds a 'Typed meta (TypeScript)' section to the README.
New SolidJS adapter with full feature parity: - useAskable() — reactive focus + promptContext signal - useAskableViewport() — IntersectionObserver-based viewport tracking - useAskableHistory() — navigation trail with dedupe + maxEntries cap - <Askable> — wrapper component using Dynamic for flexible 'as' prop - asMeta<T>() re-export for typed meta access - 9 tests (Askable component + useAskable hook) Adds SolidJS to the README frameworks table, quick starts section, CONTRIBUTING project structure, and the feature request issue template.
- useAskableCompose() added to @askable-ui/vue (computed-based) - useAskableCompose() added to @askable-ui/solid (createMemo, accepts reactive accessor to correctly track Solid signals) - examples/solid-dashboard/ — full Vite + SolidJS dashboard showing useAskable, useAskableViewport, useAskableHistory, useAskableCompose, and asMeta<T> with a live context inspector sidebar - README examples table updated, landing page adds @askable-ui/solid card
Svelte 5 version accepts a reactive function/accessor so $derived
correctly tracks rune reads. Exported via:
import { useAskableCompose } from '@askable-ui/svelte/useAskableCompose.svelte'
…e, and services Implements the Angular 16+ framework adapter: - AskableService — root injectable wrapping createAskableContext(), exposes Angular signals - AskableDirective — [askable] attribute directive serialising meta to data-askable - AskableViewportService — IntersectionObserver-based visible elements tracking - AskableHistoryService — navigation history with maxEntries and dedupe - useAskableCompose() — Signal<section[]>-based context composer (computed-reactive) - AskableModule — NgModule for non-standalone apps - 16 passing tests using TestBed + @analogjs/vite-plugin-angular Adds angular-dashboard example and updates README, CONTRIBUTING, and landing page.
Exposes recent analytics events to AI assistants so they understand the user's journey — what they clicked, visited, or triggered — before asking for help. Compatible with Segment, Mixpanel, Amplitude, PostHog, and custom event systems via a track() function. - core: createAskableAnalyticsSource with getSnapshot pattern, 8 tests - react: useAskableAnalyticsSource with useState event buffer + track() - vue: useAskableAnalyticsSource with ref + track() - solid: useAskableAnalyticsSource with createSignal + track() - svelte: useAskableAnalyticsSource.svelte.ts with $state + track() - All framework indices updated
Exposes A/B test variant assignments to AI assistants so they can explain why a user sees a different UI, debug experiment-related issues, and answer questions about feature availability under test conditions. - core: createAskableAbTestSource — accepts getExperiments(), separates treatments/controls, 8 tests. Compatible with Optimizely, LaunchDarkly, PostHog experiments, Statsig, GrowthBook, or any custom A/B system - react: useAskableAbTestSource — notifies on experiments prop change - vue: useAskableAbTestSource — deep-watches reactive experiments ref - solid: useAskableAbTestSource — createEffect tracks signal accessor - svelte: useAskableAbTestSource.svelte.ts — $effect tracks getter - All framework indices updated
Exposes WebSocket / SSE / polling connection state to AI assistants so they can explain why real-time features aren't updating, diagnose dropped connections, and guide reconnection. Includes a setStatus() helper that manages state transitions with timestamps and reconnect tracking. - core: createAskableConnectionSource with getSnapshot pattern, 8 tests - react: useAskableConnectionSource with useState + setStatus() helper - vue: useAskableConnectionSource with ref + setStatus() helper - solid: useAskableConnectionSource with createSignal + setStatus() helper - svelte: useAskableConnectionSource.svelte.ts with $state + setStatus() - All framework indices updated
Tracks named loading operations (start/finish/error) and exposes them to AI assistants so they can explain why the UI is loading, diagnose slow requests and failed data fetches, and describe error states with timing information. - core: createAskableLoadingSource — getSnapshot pattern, supports operations/loading/loaded/errored arrays, duration tracking, 8 tests - react: useAskableLoadingSource — Map-based op tracking + start/finish/error/clear - vue: useAskableLoadingSource — same API with ref - solid: useAskableLoadingSource — same API with createSignal - svelte: useAskableLoadingSource.svelte.ts — same API with $state - All framework indices updated
Detects user idleness via DOM activity events (mousemove, keydown, etc.) and exposes the state to AI assistants so they can understand session inactivity, explain why a session expired, and trigger context-aware prompts. - core: createAskableIdleSource — getSnapshot pattern, 8 tests, configurable idle threshold with isIdle/isActive/idleSeconds/lastActiveAt - react: useAskableIdleSource — useEffect for activity listeners + 5s interval - vue: useAskableIdleSource — onMounted/onUnmounted lifecycle - solid: useAskableIdleSource — createEffect + onCleanup - svelte: useAskableIdleSource.svelte.ts — onMount/onDestroy + $state - All framework indices updated
Tracks active search state (query, result count, filters, sort) and exposes it to AI assistants so they can explain empty results, suggest alternative queries, and understand what the user is looking for. - core: createAskableSearchSource with getSnapshot pattern, 9 tests. Describes no-results clearly, includes filter and sort state - react/vue/solid/svelte: setQuery/setResults/setSearching/setFilters/setSort/reset - All framework indices updated
Adds Injectable Angular services for all context sources added since the last Angular update, bringing Angular to full parity with React/Vue/Solid/Svelte. New services: - AskableNetworkSourceService — online/offline + connection type, auto-tracks events - AskableThemeSourceService — OS color scheme, contrast, motion preferences - AskableWindowSourceService — viewport dimensions, breakpoint, orientation - AskableLocaleSourceService — locale, timezone, currency, date format - AskablePermissionSourceService — browser permissions with async refresh() - AskableFeatureFlagSourceService — feature flag state with getFlags getter - AskableAnalyticsSourceService — event buffer with track() method - AskableAbTestSourceService — A/B variant assignments with getExperiments getter - AskableConnectionSourceService — WebSocket/SSE state with setStatus() helper - AskableLoadingSourceService — named loading ops with start/finish/error/clear - AskableIdleSourceService — user idle detection with markActive() and interval - AskableSearchSourceService — search state with setQuery/setResults/setFilters
Adds tab visibility context source across all frameworks. AI assistants can now detect when users switch away from the tab and understand why real-time features paused, with hide count and hidden duration tracking. - core: createAskableTabSource factory + 9 tests (all passing) - React: useAskableTabSource hook with visibilitychange listener - Vue: useAskableTabSource composable with onMounted/onUnmounted - Solid: useAskableTabSource primitive with createEffect/onCleanup - Svelte 5: useAskableTabSource.svelte.ts with $state + onMount/onDestroy - Angular: AskableTabSourceService with automatic document event cleanup
…DOM sources Fills in the remaining Angular service gaps. These services mirror the existing React/Vue/Solid/Svelte hooks and complete full-framework coverage for all sources. - AskableClipboardSourceService: auto-tracks copy events, addEntry/clear helpers - AskableStorageSourceService: thin wrapper around createAskableStorageSource - AskableNotificationSourceService: add/remove/clear/setNotifications management - AskableDOMSourceService: accepts ElementRef, element, or getter function
Enables AI assistants to proactively diagnose slow page loads and poor Core Web Vitals ratings across all frameworks. - core: createAskablePerformanceSource + rateMetric helper + 10 tests - Navigation timing: loadTime, TTFB, domContentLoaded, dns, connect - Memory info (Chrome): usedMB, totalMB, limitMB - Automatic Good/Needs-improvement/Poor ratings per Google thresholds - addMetric() API integrates with web-vitals library (LCP, FID, CLS, INP, FCP) - React/Vue/Solid/Svelte hooks + Angular AskablePerformanceSourceService
Enables AI assistants to warn users about low battery before starting long operations like file exports, data migrations, or video renders. - core: createAskableBatterySource + getBatteryStatus + formatDuration helpers + 9 tests - status: critical (<15%), low (<30%), medium (<60%), high (<100%), full - auto-subscribes to levelchange, chargingchange, chargingtimechange events - React/Vue/Solid/Svelte hooks + Angular AskableBatterySourceService
Enables AI assistants to provide location-aware assistance — nearest stores, delivery estimates, timezone-aware scheduling, and geofence-based features. - core: createAskableGeolocationSource + 9 tests - Tracks coords, accuracy, heading, speed, permissionState, and error - autoRequest and watch modes for one-shot or continuous tracking - requestPosition() for manual on-demand location requests - React/Vue/Solid/Svelte hooks + Angular AskableGeolocationSourceService
…acking Enables AI assistants to give time-aware assistance — knowing the user's local time, timezone, whether they're within business hours, and how long they've been in the current session. - core: createAskableTimeSource + buildTimeSnapshot helper + 9 tests - Tracks: local time, IANA timezone, UTC offset, dayOfWeek, isWeekend - isBusinessHours: configurable start/end hours and working days - sessionSeconds: time elapsed since page load - intervalMs option: auto-refresh interval (default 60s) - React/Vue/Solid/Svelte hooks + Angular AskableTimeSourceService
Enables AI assistants to know which element the user is working on, providing targeted help for form fields, buttons, and interactive elements. - core: createAskableFocusSource + elementToFocusSnapshot helper + 9 tests - Captures: tag, id, label, role, name, type, value, classes, isFormField - focusChangeCount and lastChangedAt for focus history context - focusout uses setTimeout to avoid false "no focus" during tab navigation - React/Vue/Solid/Svelte hooks + Angular AskableFocusSourceService
Tracks multi-step wizard, stepper, and checkout flow state across all frameworks so AI assistants can guide users through complex processes. Exports next/prev/goTo/complete/setError/reset across React, Vue, Solid, Svelte, and Angular. Core buildMultistepSnapshot computes progress, completion, and step metadata from a shared snapshot pattern.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A large batch of new hooks, examples, and documentation aimed at making
askable-uisolve common AI-assistant-in-the-UI problems out of the box.New context source hooks (core + all frameworks)
useAskableFormSourceuseAskableTableSourceuseAskableErrorSourceuseAskableUserSourceAll four hooks are implemented across React, Vue 3, SolidJS, Svelte 5 (runes), and Angular (service pattern). Core primitives (
createAskableFormSource,createAskableErrorSource,createAskableUserSource) are framework-agnostic in@askable-ui/core.Streaming chat
useAskableChat— multi-turn conversation hook with automatic context injection per turn, system prompt factory,clearMessages(), andabort(). Implemented across React, Vue, Solid, Svelte, and React Native.useAskableStream— one-shot streaming primitive withcontent(accumulated),abort(),onChunk/onSuccess/onErrorcallbacks. All frameworks.Framework adapters
useAskableAgentwith Qwik-serializable$()handlersAskableFormSourceService(ElementRef + autoTrack),AskablePageSourceService,AskableAgentServiceuseAskableAgent,useAskableStream,useAskableChatExamples upgraded
examples/nextjs-app-router— replaces Vercel AI SDKuseChatwithuseAskableChat; streaming via/api/askable-chat; full bubble chat UI;.env.exampleandtsconfig.jsonaddedexamples/solid-dashboard— adds tabbed AI chat sidebar withuseAskableChat+ context inspector viewpackages/create-askable-app/template-svelte— upgraded from context-only touseAskableAgentbutton pattern (matches Vue template)packages/create-askable-app/template-solid— new SolidJS starter templateDocumentation
AGENTS.md— new sections foruseAskableFormSource,useAskableTableSource,useAskableErrorSource,useAskableUserSource,useAskableStream,useAskableChat, server-side validation withisAskableAgentRequestREADME.md— updated framework capability tables and feature listTests
Total: 686 passing (was 587 before this branch, +99 new tests)
@askable-ui/core@askable-ui/react@askable-ui/vue@askable-ui/solid@askable-ui/svelte@askable-ui/angular@askable-ui/qwik@askable-ui/react-native@askable-ui/mcp@askable-ui/web-componentTest plan
npx vitest runin each package)ANTHROPIC_API_KEYcreate-askable-appSolidJS and Svelte templates scaffold correctlyAskableFormSourceServiceinjects correctly in an Angular component with@ViewChilduseAskableTableSourceauto-notifies on row array changes in React (state update → AI sees new count)useAskableUserSourcewithomitFields: ['email']excludes the email from resolved contextGenerated by Claude Code