mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-18 20:59:39 +02:00
* AI sidebar * Add chat and message models with associations * Implement AI chat functionality with sidebar and messaging system - Add chat and messages controllers - Create chat and message views - Implement chat-related routes - Add message broadcasting and user interactions - Update application layout to support chat sidebar - Enhance user model with initials method * Refactor AI sidebar with enhanced chat menu and interactions - Update sidebar layout with dynamic width and improved responsiveness - Add new chat menu Stimulus controller for toggling between chat and chat list views - Improve chat list display with recent chats and empty state - Extract AI avatar to a partial for reusability - Enhance message display and interaction styling - Add more contextual buttons and interaction hints * Improve chat scroll behavior and message styling - Refactor chat scroll functionality with Stimulus controller - Optimize message scrolling in chat views - Update message styling for better visual hierarchy - Enhance chat container layout with flex and auto-scroll - Simplify message rendering across different chat views * Extract AI avatar to a shared partial for consistent styling - Refactor AI avatar rendering across chat views - Replace hardcoded avatar markup with a reusable partial - Simplify avatar display in chats and messages views * Update sidebar controller to handle right panel width dynamically - Add conditional width class for right sidebar panel - Ensure consistent sidebar toggle behavior for both left and right panels - Use specific width class for right panel (w-[375px]) * Refactor chat form and AI greeting with flexible partials - Extract message form to a reusable partial with dynamic context support - Create flexible AI greeting partial for consistent welcome messages - Simplify chat and sidebar views by leveraging new partials - Add support for different form scenarios (chat, new chat, sidebar) - Improve code modularity and reduce duplication * Add chat clearing functionality with dynamic menu options - Implement clear chat action in ChatsController - Add clear chat route to support clearing messages - Update AI sidebar with dropdown menu for chat actions - Preserve system message when clearing chat - Enhance chat interaction with new menu options * Add frontmatter to project structure documentation - Create initial frontmatter for structure.mdc file - Include description and configuration options - Prepare for potential dynamic documentation rendering * Update general project rules with additional guidelines - Add rule for using `Current.family` instead of `current_family` - Include new guidelines for testing, API routes, and solution approach - Expand project-specific rules for more consistent development practices * Add OpenAI gem and AI-friendly data representations - Add `ruby-openai` gem for AI integration - Implement `to_ai_readable_hash` methods in BalanceSheet and IncomeStatement - Include Promptable module in both models - Add savings rate calculation method in IncomeStatement - Prepare financial models for AI-powered insights and interactions * Enhance AI Financial Assistant with Advanced Querying and Debugging Capabilities - Implement comprehensive AI financial query system with function-based interactions - Add detailed debug logging for AI responses and function calls - Extend BalanceSheet and IncomeStatement models with AI-friendly methods - Create robust error handling and fallback mechanisms for AI queries - Update chat and message views to support debug mode and enhanced rendering - Add AI query routes and initial test coverage for financial assistant * Refactor AI sidebar and chat layout with improved structure and comments - Remove inline AI chat from application layout - Enhance AI sidebar with more semantic HTML structure - Add descriptive comments to clarify different sections of chat view - Improve flex layout and scrolling behavior in chat messages container - Optimize message rendering with more explicit class names and structure * Add Markdown rendering support for AI chat messages - Implement `markdown` helper method in ApplicationHelper using Redcarpet - Update message view to render AI messages with Markdown formatting - Add comprehensive Markdown rendering options (tables, code blocks, links) - Enhance AI Financial Assistant prompt to encourage Markdown usage - Remove commented Markdown CSS in Tailwind application stylesheet * Missing comma * Enhance AI response processing with chat history context * Improve AI debug logging with payload size limits and internal message flag * Enhance AI chat interaction with improved thinking indicator and scrolling behavior * Add AI consent and enable/disable functionality for AI chat * Upgrade Biome and refactor JavaScript template literals - Update @biomejs/biome to latest version with caret (^) notation - Refactor AI query and chat controllers to use template literals - Standardize npm scripts formatting in package.json * Add beta testing usage note to AI consent modal * Update test fixtures and configurations for AI chat functionality - Add family association to chat fixtures and tests - Set consistent password digest for test users - Enable AI for test users - Add OpenAI access token for test environment - Update chat and user model tests to include family context * Simplify data model and get tests passing * Remove structure.mdc from version control * Integrate AI chat styles into existing prose pattern * Match Figma design spec, implement Turbo frames and actions for chats controller * AI rules refresh * Consolidate Stimulus controllers, thinking state, controllers, and views * Naming, domain alignment * Reset migrations * Improve data model to support tool calls and message types * Tool calling tests and fixtures * Tool call implementation and test * Get assistant test working again * Test updates * Process tool calls within provider * Chat UI back to working state again * Remove stale code * Tests passing * Update openai class naming to avoid conflicts * Reconfigure test env * Rebuild gemfile * Fix naming conflicts for ChatResponse * Message styles * Use OpenAI conversation state management * Assistant function base implementation * Add back thinking messages, clean up error handling for chat * Fix sync error when security price has bad data from provider * Add balance sheet function to assistant * Add better function calling error visibility * Add income statement function * Simplify and clean up "thinking" interactions with Turbo frames * Remove stale data definitions from functions * Ensure VCR fixtures working with latest code * basic stream implementation * Get streaming working * Make AI sidebar wider when left sidebar is collapsed * Get tests working with streaming responses * Centralize provider error handling * Provider data boundaries --------- Co-authored-by: Josh Pigford <josh@joshpigford.com>
120 lines
6.6 KiB
Text
120 lines
6.6 KiB
Text
---
|
|
description:
|
|
globs:
|
|
alwaysApply: true
|
|
---
|
|
This rule serves as high-level documentation for how you should write code for the Maybe codebase.
|
|
|
|
## Project Tech Stack
|
|
|
|
- Web framework: Ruby on Rails
|
|
- Minitest + fixtures for testing
|
|
- Propshaft for asset pipeline
|
|
- Hotwire Turbo/Stimulus for SPA-like UI/UX
|
|
- TailwindCSS for styles
|
|
- Lucide Icons for icons
|
|
- OpenAI for AI chat
|
|
- Database: PostgreSQL
|
|
- Jobs: Sidekiq + Redis
|
|
- External
|
|
- Payments: Stripe
|
|
- User bank data syncing: Plaid
|
|
- Market data: Synth (our custom API)
|
|
|
|
## Project conventions
|
|
|
|
These conventions should be used when writing code for Maybe.
|
|
|
|
### Convention 1: Minimize dependencies, vanilla Rails is plenty
|
|
|
|
Dependencies are a natural part of building software, but we aim to minimize them when possible to keep this open-source codebase easy to understand, maintain, and contribute to.
|
|
|
|
- Push Rails to its limits before adding new dependencies
|
|
- When a new dependency is added, there must be a strong technical or business reason to add it
|
|
- When adding dependencies, you should favor old and reliable over new and flashy
|
|
|
|
### Convention 2: Leverage POROs and concerns over "service objects"
|
|
|
|
This codebase adopts a "skinny controller, fat models" convention. Furthermore, we put almost _everything_ directly in the `app/models/` folder and avoid separate folders for business logic such as `app/services/`.
|
|
|
|
- Organize large pieces of business logic into Rails concerns and POROs (Plain ole' Ruby Objects)
|
|
- While a Rails concern _may_ offer shared functionality (i.e. "duck types"), it can also be a "one-off" concern that is only included in one place for better organization and readability.
|
|
- When concerns are used for code organization, they should be organized around the "traits" of a model; not for simply moving code to another spot in the codebase.
|
|
- When possible, models should answer questions about themselves—for example, we might have a method, `account.balance_series` that returns a time-series of the account's most recent balances. We prefer this over something more service-like such as `AccountSeries.new(account).call`.
|
|
|
|
### Convention 3: Leverage Hotwire, write semantic HTML, CSS, and JS, prefer server-side solutions
|
|
|
|
- Native HTML is always preferred over JS-based components
|
|
- Example 1: Use `<dialog>` element for modals instead of creating a custom component
|
|
- Example 2: Use `<details><summary>...</summary></details>` for disclosures rather than custom components
|
|
- Leverage Turbo frames to break up the page over JS-driven client-side solutions
|
|
- Example 1: A good example of turbo frame usage is in [application.html.erb](mdc:app/views/layouts/application.html.erb) where we load [chats_controller.rb](mdc:app/controllers/chats_controller.rb) actions in a turbo frame in the global layout
|
|
- Leverage query params in the URL for state over local storage and sessions. If absolutely necessary, utilize the DB for persistent state.
|
|
- Use Turbo streams to enhance functionality, but do not solely depend on it
|
|
- Format currencies, numbers, dates, and other values server-side, then pass to Stimulus controllers for display only
|
|
- Keep client-side code for where it truly shines. For example, @bulk_select_controller.js is a case where server-side solutions would degrade the user experience significantly. When bulk-selecting entries, client-side solutions are the way to go and Stimulus provides the right toolset to achieve this.
|
|
|
|
The Hotwire suite (Turbo/Stimulus) works very well with these native elements and we optimize for this.
|
|
|
|
### Convention 4: Optimize for simplicitly and clarity
|
|
|
|
All code should maximize readability and simplicity.
|
|
|
|
- Prioritize good OOP domain design over performance
|
|
- Only focus on performance for critical and global areas of the codebase; otherwise, don't sweat the small stuff.
|
|
- Example 1: be mindful of loading large data payloads in global layouts
|
|
- Example 2: Avoid N+1 queries
|
|
|
|
### Convention 5: Use Minitest + Fixtures for testing, minimize fixtures
|
|
|
|
Due to the open-source nature of this project, we have chosen Minitest + Fixtures for testing to maximize familiarity and predictability.
|
|
|
|
- Always use Minitest and fixtures for testing.
|
|
- Keep fixtures to a minimum. Most models should have 2-3 fixtures maximum that represent the "base cases" for that model. "Edge cases" should be created on the fly, within the context of the test which it is needed.
|
|
- For tests that require a large number of fixture records to be created, use Rails helpers such as [entries_test_helper.rb](mdc:test/support/account/entries_test_helper.rb) to act as a "factory" for creating these. For a great example of this, check out [forward_calculator_test.rb](mdc:test/models/account/balance/forward_calculator_test.rb)
|
|
- Take a minimal approach to testing—only test the absolutely critical code paths that will significantly increase developer confidence
|
|
|
|
#### Convention 5a: Write minimal, effective tests
|
|
|
|
- Use system tests sparingly as they increase the time to complete the test suite
|
|
- Only write tests for critical and important code paths
|
|
- Write tests as you go, when required
|
|
- Take a practical approach to testing. Tests are effective when their presence _significantly increases confidence in the codebase_.
|
|
|
|
Below are examples of necessary vs. unnecessary tests:
|
|
|
|
```rb
|
|
# GOOD!!
|
|
# Necessary test - in this case, we're testing critical domain business logic
|
|
test "syncs balances" do
|
|
Account::Holding::Syncer.any_instance.expects(:sync_holdings).returns([]).once
|
|
|
|
@account.expects(:start_date).returns(2.days.ago.to_date)
|
|
|
|
Account::Balance::ForwardCalculator.any_instance.expects(:calculate).returns(
|
|
[
|
|
Account::Balance.new(date: 1.day.ago.to_date, balance: 1000, cash_balance: 1000, currency: "USD"),
|
|
Account::Balance.new(date: Date.current, balance: 1000, cash_balance: 1000, currency: "USD")
|
|
]
|
|
)
|
|
|
|
assert_difference "@account.balances.count", 2 do
|
|
Account::Balance::Syncer.new(@account, strategy: :forward).sync_balances
|
|
end
|
|
end
|
|
|
|
# BAD!!
|
|
# Unnecessary test - in this case, this is simply testing ActiveRecord's functionality
|
|
test "saves balance" do
|
|
balance_record = Account::Balance.new(balance: 100, currency: "USD")
|
|
|
|
assert balance_record.save
|
|
end
|
|
```
|
|
|
|
### Convention 6: Use ActiveRecord for complex validations, DB for simple ones, keep business logic out of DB
|
|
|
|
- Enforce `null` checks, unique indexes, and other simple validations in the DB
|
|
- ActiveRecord validations _may_ mirror the DB level ones, but not 100% necessary. These are for convenience when error handling in forms. Always prefer client-side form validation when possible.
|
|
- Complex validations and business logic should remain in ActiveRecord
|
|
|