Settings > AI tab now includes context size slider (2048–131072) with VRAM
estimate and a chatbot name field. ChatService reads both dynamically instead
of hardcoding num_ctx=16384 and "Purrse AI". Chat panel FAB and empty state
use mdi-cat icon to match the rest of the app.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the AI updates a category (or any tool result), the transactions
page now automatically reloads. ChatPanel triggers a refresh counter
in the usePageContext composable when the response includes a tool
result, and TransactionsView watches that counter to reload data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the classify-uncategorized endpoint from synchronous to async.
The controller now queues a ClassificationJob to an unbounded channel
and returns 202 Accepted. A new BackgroundService processes jobs and
pushes results (or errors) to the user via SignalR. The frontend
listens for the AiClassificationComplete event and surfaces it in the
notification system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the standalone /chat page with a bottom-right floating widget
available on every page. The panel sends page context with each message
so the AI knows what the user is viewing. On the Transactions page,
the full visible transaction list (with filters) is serialized into
the context so the AI can answer questions about on-screen entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The 401 interceptor was re-triggering itself when the refresh call
also returned 401, causing repeated requests before eventually
logging out. Add guards to skip refresh for the refresh endpoint
itself and prevent any request from retrying more than once.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrate 6 new tool chains into the chat service: get_budget,
get_budget_summary, get_loan_details, calculate_loan_payoff,
list_payees, and get_scheduled_transactions. Also raises the
search_transactions page_size cap from 25 to 50 and the upcoming
bills display from 5 to 10.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three new tools: list_categories shows all categories with type and
parent, create_category adds a new one with optional parent nesting,
delete_category removes non-system categories by name. Frontend renders
category tables, success alerts for creation, and warning alerts for
deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Conversational AI chat that uses Ollama's native tool-calling API to query
transactions, spending reports, account balances, dashboard summaries, and
update transaction categories through natural language. Includes persistent
conversation history, a full-page chat UI with sidebar, and rich inline
rendering of tool results (tables, alerts, cards).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full-stack profile section: DisplayName column on User model, profile CRUD
endpoints on AuthController, and complete Settings > Profile tab UI with
profile editing, password change, account info, and account deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v-data-table-server re-emits update:options when items/totalCount
change, creating a loop that resets to page 1. Guard against
redundant fetches by skipping when page and pageSize haven't
changed. Remove duplicate loadTransactions from onMounted since
the table's initial update:options event handles the first load.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace v-data-table with v-data-table-server so page changes
fetch from the API instead of being limited to the first 50
results. Filters reset to page 1; page/size changes trigger a
new API call with the correct page and pageSize parameters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make the entire header clickable to toggle rail mode so users
can expand the drawer after collapsing it
- Center the cat icon in rail mode via scoped CSS
- Add tooltips on all nav items and logout when in rail mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resets LastSyncAt on all linked accounts so the next sync
re-fetches the full 90-day transaction window. Duplicate
detection prevents re-importing existing transactions.
- POST /api/bank-sync/connections/{id}/reset-sync endpoint
- Re-sync button shown only on SimpleFIN connection cards
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap edit/delete buttons in a flex container so they render
side by side instead of stacking. Fix Dashboard DateTime to use
UTC kind, which Npgsql requires for timestamp comparisons.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Group discovered SimpleFIN accounts by institution and create a
separate SyncConnection per institution so each bank appears as
its own card in the UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sync-now and sync-all now return 202 Accepted immediately and
dispatch work to a background task. The frontend uses the existing
SignalR BankSyncComplete notification to stop the spinner and
display results.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HttpClient does not extract Basic Auth credentials from URLs with
embedded user:pass@host format. Parse the access URL, build the
Authorization header explicitly, and strip credentials from the
request URI. Also send Content-Length: 0 on token exchange POST
and update setup instructions to point to beta-bridge.simplefin.org.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of showing defaults as greyed-out placeholder text, populate
textareas with the actual default prompt text so users can directly
edit it. Add {categories}, {examples}, and {transactions} placeholders
so users control where dynamic data is inserted in the prompts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SystemPrompt and UserPromptTemplate fields to AI categorization
settings so users can customize the prompts sent to Ollama without
code changes. Null/empty values fall back to built-in defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds local LLM-based transaction categorization using Ollama:
- Settings UI to configure Ollama URL, model, confidence threshold
- Auto-categorization during bank sync and file import
- Manual "Classify Uncategorized" button on Transactions screen that respects active filters
- Payee default category learning loop for classified transactions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Plaid ClientId/Secret are now stored per-user in the database
(encrypted) instead of in appsettings.json. Users enter their own
Plaid developer credentials in the Settings > Bank Connections tab.
- New BankSyncSettings model (1:1 with User) for encrypted credentials
- PlaidSyncProvider is now stateless, receives credentials per-call
- Settings UI shows a credentials card with save form
- Connect via Plaid button disabled until credentials are configured
- Removed Plaid section from appsettings.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validate Plaid credentials are configured before calling the API,
and validate the returned link token before passing it to Plaid
Link JS. Show error snackbars for all bank sync failures instead
of only logging to console.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove nested AppLayout wrapper from SettingsView — the layout is
already applied at the App.vue level around router-view.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add automated transaction syncing via Plaid and SimpleFIN providers,
a Settings page for managing connections and account mappings,
background scheduled syncing, and sync history logging.
New backend: BankSync plugin project with PlaidSyncProvider and
SimpleFinSyncProvider, SyncConnection/LinkedAccount/SyncLog models,
AES-256 encryption service, BankSyncService orchestration,
BankSyncBackgroundService (15-min tick), and BankSyncController
(13 endpoints). EF migration creates sync_connections,
linked_accounts, and sync_logs tables.
New frontend: Settings view with 3 tabs (Profile, Bank Connections,
Sync History), bankSync API service, BankSyncComplete SignalR
notifications, and Settings nav item in sidebar + avatar dropdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add full frontend UI for five backend features: bank reconciliation (3-step
stepper workflow), payee management (CRUD with alias chips), transaction splits
(expandable rows + split editor), plugins (card grid), and real-time SignalR
notifications (bell dropdown with badge). Fix backend PayeeResponse to expose
alias IDs for deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap each report API call in a fetchReport helper that catches errors
individually and returns null, treating 4xx responses as empty data
instead of surfacing an error message to the user.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add interactive reports dashboard with 4 chart types (spending by
category donut, income vs expense bar, net worth area, cash flow bar)
using ApexCharts, date range presets, and account filtering. Add
investment portfolio view with holdings table, allocation chart, and
gain/loss color coding. Includes TypeScript types and API services.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add API service files and replace stub views with full implementations:
- Budgets: month navigator, budget items table with progress bars, create/edit/delete
- Scheduled Transactions: data table with skip/post-now actions, add/edit dialog
- Loans: loan list, detail view with amortization schedule, payoff scenario calculator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete the import flow from file upload through duplicate resolution
to transaction creation. Previously, ResolveDuplicatesAsync was a stub
that only incremented counters, FileWatcherService detected files but
didn't process them, and ImportsView.vue ignored the API response.
Backend:
- Add ParsedDataJson column to ImportBatch to persist parsed data
between upload and confirm steps
- Rewrite ImportService.ResolveDuplicatesAsync to deserialize parsed
transactions and create/merge/skip based on user decisions, with
payee matching, fingerprinting, and account balance updates
- Add GetBatchesAsync for import history
- Complete FileWatcherService: wait for file ready, resolve account by
filename, call UploadAsync, send SignalR notification, archive file
- Add GET /api/imports/batches endpoint
Frontend:
- Create imports API service (frontend/src/services/imports.ts)
- Add ImportBatch, DuplicateResolution types
- Rewrite ImportsView.vue with 3-step Vuetify stepper wizard:
upload, review with duplicate handling, completion summary,
plus import history table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The broad plugins/ and imports/ patterns were matching directories
at all levels, excluding frontend/src/plugins/vuetify.ts,
frontend/src/views/imports/, frontend/src/views/plugins/, and
src/Purrse.Tests/Plugins/. Changed to /plugins/ and /imports/
to only match root-level directories.
This was the root cause of the Docker build failure - vuetify.ts
was missing from the repo.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>