finance-copilot 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. finance_copilot/__init__.py +1 -0
  2. finance_copilot/__main__.py +58 -0
  3. finance_copilot/api/__init__.py +1 -0
  4. finance_copilot/api/deps.py +16 -0
  5. finance_copilot/api/routes/__init__.py +1 -0
  6. finance_copilot/api/routes/annotations.py +712 -0
  7. finance_copilot/api/routes/categories.py +74 -0
  8. finance_copilot/api/routes/config.py +126 -0
  9. finance_copilot/api/routes/data.py +234 -0
  10. finance_copilot/api/routes/embeddings.py +157 -0
  11. finance_copilot/api/routes/groups.py +138 -0
  12. finance_copilot/api/routes/insights.py +19 -0
  13. finance_copilot/api/routes/local_llm.py +134 -0
  14. finance_copilot/api/routes/people.py +80 -0
  15. finance_copilot/api/routes/rules.py +103 -0
  16. finance_copilot/api/routes/statements.py +196 -0
  17. finance_copilot/api/routes/transactions.py +163 -0
  18. finance_copilot/app.py +137 -0
  19. finance_copilot/cli.py +101 -0
  20. finance_copilot/config.py +208 -0
  21. finance_copilot/db/__init__.py +1 -0
  22. finance_copilot/db/connection.py +145 -0
  23. finance_copilot/db/lifecycle.py +55 -0
  24. finance_copilot/db/migrations/001_initial.sql +57 -0
  25. finance_copilot/db/migrations/002_links.sql +23 -0
  26. finance_copilot/db/migrations/003_people.sql +13 -0
  27. finance_copilot/db/migrations/004_member_type.sql +6 -0
  28. finance_copilot/db/migrations/005_drop_group_type.sql +4 -0
  29. finance_copilot/db/migrations/006_seed_categories.sql +122 -0
  30. finance_copilot/db/migrations/007_expand_annotation_source.sql +21 -0
  31. finance_copilot/db/migrations/008_feedback_stats.sql +12 -0
  32. finance_copilot/db/migrations/009_add_reimbursement_category.sql +3 -0
  33. finance_copilot/db/migrations/010_provenance_dedup_indexes.sql +14 -0
  34. finance_copilot/db/migrations/011_annotation_jobs.sql +14 -0
  35. finance_copilot/db/migrations/012_statement_period.sql +9 -0
  36. finance_copilot/db/migrations/013_category_ids.sql +24 -0
  37. finance_copilot/db/migrations/014_json_list_columns.sql +29 -0
  38. finance_copilot/db/migrations/015_annotation_reasoning.sql +6 -0
  39. finance_copilot/db/migrations/016_app_settings.sql +10 -0
  40. finance_copilot/db/migrations/017_counterparty_key.sql +26 -0
  41. finance_copilot/db/migrations/018_self_transfers_category.sql +22 -0
  42. finance_copilot/db/migrations/019_annotation_source_learned_rule_rag_knn.sql +35 -0
  43. finance_copilot/db/migrations/020_person_relationship_and_learned_rule_suppressions.sql +27 -0
  44. finance_copilot/db/migrations/021_statement_balances.sql +58 -0
  45. finance_copilot/db/migrations/022_statement_account_ref.sql +9 -0
  46. finance_copilot/db/migrations/023_transaction_links.sql +16 -0
  47. finance_copilot/db/migrations/024_annotation_review_snooze.sql +11 -0
  48. finance_copilot/db/migrations/025_job_kind.sql +5 -0
  49. finance_copilot/db/migrations/026_user_rules.sql +56 -0
  50. finance_copilot/db/queries/__init__.py +1 -0
  51. finance_copilot/db/queries/annotations.py +159 -0
  52. finance_copilot/db/queries/app_settings.py +154 -0
  53. finance_copilot/db/queries/categories.py +144 -0
  54. finance_copilot/db/queries/common.py +28 -0
  55. finance_copilot/db/queries/embeddings.py +206 -0
  56. finance_copilot/db/queries/feedback_stats.py +88 -0
  57. finance_copilot/db/queries/groups.py +237 -0
  58. finance_copilot/db/queries/insights.py +772 -0
  59. finance_copilot/db/queries/learned_rules.py +218 -0
  60. finance_copilot/db/queries/people.py +179 -0
  61. finance_copilot/db/queries/transactions.py +298 -0
  62. finance_copilot/db/queries/user_rules.py +253 -0
  63. finance_copilot/demo_seed.py +560 -0
  64. finance_copilot/local_llm.py +356 -0
  65. finance_copilot/main.py +254 -0
  66. finance_copilot/models/__init__.py +1 -0
  67. finance_copilot/models/annotation.py +132 -0
  68. finance_copilot/models/transaction.py +48 -0
  69. finance_copilot/parsers/__init__.py +1 -0
  70. finance_copilot/parsers/banks/__init__.py +1 -0
  71. finance_copilot/parsers/banks/kotak.py +96 -0
  72. finance_copilot/parsers/base.py +46 -0
  73. finance_copilot/parsers/generic.py +401 -0
  74. finance_copilot/parsers/registry.py +32 -0
  75. finance_copilot/parsers/upi.py +42 -0
  76. finance_copilot/pipeline/__init__.py +1 -0
  77. finance_copilot/pipeline/annotate.py +1036 -0
  78. finance_copilot/pipeline/calibration.py +58 -0
  79. finance_copilot/pipeline/counterparty.py +201 -0
  80. finance_copilot/pipeline/embed.py +299 -0
  81. finance_copilot/pipeline/ingest.py +236 -0
  82. finance_copilot/pipeline/llm.py +568 -0
  83. finance_copilot/pipeline/rules.py +234 -0
  84. finance_copilot/pipeline/run_summary.py +192 -0
  85. finance_copilot/pipeline/sources.py +33 -0
  86. finance_copilot/ui_dist/assets/CategoryPicker-Cm0NSo75.js +1 -0
  87. finance_copilot/ui_dist/assets/ConfirmDialog-OLzxIURy.js +1 -0
  88. finance_copilot/ui_dist/assets/Dashboard-BSVQzNdb.js +21 -0
  89. finance_copilot/ui_dist/assets/EmptyState-DWGf9hQV.js +1 -0
  90. finance_copilot/ui_dist/assets/Groups-CxbdIaHH.js +1 -0
  91. finance_copilot/ui_dist/assets/Insights-CAcvj1Wu.js +1 -0
  92. finance_copilot/ui_dist/assets/People-C9IyajLX.js +1 -0
  93. finance_copilot/ui_dist/assets/PeriodPicker-oXvMQJaq.js +1 -0
  94. finance_copilot/ui_dist/assets/ReasoningPanel-CCk-75_X.js +6 -0
  95. finance_copilot/ui_dist/assets/ReviewQueue-DBBU47Q9.js +26 -0
  96. finance_copilot/ui_dist/assets/Settings-DHQMZoY-.js +56 -0
  97. finance_copilot/ui_dist/assets/Transactions-X_Kspt5O.js +1 -0
  98. finance_copilot/ui_dist/assets/Upload-PHdAA6CH.js +21 -0
  99. finance_copilot/ui_dist/assets/chevron-down-BOTn-jA0.js +6 -0
  100. finance_copilot/ui_dist/assets/chevron-right-1ZTDEAuV.js +6 -0
  101. finance_copilot/ui_dist/assets/circle-check-DVy3w3Qy.js +6 -0
  102. finance_copilot/ui_dist/assets/circle-help-B0D8uify.js +6 -0
  103. finance_copilot/ui_dist/assets/dates-DENdhcfJ.js +1 -0
  104. finance_copilot/ui_dist/assets/index-B86kwi0r.css +1 -0
  105. finance_copilot/ui_dist/assets/index-CttMkFOe.js +175 -0
  106. finance_copilot/ui_dist/assets/index-D94rVQ8L.js +18 -0
  107. finance_copilot/ui_dist/assets/pencil-BdwggxyK.js +11 -0
  108. finance_copilot/ui_dist/assets/plus-DTgrI-ia.js +6 -0
  109. finance_copilot/ui_dist/assets/refresh-cw-BYXFldMU.js +6 -0
  110. finance_copilot/ui_dist/assets/trash-2-Oxw5TKtt.js +6 -0
  111. finance_copilot/ui_dist/assets/zap-C-11zHGY.js +6 -0
  112. finance_copilot/ui_dist/index.html +13 -0
  113. finance_copilot-0.1.0.dist-info/METADATA +291 -0
  114. finance_copilot-0.1.0.dist-info/RECORD +116 -0
  115. finance_copilot-0.1.0.dist-info/WHEEL +4 -0
  116. finance_copilot-0.1.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1 @@
1
+ """Personal finance budgeting automation — local-first ingestion, embeddings, and RAG annotation."""
@@ -0,0 +1,58 @@
1
+ """Run the API server: `python -m src`.
2
+
3
+ Owns the host default (127.0.0.1) so the API - and every bank statement it
4
+ serves - is loopback-only unless the user deliberately opts into LAN exposure.
5
+ There is no authentication layer yet (single-user local product), so a
6
+ non-loopback bind is a real disclosure and gets a loud warning, never a silent
7
+ copy-pasted default.
8
+
9
+ Config via environment: HOST (default 127.0.0.1), PORT (default 8000),
10
+ RELOAD (set to 1/true for auto-reload during development).
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import ipaddress
15
+ import logging
16
+ import os
17
+
18
+ import uvicorn
19
+
20
+ logger = logging.getLogger("finance_copilot")
21
+
22
+ # Names ip_address() cannot parse but which are still loopback in practice.
23
+ _LOOPBACK_NAMES = {"localhost", "localhost.localdomain"}
24
+
25
+
26
+ def _is_loopback(host: str) -> bool:
27
+ if host in _LOOPBACK_NAMES:
28
+ return True
29
+ try:
30
+ return ipaddress.ip_address(host).is_loopback
31
+ except ValueError:
32
+ # A hostname we can't resolve to a literal — treat as non-loopback so we
33
+ # err toward warning rather than staying silent.
34
+ return False
35
+
36
+
37
+ def warn_if_exposed(host: str) -> None:
38
+ """Warn when binding somewhere other than loopback (0.0.0.0, a LAN IP, etc.)."""
39
+ if _is_loopback(host):
40
+ return
41
+ logger.warning(
42
+ "Binding to %s exposes the API - and every bank statement it serves - to "
43
+ "your whole network with NO authentication. Bind to 127.0.0.1 (the default) "
44
+ "unless you specifically intend LAN access.",
45
+ host,
46
+ )
47
+
48
+
49
+ def main() -> None:
50
+ host = os.getenv("HOST", "127.0.0.1")
51
+ port = int(os.getenv("PORT", "8000"))
52
+ reload = os.getenv("RELOAD", "").lower() in ("1", "true", "yes")
53
+ warn_if_exposed(host)
54
+ uvicorn.run("finance_copilot.main:app", host=host, port=port, reload=reload)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
@@ -0,0 +1 @@
1
+ """FastAPI application wiring: routes and shared dependencies."""
@@ -0,0 +1,16 @@
1
+ """Shared FastAPI dependencies (e.g. database connection or session accessors)."""
2
+ from __future__ import annotations
3
+
4
+ import sqlite3
5
+ from collections.abc import Generator
6
+
7
+ from finance_copilot.db.connection import get_connection
8
+
9
+
10
+ def get_db() -> Generator[sqlite3.Connection, None, None]:
11
+ """Per-request connection. Migrations run once at startup (lifespan), not here."""
12
+ conn = get_connection()
13
+ try:
14
+ yield conn
15
+ finally:
16
+ conn.close()
@@ -0,0 +1 @@
1
+ """HTTP route modules for statements, transactions, annotations, groups, people, embeddings, and categories."""