- Add trimHistory() to keep most recent messages within 100k token budget
- Add formatMessageWithHistory() to prepend conversation context to each message
- Wire up in useAIChat.ts: sendMessage now includes full history
- Keep --resume as belt-and-suspenders for same-session continuity
- 14 new tests in ai-chat.test.ts and useAIChat.test.ts
* feat: add claude CLI subprocess backend for AI panels
Add claude_cli.rs module that spawns the local `claude` CLI as a
subprocess instead of calling the Anthropic API directly. This removes
the need for users to configure an API key — the CLI uses the user's
existing Claude authentication.
- find_claude_binary(): discovers claude in PATH or common locations
- check_cli(): returns install/version status for the frontend
- run_chat_stream(): spawns claude -p with stream-json for chat panel
- run_agent_stream(): spawns claude with MCP vault tools for agent panel
- Parses stream-json NDJSON events and emits typed Tauri events
- Remove http:default capability (no longer calling APIs from frontend)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: replace Anthropic API with Claude CLI for AI chat and agent panels
Remove direct Anthropic API calls and the entire tool-use loop from the frontend.
Both AI Chat and AI Agent panels now delegate to the `claude` CLI subprocess via
Tauri commands, streaming NDJSON events back to the UI.
Key changes:
- ai-chat.ts / ai-agent.ts: replace SSE/API streaming with Tauri invoke + listen
- useAIChat / useAiAgent hooks: simplified to use CLI streaming callbacks
- AIChatPanel / AiPanel: remove API key dialogs, model selectors, undo support
- SettingsPanel: remove Anthropic key field (no longer needed)
- claude_cli.rs: add comprehensive tests (37 total, 90% coverage)
- mock-handlers: replace ai_chat with check_claude_cli / stream_claude_* stubs
- Net -432 lines across 17 files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add --verbose flag to claude CLI subprocess args
* chore: exclude search.rs and lib.rs from coverage (qmd integration + Tauri setup)
---------
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The AI panel called /api/ai/agent and /api/ai/chat — relative HTTP
endpoints that only exist in the Vite dev server. In the Tauri app
there is no local HTTP server, so requests failed with "The string
did not match the expected pattern".
Replace with direct calls to https://api.anthropic.com/v1/messages
with proper headers (x-api-key, anthropic-version). Tauri's webview
allows fetch() to external URLs without CORS issues.
Co-authored-by: Test <test@test.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Wrap ref assignments in useEffect to fix refs-during-render in
useTabManagement, useKeyboardNavigation, and Editor
- Rewrite useAppKeyboard to define keyMap inside useEffect, eliminating
ref access during render
- Add eslint-disable for react-hooks/set-state-in-effect on legitimate
dialog reset patterns (CommitDialog, CreateNoteDialog, CreateTypeDialog,
QuickOpenPalette, AIChatPanel, useVaultLoader)
- Add eslint-disable for react-hooks/static-components on icon lookups
(NoteItem, NoteList PinnedCard) — stateless icon components from a
static map
- Add eslint-disable for react-hooks/purity on Date.now() in
NoteItem TrashDateLine — intentionally memoized on trashedAt
- Remove unused `model` param from buildSystemPrompt (ai-chat.ts) and
update callers
- Fix exhaustive-deps: suppress vault object dep in App.tsx git history
effect (vault object is unstable, loadGitHistory is the real dep)
- Remove unused `modifiedFiles` from useNoteListData params and caller
- Add missing `ref` to Sidebar useOutsideClick deps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Test mocks: use { children?: React.ReactNode } and Record<string, unknown>
- Editor.tsx: use unknown[] for BlockNote block arrays
- wikilinks.ts: add BlockLike/InlineItem interfaces for block processing
- useMcpBridge.ts: use unknown for resolve/reject and Record<string, unknown>
- ai-chat.ts: use unknown catch + instanceof Error check
- mock-tauri.ts: type messages array, use Record<string, unknown> for args
(keep one targeted eslint-disable for heterogeneous handler map)
- vite.config.ts: use http.IncomingMessage/ServerResponse, typed messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite AIChatPanel with:
- Context picker: current note auto-added, search to add more notes,
removable context pills, token estimation badge
- Real Anthropic API integration via Vite dev server proxy (SSE streaming)
- API key stored in localStorage, configurable via dialog
- Model selector: Haiku 3.5, Sonnet 4, Opus 4
- Mock fallback when no API key is configured
- Extracted useAIChat hook and ai-chat utilities for clean separation
Decision: Using Vite middleware proxy for dev mode to avoid CORS issues
with direct browser-to-Anthropic calls. Phase 2 will add Rust backend.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>