Skip to content

feat(ai-core): provider-agnostic AI architecture with streaming#156

Merged
github-actions[bot] merged 19 commits into
developfrom
feature/ai-core-provider-abstraction
Mar 14, 2026
Merged

feat(ai-core): provider-agnostic AI architecture with streaming#156
github-actions[bot] merged 19 commits into
developfrom
feature/ai-core-provider-abstraction

Conversation

@tomymaritano

@tomymaritano tomymaritano commented Mar 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • New @readied/ai-core package — provider-agnostic AI architecture with LLMProvider interface, ProviderRegistry, streaming SSE parser, retry logic with exponential backoff, context builder with token budgeting, and AIService orchestrator
  • Full Electron integration — IPC bridge with batched streaming events, preload API, and renderer AiPanel wired to the new streaming architecture
  • UX fixes — unified dual AI panel entry points (Cmd+K and Sparkles button) into single panel, fixed panel height to fill container, made React DevTools dev-only via dynamic import
  • Monorepo fix — pinned @types/react to 18.x via pnpm overrides to resolve lucide-react type mismatch

Architecture

Renderer (AiPanel) → IPC → Main (ai-core bridge) → AIService → ProviderRegistry → AnthropicProvider → SSE stream
                   ←  batched LLMEvents (text/error/done)  ←

What's included

packages/ai-core (new)

  • LLMProvider interface + ProviderRegistry for pluggable providers
  • AnthropicProvider with native SSE streaming (no SDK dependency)
  • ContextBuilder with token budgeting and automatic content trimming
  • AIService orchestrator with retry, cancellation, and context building
  • LLMEvent protocol: text, error, done, tool_call, tool_result
  • Reusable SSE stream parser

apps/desktop

  • IPC bridge with 50ms batched event streaming (main → renderer)
  • Preload API: window.readied.ai.chat(), .onEvent(), .cancel()
  • Unified AI panel (single instance, both Cmd+K and Sparkles button toggle it)
  • Panel height fix (fills container instead of 350px cutoff)
  • Dynamic import for electron-devtools-installer (excluded from prod)

Monorepo

  • Removed deprecated @readied/ai-assistant package
  • Added pnpm.overrides to pin @types/react@18.3.27 across workspace

Test plan

  • All 16 packages pass pnpm test
  • pnpm typecheck passes (17/17 tasks)
  • pnpm build succeeds
  • Manual: Cmd+K opens AI panel in ask-notes mode
  • Manual: Sparkles button toggles same panel
  • Manual: AI chat streams responses correctly
  • Manual: Panel fills full height of sidebar

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added streaming AI chat responses for real-time interaction
    • Introduced provider selection (Anthropic, OpenAI, Ollama support)
    • Added ability to cancel in-flight AI requests
    • Implemented configuration validation for AI providers
    • Enhanced chat interface with conversation modes
  • Refactor

    • Restructured AI system for multi-provider support
    • Updated settings schema with provider configuration

tomymaritano and others added 18 commits March 13, 2026 18:49
## Summary

Release 0.9.0 — a major milestone with AI features, sync stability, and
a complete website redesign.

- **Website redesign** with shadcn/ui + Magic UI
- **Auth UX rethink** — Enable Sync flow + middleware fix (500 → 401)
- **Sync stability** — error propagation, exponential backoff, abort on
logout, typed token refresh
- **Sync onboarding** — prompt after 5 notes + offline queue visibility
- **AI Commands (Cmd+K v1)** — command panel, settings, keybindings
- **AI Knowledge (Cmd+K v2)** — RAG, ask notes, related context
- **AI Extensibility** — plugin API, presets import/export
- **API documentation**

## Version bumps

| File | From | To |
|------|------|----|
| `package.json` | 0.2.0 | 0.9.0 |
| `apps/desktop/package.json` | 0.8.0 | 0.9.0 |

## Checklist

- [x] Version bumped in root `package.json`
- [x] Version bumped in `apps/desktop/package.json`
- [x] CHANGELOG.md updated
- [x] Tests pass
- [ ] QA smoke test on macOS
- [ ] QA smoke test on Windows
- [ ] Tag `v0.9.0` after merge

## Post-merge

After merging to `main`:
1. Tag `v0.9.0` on main
2. Merge `main` back into `develop`
3. Delete `release/0.9.0` branch

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* AI Assistant panel with modeful interface (chat/ask-notes modes),
configurable via settings
  * AI command presets support (export/import functionality)
  * Sync status monitoring with error tracking and pending change count
  * Enable Sync onboarding flow for new users
  * Redesigned website with modernized design system
* Settings panel for AI configuration (API key, model selection, context
limits)

* **Bug Fixes**
  * Improved token handling for deep-link authentication
  * Better sync error classification and exponential backoff
  * Enhanced device limit error handling

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary

- Adds `auto-tag.yml` workflow that was created during v0.9.0
development but missed the squash merge to main
- Without this workflow, release PRs don't trigger automatic tag
creation, breaking the release pipeline

## Context

The release pipeline chain is: `release/* PR merge → auto-tag creates
vX.Y.Z → release.yml builds + publishes`

This workflow was in `release/0.9.0` but the squash merge of PR #149
didn't include it, so v0.9.0 never got tagged or released.

## After merge

Once this is on main, I'll manually create the `v0.9.0` tag to trigger
the release build.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Release v0.9.0

### Highlights

- **Auth → Payment → Sync flow**: License-gated sync with smart step
routing in EnableSyncModal
- **Stripe checkout**: Monthly (€2/mo) and annual (€20/year) plan
selection
- **Sidebar drag-and-drop**: Grip handle, circular reference prevention,
child depth propagation
- **CI/CD**: Auto-deploy API — develop → staging, main → production
- **Design tokens**: SyncStatusIndicator uses CSS variables instead of
hardcoded colors
- **AI features**: Command execution, plugin bridge, knowledge system
(Phase 4-5)
- **UI cleanup**: Tailwind v4 canonical classes, removed dead
design-system package

### Changes since v0.8.0

- feat(sync): connect auth → payment → sync flow with license gating
(#154)
- chore: Tailwind v4 canonical classes + tsconfig cleanup (#151)
- feat(ai): complete Phase 4-5 — AI command execution + plugin bridge
(#150)
- feat(ai,plugins): complete Phase 4-5 — AI knowledge & extensibility
- feat(desktop,api): complete Phase 1-3 roadmap implementation

### Checklist

- [x] `pnpm typecheck` passes
- [x] `pnpm test` passes
- [x] `package.json` version is `0.9.0`
- [x] All features merged to develop first
- [x] API production secrets configured (Stripe, Resend)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

# Release Notes

* **New Features**
* Added AI-powered text commands (summarize, rewrite, tweet) with plugin
integration.
* Introduced drag-and-drop notebook reordering with automatic circular
reference protection.
  * Enhanced sync onboarding with license-based feature gating.
  * Improved magic link authentication with automatic verification.

* **Bug Fixes**
  * Fixed token refresh infinite loop handling.
  * Added URL encoding for verification links.
  * Improved cleanup for animated UI components.

* **Improvements**
  * Enhanced error handling for authentication and sync failures.
  * Added accessibility attributes (ARIA labels, semantic HTML).
  * Updated visual styling with new token-driven design system.

* **Refactor**
  * Migrated from design-system package to plugin-api package.
  * Consolidated design tokens and theme system.

* **Chores**
  * Updated GitHub Actions release automation.
  * Refreshed project documentation and contribution guidelines.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…used imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements context assembly for LLM calls with token-aware budget management:
drops oldest history messages and truncates/excludes notes that exceed limits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements parseSSEStream as an async generator that handles chunked
Uint8Array streams, double-newline event boundaries, event/data field
parsing, comment skipping, and malformed JSON resilience.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements AnthropicProvider with full SSE streaming support, HTTP error
classification, usage token tracking, static model list, and config validation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…etry

Implements AIServiceImpl that wires together ProviderRegistry, buildContext,
and withRetry into a single chat() entry point returning an abortable
AsyncIterable<LLMEvent> handle with start/done envelope events.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace legacy ai:query handler with ai-core-based streaming IPC:
- Add @readied/ai-core dependency, remove @readied/ai-assistant
- Create apps/desktop/src/main/ai/setup.ts: singleton AIService factory using ProviderRegistry + AnthropicProvider with net.fetch
- Create apps/desktop/src/main/ai/ipc-ai.ts: registerAIHandlers with ai:chat (streaming), ai:cancel, ai:validate, ai:exportPreset, ai:importPreset; 50ms text batching + per-window handle tracking
- Remove old registerAiHandlers() inline function from index.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace ai.query() with ai.chat(), ai.onEvent(), ai.cancel(), ai.validate().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace synchronous ai.query() calls with event-driven ai.chat() streaming.
Add provider field to settings schema (v3 migration), copy aiCommandTypes
to ai-core, and update all renderer imports from @readied/ai-assistant
to @readied/ai-core.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All functionality has been migrated to @readied/ai-core.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Merge duplicate AI panel systems (plugin + App.tsx) into single
  panel instance managed by App.tsx
- Plugin's Sparkles button now dispatches CustomEvent instead of
  managing its own panel, eliminating the duplicate panel that
  appeared inside the editor zone
- Fix AI panel CSS from fixed height (350px) to 100% to fill
  the side panel container properly
- Default to 'ask-notes' mode (RAG) when opening panel via ⌘K
- Make React DevTools a dynamic import so it stays out of
  production bundle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lucide-react@0.562 ships types against @types/react@19.x, but the
desktop app uses React 18. pnpm hoisted the 19.x types from apps/web,
causing a type identity mismatch (bigint not in React 18 ReactNode).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Mar 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
readide Ready Ready Preview, Comment Mar 14, 2026 6:07pm

Request Review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The pull request refactors the AI subsystem from a monolithic @readied/ai-assistant package to a new modular @readied/ai-core architecture. It introduces a provider-agnostic streaming protocol with provider registry support (including AnthropicProvider), IPC-based chat integration in the desktop main process, and corresponding updates to renderer components, settings schema, and preload APIs. The legacy AI module is removed entirely.

Changes

Cohort / File(s) Summary
AI Core Package (New)
packages/ai-core/package.json, packages/ai-core/src/types.ts, packages/ai-core/src/provider.ts, packages/ai-core/src/provider-registry.ts, packages/ai-core/src/context-builder.ts, packages/ai-core/src/retry.ts, packages/ai-core/src/ai-service.ts, packages/ai-core/src/ai-command-types.ts, packages/ai-core/src/providers/anthropic.ts, packages/ai-core/src/providers/sse-parser.ts, packages/ai-core/src/index.ts
New modular AI core with LLMEvent streaming protocol, ProviderRegistry, AnthropicProvider implementation, context builder with token budgeting, retry logic with exponential backoff, AIServiceImpl for managing streaming chats, and AI command types/validation. Comprehensive test coverage added across modules.
Desktop Main Process Integration
apps/desktop/src/main/ai/setup.ts, apps/desktop/src/main/ai/ipc-ai.ts, apps/desktop/src/main/index.ts
New AI service instantiation (setup.ts with AnthropicProvider), IPC handler registration (ipc-ai.ts with ai:chat, ai:cancel, ai:validate channels), streaming consumer with event batching, and per-window handle tracking. Main process wired to initialize AI service at startup and replace legacy AI handlers.
Desktop Preload & IPC API
apps/desktop/src/preload/index.ts
Replaced query method with streaming chat(), added onEvent() listener, cancel(), and validate() methods. Chat requests now include query, currentNote, relevantNotes, history, mode, provider, and providerConfig fields instead of simple message/system structure.
Desktop Renderer AI Components
apps/desktop/src/renderer/components/ai/AiPanel.tsx, apps/desktop/src/renderer/App.tsx, apps/desktop/src/renderer/plugins/aiAssistant.tsx, apps/desktop/src/renderer/hooks/useRegisterPluginAiCommands.ts
AiPanel migrated to streaming with active request tracking, event-driven text accumulation, and output-target actions. App.tsx imports updated to use ai-core. Plugin refactored to CustomEvent-based toggle (removed bridge/panel coupling). Hook import paths updated. Added AiInitialCommand interface and event listener for readied:ai:toggle-panel.
Desktop Settings & Schema
apps/desktop/src/renderer/stores/settings/schema.ts, apps/desktop/src/renderer/stores/settings/settingsStore.ts, apps/desktop/src/renderer/pages/settings/sections/AiSection.tsx
Settings version bumped to 3 with new provider field (anthropic/openai/ollama enum), model relaxed to string, and provider-specific apiKey handling. Migration logic added for v2→v3. AiSection now includes provider selection UI and uses validate() instead of query for testing connections.
Legacy AI Assistant Removal
packages/ai-assistant/src/claude-client.ts, packages/ai-assistant/src/prompts.ts, packages/ai-assistant/src/rag.ts, packages/ai-assistant/src/index.ts
Entire claude-client module, prompts and templates, RAG functionality, and public exports removed. All symbols previously re-exported are eliminated, shifting responsibility to ai-core package.
Dependency & Configuration
apps/desktop/package.json, package.json, .claude/settings.local.json
Changed ai-assistant workspace dependency to ai-core. Added pnpm overrides for @types/react and @types/react-dom. Added Bash permissions for tsc, git stash/rm, and turbo commands in Claude settings.
Styling
apps/desktop/src/renderer/styles/ai-panel.css
Replaced fixed 350px height with 100% flex height and removed top border for improved layout flexibility.

Sequence Diagram(s)

sequenceDiagram
    participant Renderer as Renderer<br/>(AiPanel)
    participant IPC as Electron IPC
    participant Service as AIService
    participant Provider as AnthropicProvider
    participant Network as Anthropic API

    Renderer->>IPC: ai:chat { query, history,<br/>mode, provider }
    activate IPC
    IPC->>Service: chat(request)
    activate Service
    Service->>Service: buildContext(sources,<br/>budget)
    Service->>Provider: chat(options,<br/>config)
    activate Provider
    Provider->>Network: POST /v1/messages<br/>(stream SSE)
    activate Network
    Network-->>Provider: SSE stream<br/>(text_delta, etc)
    deactivate Network
    
    loop Streaming Events
        Provider->>Provider: parseSSEStream()
        Provider->>Service: yield LLMEvent<br/>(text, usage)
        Service->>Service: track tokens,<br/>accumulate
        Service->>IPC: emit text event<br/>(batched, 50ms)
        IPC->>Renderer: ai:event<br/>(text delta)
        Renderer->>Renderer: accumulate text,<br/>update UI
    end
    
    Provider-->>Service: yield done event
    deactivate Provider
    Service->>Service: cleanup handle,<br/>emit duration
    Service-->>IPC: done(duration,<br/>cancelled)
    deactivate Service
    IPC->>Renderer: ai:event (done)
    deactivate IPC
    Renderer->>Renderer: finalize stream,<br/>apply output target
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

size/XL

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and accurately summarizes the primary change: introducing a provider-agnostic AI architecture with streaming capabilities. It is concise, specific, and reflects the main objective of the PR without being overly broad or vague.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/ai-core-provider-abstraction
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

- Accept all apps/web changes from develop
- Move aiCommandTypes from ai-assistant into ai-core
- Fix test imports for renamed ai-command-types module
- Regenerate pnpm-lock.yaml

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot enabled auto-merge (squash) March 14, 2026 18:06
@github-actions github-actions Bot added dependencies Pull requests that update a dependency file app:desktop size/XL labels Mar 14, 2026
@github-actions github-actions Bot merged commit a24a231 into develop Mar 14, 2026
14 of 15 checks passed
github-actions Bot pushed a commit that referenced this pull request Mar 14, 2026
## Summary

- Merges all develop changes into main for release preparation
- Includes: AI core provider abstraction (#156), automated release
pipeline (#157), and all other develop work
- All conflicts resolved (develop is source of truth)

## What happens after merge

1. Go to **Actions → Release → Run workflow** (branch: main)
2. semantic-release calculates version, creates tag + draft release
3. Build workflow triggers automatically for mac/win/linux
4. Release is published when all builds succeed

## Test plan

- [x] All tests pass (`pnpm test` — 16/16)
- [x] No conflict markers remaining
- [ ] CI checks pass on this PR

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
tomymaritano added a commit that referenced this pull request Mar 18, 2026
Resolve conflicts keeping tool use features + CodeRabbit fixes.
Incoming from develop: ai-core base (#156), release pipeline (#157), cleanUrls fix (#164).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:desktop dependencies Pull requests that update a dependency file size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant