feat: financial-event transaction deduplication engine#21
Open
alon710 wants to merge 17 commits into
Open
Conversation
Adds a streaming /chat page that uses the same AI provider configured for categorization (Claude or Ollama). The agent answers free-text questions about the user's finances through tool calls that wrap existing read-only DB queries (transactions, monthly summary, top merchants, category breakdown). Page and sidebar entry are disabled when no AI provider is configured. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Next.js 16 renames the Middleware file convention to Proxy. The build emits a deprecation warning until the rename happens. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
refactor: rename middleware.ts to proxy.ts for Next.js 16
…endering Adds persistent chat sessions backed by SQLite (migration 021), a session history sidebar with rename and delete actions, AI-generated chat titles via a setChatTitle tool, and markdown rendering for assistant responses using react-markdown. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(chat): AI chat agent with persistent sessions and tool-based data access
Bank-side credit card payments are tagged kind='transfer' by detectKind but the transactions summary and list kind-filter used the raw charged_amount sign, so transfers double-counted with individual card line items in totals, top merchants, and the largest-expense widget. Switch those queries to filter on kind, and backfill existing rows in a new migration that reclassifies bank rows matching the credit-card payment patterns.
…nting fix(transactions): exclude credit card transfers from expense totals
* feat(ai): add Gemini as a third AI provider Adds Google Gemini alongside Claude and Ollama for transaction categorization. Uses @google/genai with gemini-2.5-flash and stores the API key encrypted under provider-specific setting keys so it can coexist with a Claude key. Wires the new option through the setup wizard, settings page, factory, and i18n. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Add Gemini provider support * refactor(ai): simplify Gemini provider changes - always require a key on save and drop the leave-blank-to-keep-stored UX, removing the hasStoredKey helper, hasClaudeApiKey/hasGeminiApiKey flags, and the i18n hint pair this required - extract shared parseCategorizationResponse used by ClaudeProvider and GeminiProvider - merge ClaudeConfig and GeminiConfig in the setup wizard into a single ApiKeyConfig with a children slot for provider-specific extras - dispatch friendlyAIError on the provider argument instead of cascading regex matches over raw error text - drop redundant Gemini model whitelist checks in the factory and settings writer Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: pin PR target to upstream Shaya16/Spent Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: remove upstream PR target note from CLAUDE.md --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Adds .github/workflows/ci.yml that runs `bun run ci` on every PR + push to main with fail-fast on five strict checks: Biome formatter, TypeScript, @lingual/i18n-check (next-intl-recommended) for missing + orphan keys, knip for dead code, react-compiler-healthcheck, and `bun test`. Switches the toolchain to Bun: package-lock.json removed, bun.lock committed, all `npm`/`node` shell-outs in scripts/ replaced with `bun`, service installer cheat-sheets updated. Service templates (.plist, .service, .vbs, .xml) unchanged since they invoke node + next directly. Adds tooling configs (biome.jsonc, knip.json), a wrapper script for i18n-check with documented dynamic-namespace and baseline-orphan ignores, and one smoke test (src/server/lib/dedup.test.ts) so the test gate is real. Applies a one-pass Biome formatter sweep across 110 files. README, CLAUDE.md, and menubar/README.md updated to reflect bun commands, new Requirements, CI badge, and the `bun run ci` workflow. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sync): show full provider error message in progress dialog Truncating to 60 chars hid the actual failure reason. Wrap when the row is in error state; keep truncation for non-error statuses. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(readme): refresh bank coverage, add chat feature, bump default model Replaces the three-bank list with the full israeli-bank-scrapers roster shipped enabled today. Documents the new /chat agent. Updates the Claude default to claude-haiku-4-5-20251001 and refreshes the roadmap. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix(ai): support Gemini in chat and trim provider API keys Gemini was wired into setup and categorization but never into the chat model factory, so chat returned 400 "AI provider not configured" for Gemini users. Add a gemini branch to createChatModel via @ai-sdk/google, and trim Claude/Gemini keys before validating and saving. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ui): point Star on GitHub link to alon710/Spent Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
#13) - i18n: serve every page under /en or /he via next-intl; the active locale comes from the URL plus the NEXT_LOCALE cookie (no database), defaulting to English. The proxy adds CSRF same-origin checks on /api. - transactions: detect bank-side credit-card settlements, internal account-to-account transfers, and ATM withdrawals so they stop double-counting spend; add a "treat ATM withdrawals as transfers" setting. - ui: add vertical spacing between sidebar items, plus broad pre-launch polish across components, docs, website, menubar, scripts, copy, and PWA icons/manifest. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Group duplicate cross-account representations of one real-world money movement (internal transfers, bank-side credit card bill payments, ATM withdrawals) into auditable Financial Events with a canonical row, confidence scoring, human-readable match reasons, and lossless undo. This generalizes the previous keyword-based kind-flipping into a tunable, reversible matching layer while keeping the existing exact dedup, the kind column, and every reporting query backward compatible. Adds migration 022 (financial_events, event_members, match_settings, match_rules, additive transactions columns, blocking index, and a spendable_transactions view), a pure unit-tested matching engine, the DB apply/list/confirm/reject layer, sync-flow wiring, an events API, a transaction-list event badge, and a full design document. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add drizzle-orm + drizzle-kit over the existing better-sqlite3 connection (getOrm() wraps the same getDb() handle). schema.ts mirrors the live DB, generated by introspecting a fully-migrated database; the .sql migration runner remains the source of truth for DDL. Migrate the financial-events query module to Drizzle as the canonical pattern, preserving signatures and behavior (verified end to end). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Convert the remaining query modules to the Drizzle query builder for simple single-table CRUD and upserts, while keeping complex analytics (aggregates, multi-table joins, window functions, recursive CTEs, and the dedup ON CONFLICT batch upsert) as raw SQL on the same connection. Signatures and behavior are preserved exactly; verified end to end across settings, workspaces, sync runs, budgets, excluded merchants, categories, and the financial-event pipeline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Delete the macOS/Windows menubar apps, the service install scripts, the docs-seed/setup/uninstall/screenshot scripts, and Spent.sln; refresh CI, eslint, knip, biome, README, and SECURITY config; add a lint-changed helper script. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-migration # Conflicts: # src/app/api/setup/bank/test/route.ts # src/components/dashboard/transactions-table.tsx # src/lib/api.ts # src/server/db/queries/home.ts # src/server/db/queries/transactions.ts # src/server/lib/transfers.ts # src/server/sync/orchestrator.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a Financial Event layer that groups duplicate cross-account representations of one real-world money movement (internal transfers, bank-side credit card bill payments, and ATM withdrawals) into auditable events with a canonical reporting row, confidence scoring, human-readable reasons, and lossless undo, generalizing the previous keyword-based kind-flipping into a tunable, reversible matching layer. The backend adds migration 022 (financial_events, event_members, match_settings, match_rules, additive transactions columns, a blocking index, and a spendable_transactions view), a pure unit-tested matching engine, the DB apply/list/confirm/reject layer, sync-flow wiring, and an events API; the UI adds a Transfer / Card payment badge on grouped transaction rows (en/he i18n), and a full design document is included under docs/. It stays backward compatible: the kind column, the existing exact dedup, and every reporting query are unchanged, and the migration produces zero reporting drift on upgrade. The full CI gate passes (format, typecheck, i18n, knip, react-doctor, 29 tests), and the matching DB lifecycle was separately verified end to end against the real code.
🤖 Generated with Claude Code