This document explains the architecture and constraints of the local AI integration in ZenTrack.
The AI layer exists to enhance task parsing and provide conversational assistance for productivity queries. It does not replace core app logic or make decisions on behalf of the user.
The system is designed to fail gracefully. If AI is unavailable, the app must function identically to a version where AI was never implemented.
- Parse natural language task input into structured data (title, due date, tags, priority)
- Answer questions about tasks, time entries, study streaks, and upcoming deadlines
- Suggest prioritization strategies based on user context
- Provide focus recommendations (e.g., "What should I work on next?")
- Modify the database directly
- Make automatic changes to tasks without explicit user confirmation
- Send any data outside the local machine
- Block or delay core app functionality (all AI calls have timeouts)
- Assume control over UI state beyond the chat panel
AI responses are advisory. The user retains full control over task creation, editing, and deletion.
- Standardized HTTP API for model inference
- Wide model compatibility (llama, qwen, phi, mistral, gemma, deepseek)
- Runs as a local service with minimal configuration
- No API keys or authentication required
- Deployment simplicity: Users should not need to install Ollama to evaluate ZenTrack
- Performance: Not all machines can run LLMs efficiently
- Privacy: Some users prefer zero AI involvement
- Reliability: Local models can fail, timeout, or produce malformed output
The app must never assume AI is present.
- On mount,
checkOllamaAvailability()pingshttp://127.0.0.1:11434/api/tags - Timeout: 3 seconds
- Result cached for 5 minutes
useAIAvailability()hook exposes{ isAvailable, isChecking, forceRefresh }- Manual recheck triggered via UI button (no auto-polling)
If Ollama is not running, the check fails silently. No errors logged to console.
- User types natural language in task input field
SmartTaskInputcallsollamaClient.parseTask(input)- Timeout: 30 seconds
- If successful: Structured JSON returned → prefill form fields
- If failed: Fall back to regex-based parsing (existing NLP layer)
- No user-facing error messages for AI failures
- User opens AI Assistant panel (only visible when AI available)
- System message injects context: tasks, time entries, streak data
- User sends query →
ollamaClient.generate()with conversation history - Streaming responses not implemented (MVP uses full responses)
- Chat history stored in React state (not persisted)
- "Reset Chat" clears conversation and re-injects fresh context
Context injection format:
You are a productivity assistant for ZenTrack.
User Context:
- 12 active tasks (3 overdue)
- 4.5 hours tracked today
- Current study streak: 7 days
- Next deadline: Math assignment in 2 days
Answer questions about tasks, suggest priorities, and provide focus advice.
- AI availability check passes
- Compatible model detected
- Panel toggles via sidebar button
- AI becomes unavailable mid-session (rare, but handle gracefully)
- User clicks outside panel or presses Escape
- Malformed AI responses: Show "I couldn't process that request" fallback
- Timeout: Show "Response took too long" message
- Lost connection: Hide AI Assistant button, show recheck UI
Do not crash the app if Ollama stops responding.
AI errors must not surface as alerts, toasts, or modal dialogs. Users who never enabled AI should never know it exists.
- Wrap all
ollamaClientcalls in try-catch - Validate JSON structure before parsing
- Provide fallback values for missing fields
- Log errors to console only in development mode
- Availability check: 3s
- Task parsing: 30s (allows time for cold start)
- Chat generation: 30s
If timeout exceeded, cancel the request via AbortController.
- Automatic task creation: AI should not add tasks without user confirmation
- Background agents: No autonomous AI running in the background
- Model fine-tuning: Use pre-trained models as-is
- Multi-turn reasoning: Keep conversations shallow (no chain-of-thought)
- Voice input: Text-only for now
- Cloud model fallback: Do not contact external APIs if local AI fails
- Persistent chat history: Do not save conversations to SQLite
- Custom model configurations: No UI for changing temperature, top_p, etc.
These constraints exist to keep the AI layer simple, predictable, and maintainable.
- Verify the app works fully with Ollama disabled
- Ensure no console errors when AI calls fail
- Test with at least two different models (e.g., llama3 and qwen2.5)
- Confirm no UI blocking or freezing during AI operations
- Check that no user data is logged to console or terminal
- All AI-related code lives in
/src/ai/or/src/hooks/for AI hooks - Use TypeScript strict mode
- Prefer explicit error types over
any - Document prompt templates in source files (not external config)
- Manual testing only (no AI unit tests required yet)
- Verify cold start behavior (Ollama running but model not loaded)
- Test interrupted responses (stop Ollama mid-generation)
- Confirm fallback parsing works when AI is disabled
- AI failure does not break core functionality
- No new dependencies added for AI features
- Timeout values documented
- Chat panel does not leak memory on repeated open/close
- Recheck button works correctly after Ollama restarts
Current supported models (tested):
- llama3 (8B recommended)
- qwen2.5 (7B or 14B)
- phi-3 (3.8B, fast on CPU)
- mistral (7B)
- gemma (7B)
- deepseek-coder (6.7B)
Models must support JSON output formatting via prompt instructions. Do not rely on special API features (e.g., Ollama's format: "json" parameter is not required but can be used if present).
- First AI call may take 10-15 seconds (model loading)
- Subsequent calls: 1-3 seconds depending on hardware
- Context injection adds ~500 tokens per chat message
- Large task lists (100+ tasks) may slow context generation
Do not optimize prematurely. Profile before adding complexity.
If AI usage grows, we'll consider:
- Caching parsed task structures
- Streaming responses for chat
- Allowing users to select preferred model
- Persisting chat history (with explicit user consent)