Commit Graph

2 Commits

Author SHA1 Message Date
Wes
7685650e63 feat(assistant): add get_budget function for budget tracking (#1966)
* feat(assistant): add get_budget function for budget tracking

Exposes the existing Budget / BudgetCategory pacing data to the AI
assistant as a `get_budget` function. Supports a target month and an
optional `prior_months` window for trend comparison, with the response
shape matching the budget UI (totals, income, per-category status,
suggested daily spend on the current month).

Honors custom month_start_day by matching `Budget.param_to_date`
semantics for explicit slug input, so `month` round-trips with the
response's `month` field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(assistant): use fixture reference for Food & Drink lookup

Replace fragile string match on `bc.category.name == "Food & Drink"`
with the `categories(:food_and_drink)` fixture so the test setup
isn't sensitive to category-name translations.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(assistant): enforce strict month format in get_budget

`Date.strptime` is lenient about trailing characters, so inputs like
`"2026-05-01"` or `"may-2026foo"` were parsing successfully and being
silently truncated to May 2026. Pre-validate the raw string with anchored
regex patterns for the documented YYYY-MM and MMM-YYYY shapes so
malformed tool arguments raise Assistant::Error instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(budgets): suggested_daily_spending handles custom-month periods

The helper compared `budget.start_date.month/year` against
`Date.current.month/year` and returned nil whenever the current period
straddled two calendar months — common for families with
`month_start_day != 1` (e.g., May 15–Jun 14 viewed on Jun 1). Replace
the calendar-month check with `budget.current?` and compute remaining
days from `budget.end_date` so the helper works for both standard and
custom periods. This also restores the daily pacing row in the budget
UI for custom-month families.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(assistant): make get_budget read-only for prior months

`prior_months: N` was calling `Budget.find_or_bootstrap` for every
month, which created empty `Budget` rows (and synced `BudgetCategory`
children) as a side effect of an AI query. Only the explicit target
month now bootstraps; prior months use `Budget.find_by` and are
dropped from the response if they don't exist. The response now
includes `months_unavailable: N` so the LLM can phrase a sensible
answer when fewer months come back than requested.

Extract `Budget.period_for(date, family:)` to share the date-bracket
math between `find_or_bootstrap`, `budget_date_valid?`, and the new
read-only path in `get_budget`.

Adds two tests covering the no-bootstrap behavior for prior months
and the `prior_months` clamp at `MAX_PRIOR_MONTHS`. Updates the
existing N+1 sorted-months test to seed prior budgets explicitly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: wolstad <wesleyolstad@protonmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 00:51:16 +02:00
Juan José Mata
9e57954a99 Add Family vector search function call / support for document vault (#961)
* Add SearchFamilyImportedFiles assistant function with vector store support

Implement per-Family document search using OpenAI vector stores, allowing
the AI assistant to search through uploaded financial documents (tax returns,
statements, contracts, etc.). The architecture is modular with a provider-
agnostic VectorStoreConcept interface so other RAG backends can be added.

Key components:
- Assistant::Function::SearchFamilyImportedFiles - tool callable from any LLM
- Provider::VectorStoreConcept - abstract vector store interface
- Provider::Openai vector store methods (create, upload, search, delete)
- Family::VectorSearchable concern with document management
- FamilyDocument model for tracking uploaded files
- Migration adding vector_store_id to families and family_documents table

https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh

* Extract VectorStore adapter layer for swappable backends

Replace the Provider::VectorStoreConcept mixin with a standalone adapter
architecture under VectorStore::. This cleanly separates vector store
concerns from the LLM provider and makes it trivial to swap backends.

Components:
- VectorStore::Base — abstract interface (create/delete/upload/remove/search)
- VectorStore::Openai — uses ruby-openai gem's native vector_stores.search
- VectorStore::Pgvector — skeleton for local pgvector + embedding model
- VectorStore::Qdrant — skeleton for Qdrant vector DB
- VectorStore::Registry — resolves adapter from VECTOR_STORE_PROVIDER env
- VectorStore::Response — success/failure wrapper (like Provider::Response)

Consumers updated to go through VectorStore.adapter:
- Family::VectorSearchable
- Assistant::Function::SearchFamilyImportedFiles
- FamilyDocument

Removed: Provider::VectorStoreConcept, vector store methods from Provider::Openai

https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh

* Add Vector Store configuration docs to ai.md

Documents how to configure the document search feature, covering all
three supported backends (OpenAI, pgvector, Qdrant), environment
variables, Docker Compose examples, supported file types, and privacy
considerations.

https://claude.ai/code/session_01TSkKc7a9Yu2ugm1RvSf4dh

* No need to specify `imported` in code

* Missed a couple more places

* Tiny reordering for the human OCD

* Update app/models/assistant/function/search_family_files.rb

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>

* PR comments

* More PR comments

---------

Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-02-11 15:22:56 +01:00