@cachly-dev/mcp-server 0.10.64 → 0.10.66

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 (270) hide show
  1. package/dist/src/handlers/brain.js +1 -1
  2. package/dist/src/index.js +1 -1
  3. package/package.json +7 -1
  4. package/server.json +2 -2
  5. package/.env.test.example +0 -23
  6. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -50
  7. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  8. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -25
  9. package/.github/workflows/eas-build-android.yml +0 -58
  10. package/.github/workflows/eas-update.yml +0 -55
  11. package/.github/workflows/publish.yml +0 -72
  12. package/BENCH.md +0 -91
  13. package/CHANGELOG.md +0 -604
  14. package/CHANGELOG.md.tmp +0 -0
  15. package/Dockerfile +0 -16
  16. package/LAUNCH_TEXTS.md +0 -182
  17. package/PROGRESS.md +0 -137
  18. package/STRATEGY.md +0 -228
  19. package/VISION_10X.md +0 -133
  20. package/apps/travel-chaos-organizer/.env.example +0 -49
  21. package/apps/travel-chaos-organizer/DEPLOY.md +0 -328
  22. package/apps/travel-chaos-organizer/Makefile +0 -57
  23. package/apps/travel-chaos-organizer/README.md +0 -159
  24. package/apps/travel-chaos-organizer/backend/.env.example +0 -10
  25. package/apps/travel-chaos-organizer/backend/Dockerfile +0 -25
  26. package/apps/travel-chaos-organizer/backend/alembic/env.py +0 -56
  27. package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +0 -24
  28. package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
  29. package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +0 -24
  30. package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +0 -24
  31. package/apps/travel-chaos-organizer/backend/alembic.ini +0 -39
  32. package/apps/travel-chaos-organizer/backend/app/__init__.py +0 -0
  33. package/apps/travel-chaos-organizer/backend/app/auth/__init__.py +0 -0
  34. package/apps/travel-chaos-organizer/backend/app/auth/keycloak.py +0 -81
  35. package/apps/travel-chaos-organizer/backend/app/config.py +0 -66
  36. package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
  37. package/apps/travel-chaos-organizer/backend/app/db/database.py +0 -20
  38. package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +0 -71
  39. package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +0 -31
  40. package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +0 -4
  41. package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +0 -5
  42. package/apps/travel-chaos-organizer/backend/app/limiter.py +0 -4
  43. package/apps/travel-chaos-organizer/backend/app/logging_config.py +0 -25
  44. package/apps/travel-chaos-organizer/backend/app/main.py +0 -77
  45. package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
  46. package/apps/travel-chaos-organizer/backend/app/models/schemas.py +0 -142
  47. package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
  48. package/apps/travel-chaos-organizer/backend/app/routers/admin.py +0 -237
  49. package/apps/travel-chaos-organizer/backend/app/routers/cache.py +0 -13
  50. package/apps/travel-chaos-organizer/backend/app/routers/events.py +0 -29
  51. package/apps/travel-chaos-organizer/backend/app/routers/export.py +0 -122
  52. package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +0 -122
  53. package/apps/travel-chaos-organizer/backend/app/routers/items.py +0 -130
  54. package/apps/travel-chaos-organizer/backend/app/routers/mail.py +0 -108
  55. package/apps/travel-chaos-organizer/backend/app/routers/parse.py +0 -303
  56. package/apps/travel-chaos-organizer/backend/app/routers/payments.py +0 -179
  57. package/apps/travel-chaos-organizer/backend/app/routers/trips.py +0 -134
  58. package/apps/travel-chaos-organizer/backend/app/routers/users.py +0 -169
  59. package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +0 -37
  60. package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
  61. package/apps/travel-chaos-organizer/backend/app/services/cache.py +0 -131
  62. package/apps/travel-chaos-organizer/backend/app/services/drip.py +0 -128
  63. package/apps/travel-chaos-organizer/backend/app/services/email.py +0 -61
  64. package/apps/travel-chaos-organizer/backend/app/services/errors.py +0 -44
  65. package/apps/travel-chaos-organizer/backend/app/services/notifier.py +0 -10
  66. package/apps/travel-chaos-organizer/backend/app/services/ollama.py +0 -101
  67. package/apps/travel-chaos-organizer/backend/app/services/parser.py +0 -22
  68. package/apps/travel-chaos-organizer/backend/app/services/quota.py +0 -85
  69. package/apps/travel-chaos-organizer/backend/app/services/sentry.py +0 -11
  70. package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +0 -35
  71. package/apps/travel-chaos-organizer/backend/pytest.ini +0 -4
  72. package/apps/travel-chaos-organizer/backend/requirements-dev.txt +0 -6
  73. package/apps/travel-chaos-organizer/backend/requirements.txt +0 -25
  74. package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
  75. package/apps/travel-chaos-organizer/backend/tests/conftest.py +0 -223
  76. package/apps/travel-chaos-organizer/backend/tests/test_admin.py +0 -99
  77. package/apps/travel-chaos-organizer/backend/tests/test_cache.py +0 -142
  78. package/apps/travel-chaos-organizer/backend/tests/test_drip.py +0 -32
  79. package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +0 -121
  80. package/apps/travel-chaos-organizer/backend/tests/test_export.py +0 -48
  81. package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +0 -107
  82. package/apps/travel-chaos-organizer/backend/tests/test_items.py +0 -138
  83. package/apps/travel-chaos-organizer/backend/tests/test_mail.py +0 -113
  84. package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +0 -145
  85. package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +0 -98
  86. package/apps/travel-chaos-organizer/backend/tests/test_parser.py +0 -72
  87. package/apps/travel-chaos-organizer/backend/tests/test_payments.py +0 -163
  88. package/apps/travel-chaos-organizer/backend/tests/test_quota.py +0 -46
  89. package/apps/travel-chaos-organizer/backend/tests/test_search.py +0 -67
  90. package/apps/travel-chaos-organizer/backend/tests/test_trips.py +0 -123
  91. package/apps/travel-chaos-organizer/backend/tests/test_users.py +0 -52
  92. package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
  93. package/apps/travel-chaos-organizer/caddy/Caddyfile +0 -27
  94. package/apps/travel-chaos-organizer/docker-compose.node1.yml +0 -31
  95. package/apps/travel-chaos-organizer/docker-compose.override.yml +0 -14
  96. package/apps/travel-chaos-organizer/docker-compose.yml +0 -128
  97. package/apps/travel-chaos-organizer/frontend/.env.example +0 -13
  98. package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +0 -80
  99. package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +0 -166
  100. package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +0 -130
  101. package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +0 -381
  102. package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +0 -346
  103. package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +0 -363
  104. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +0 -34
  105. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +0 -35
  106. package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +0 -91
  107. package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +0 -71
  108. package/apps/travel-chaos-organizer/frontend/app/auth.tsx +0 -29
  109. package/apps/travel-chaos-organizer/frontend/app/index.tsx +0 -16
  110. package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +0 -119
  111. package/apps/travel-chaos-organizer/frontend/app.config.ts +0 -54
  112. package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +0 -66
  113. package/apps/travel-chaos-organizer/frontend/assets/icon.svg +0 -79
  114. package/apps/travel-chaos-organizer/frontend/assets/splash.svg +0 -15
  115. package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +0 -102
  116. package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +0 -107
  117. package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +0 -109
  118. package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +0 -45
  119. package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +0 -19
  120. package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +0 -155
  121. package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +0 -55
  122. package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +0 -80
  123. package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +0 -39
  124. package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +0 -39
  125. package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +0 -70
  126. package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +0 -121
  127. package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +0 -70
  128. package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +0 -73
  129. package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +0 -130
  130. package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +0 -60
  131. package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +0 -42
  132. package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +0 -146
  133. package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +0 -70
  134. package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +0 -44
  135. package/apps/travel-chaos-organizer/frontend/eas.json +0 -22
  136. package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +0 -24
  137. package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +0 -60
  138. package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +0 -112
  139. package/apps/travel-chaos-organizer/frontend/lib/api.ts +0 -223
  140. package/apps/travel-chaos-organizer/frontend/lib/auth.ts +0 -93
  141. package/apps/travel-chaos-organizer/frontend/lib/db.ts +0 -86
  142. package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +0 -54
  143. package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +0 -13
  144. package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +0 -112
  145. package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +0 -145
  146. package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +0 -43
  147. package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +0 -28
  148. package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +0 -44
  149. package/apps/travel-chaos-organizer/frontend/package-lock.json +0 -13221
  150. package/apps/travel-chaos-organizer/frontend/package.json +0 -44
  151. package/apps/travel-chaos-organizer/frontend/tsconfig.json +0 -23
  152. package/apps/travel-chaos-organizer/keycloak/realm-export.json +0 -59
  153. package/apps/travel-chaos-organizer/landing/index.html +0 -773
  154. package/apps/travel-chaos-organizer/scripts/backup.sh +0 -14
  155. package/apps/travel-chaos-organizer/scripts/configure-env.sh +0 -82
  156. package/apps/travel-chaos-organizer/scripts/deploy.sh +0 -54
  157. package/apps/travel-chaos-organizer/scripts/health-check.sh +0 -36
  158. package/apps/travel-chaos-organizer/scripts/migrate.sh +0 -7
  159. package/apps/travel-chaos-organizer/scripts/server-setup.sh +0 -85
  160. package/apps/travel-chaos-organizer/scripts/smoke-test.sh +0 -29
  161. package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +0 -71
  162. package/apps/travel-chaos-organizer/telegram-bot/.env.example +0 -3
  163. package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +0 -6
  164. package/apps/travel-chaos-organizer/telegram-bot/bot.py +0 -504
  165. package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +0 -3
  166. package/dist/src/__tests__/auth.test.d.ts +0 -1
  167. package/dist/src/__tests__/auth.test.js +0 -107
  168. package/dist/src/__tests__/auth.test.js.map +0 -1
  169. package/dist/src/__tests__/brain-flow.test.d.ts +0 -12
  170. package/dist/src/__tests__/brain-flow.test.js +0 -1241
  171. package/dist/src/__tests__/brain-flow.test.js.map +0 -1
  172. package/dist/src/__tests__/confidence.test.d.ts +0 -13
  173. package/dist/src/__tests__/confidence.test.js +0 -233
  174. package/dist/src/__tests__/confidence.test.js.map +0 -1
  175. package/dist/src/__tests__/e2e/api-auth.test.d.ts +0 -7
  176. package/dist/src/__tests__/e2e/api-auth.test.js +0 -162
  177. package/dist/src/__tests__/e2e/api-auth.test.js.map +0 -1
  178. package/dist/src/__tests__/e2e/api-health.test.d.ts +0 -7
  179. package/dist/src/__tests__/e2e/api-health.test.js +0 -95
  180. package/dist/src/__tests__/e2e/api-health.test.js.map +0 -1
  181. package/dist/src/__tests__/e2e/cli.test.d.ts +0 -10
  182. package/dist/src/__tests__/e2e/cli.test.js +0 -204
  183. package/dist/src/__tests__/e2e/cli.test.js.map +0 -1
  184. package/dist/src/__tests__/e2e/config.d.ts +0 -35
  185. package/dist/src/__tests__/e2e/config.js +0 -53
  186. package/dist/src/__tests__/e2e/config.js.map +0 -1
  187. package/dist/src/__tests__/e2e/funnel.test.d.ts +0 -13
  188. package/dist/src/__tests__/e2e/funnel.test.js +0 -90
  189. package/dist/src/__tests__/e2e/funnel.test.js.map +0 -1
  190. package/dist/src/__tests__/e2e/mcp-tools.test.d.ts +0 -7
  191. package/dist/src/__tests__/e2e/mcp-tools.test.js +0 -129
  192. package/dist/src/__tests__/e2e/mcp-tools.test.js.map +0 -1
  193. package/dist/src/__tests__/e2e/provisioning.test.d.ts +0 -15
  194. package/dist/src/__tests__/e2e/provisioning.test.js +0 -123
  195. package/dist/src/__tests__/e2e/provisioning.test.js.map +0 -1
  196. package/dist/src/__tests__/handlers-unit.test.d.ts +0 -12
  197. package/dist/src/__tests__/handlers-unit.test.js +0 -505
  198. package/dist/src/__tests__/handlers-unit.test.js.map +0 -1
  199. package/dist/src/__tests__/namespace.test.d.ts +0 -1
  200. package/dist/src/__tests__/namespace.test.js +0 -114
  201. package/dist/src/__tests__/namespace.test.js.map +0 -1
  202. package/dist/src/__tests__/rerank.test.d.ts +0 -1
  203. package/dist/src/__tests__/rerank.test.js +0 -115
  204. package/dist/src/__tests__/rerank.test.js.map +0 -1
  205. package/dist/src/__tests__/utils.test.d.ts +0 -1
  206. package/dist/src/__tests__/utils.test.js +0 -83
  207. package/dist/src/__tests__/utils.test.js.map +0 -1
  208. package/dist/src/bench/cachly-bench.d.ts +0 -35
  209. package/dist/src/bench/cachly-bench.js +0 -182
  210. package/dist/src/bench/cachly-bench.js.map +0 -1
  211. package/dist/src/bench/fixtures.d.ts +0 -37
  212. package/dist/src/bench/fixtures.js +0 -225
  213. package/dist/src/bench/fixtures.js.map +0 -1
  214. package/dist/src/search.test.d.ts +0 -1
  215. package/dist/src/search.test.js +0 -713
  216. package/dist/src/search.test.js.map +0 -1
  217. package/eslint.config.js +0 -16
  218. package/glama.json +0 -36
  219. package/llms.txt +0 -155
  220. package/packages/telegram-notify/SPLIT_PLAN.md +0 -106
  221. package/packages/telegram-notify/client.ts +0 -88
  222. package/packages/telegram-notify/emojis.json +0 -22
  223. package/packages/telegram-notify/pyproject.toml +0 -17
  224. package/packages/telegram-notify/telegram_notify/__init__.py +0 -3
  225. package/packages/telegram-notify/telegram_notify/client.py +0 -87
  226. package/packages/telegram-notify/telegram_notify/emojis.json +0 -22
  227. package/scripts/e2e-run.sh +0 -160
  228. package/scripts/generate-icons.js +0 -28
  229. package/smithery.yaml +0 -45
  230. package/src/__tests__/auth.test.ts +0 -147
  231. package/src/__tests__/brain-flow.test.ts +0 -1472
  232. package/src/__tests__/confidence.test.ts +0 -285
  233. package/src/__tests__/e2e/api-auth.test.ts +0 -182
  234. package/src/__tests__/e2e/api-health.test.ts +0 -103
  235. package/src/__tests__/e2e/cli.test.ts +0 -228
  236. package/src/__tests__/e2e/config.ts +0 -53
  237. package/src/__tests__/e2e/funnel.test.ts +0 -99
  238. package/src/__tests__/e2e/mcp-tools.test.ts +0 -191
  239. package/src/__tests__/e2e/provisioning.test.ts +0 -128
  240. package/src/__tests__/handlers-unit.test.ts +0 -677
  241. package/src/__tests__/namespace.test.ts +0 -126
  242. package/src/__tests__/rerank.test.ts +0 -130
  243. package/src/__tests__/utils.test.ts +0 -81
  244. package/src/auth.ts +0 -46
  245. package/src/bench/cachly-bench.ts +0 -217
  246. package/src/bench/fixtures.ts +0 -256
  247. package/src/ckg.ts +0 -103
  248. package/src/confidence.ts +0 -38
  249. package/src/embeddings.ts +0 -217
  250. package/src/handlers/advanced.ts +0 -647
  251. package/src/handlers/brain.ts +0 -2622
  252. package/src/handlers/cache.ts +0 -633
  253. package/src/handlers/context.ts +0 -222
  254. package/src/handlers/fedbrain.ts +0 -1232
  255. package/src/handlers/instances.ts +0 -180
  256. package/src/handlers/roadmap.ts +0 -201
  257. package/src/handlers/syndicate.ts +0 -460
  258. package/src/handlers/tco.ts +0 -345
  259. package/src/handlers/team.ts +0 -1249
  260. package/src/index.ts +0 -2815
  261. package/src/namespace.ts +0 -128
  262. package/src/notifier.ts +0 -5
  263. package/src/rerank.ts +0 -148
  264. package/src/search.test.ts +0 -848
  265. package/src/search.ts +0 -1781
  266. package/src/tools.ts +0 -2056
  267. package/src/utils.ts +0 -90
  268. package/test-features.cjs +0 -23
  269. package/tsconfig.json +0 -16
  270. package/vitest.config.ts +0 -14
@@ -1,159 +0,0 @@
1
- # Travel Chaos Organizer
2
-
3
- Reisechaos automatisch organisieren — Screenshots, Buchungen, PDFs und Tickets in einer smarten Timeline.
4
-
5
- ## Stack
6
-
7
- | Layer | Tech |
8
- |---|---|
9
- | Mobile | React Native + Expo SDK 52 |
10
- | Auth | Keycloak (self-hosted, OIDC + PKCE) |
11
- | Backend | Python 3.12 + FastAPI |
12
- | Datenbank | PostgreSQL 16 |
13
- | AI Parsing | Ollama (Vision-Modell, konfigurierbar) |
14
- | Offline | expo-sqlite + expo-file-system |
15
-
16
- ## Architektur
17
-
18
- ```
19
- Expo App ──OIDC──► Keycloak
20
- │
21
- └──REST──► FastAPI Backend
22
- │
23
- ├── PostgreSQL
24
- ├── /data/uploads (Dateien)
25
- └── Ollama API (AI Parsing)
26
- ```
27
-
28
- ## Lokales Setup
29
-
30
- ### 1. Voraussetzungen
31
- - Docker + Docker Compose
32
- - Ollama auf eurem Server mit Vision-Modell
33
-
34
- ### 2. Backend starten
35
-
36
- ```bash
37
- cd apps/travel-chaos-organizer
38
- cp .env.example .env
39
- # OLLAMA_URL auf euren Server anpassen
40
- docker compose up -d
41
- ```
42
-
43
- Die API ist dann unter `http://localhost:8000` erreichbar.
44
- Swagger UI: `http://localhost:8000/docs`
45
- Keycloak Admin: `http://localhost:8080` (admin/admin)
46
-
47
- ### 3. Frontend starten
48
-
49
- ```bash
50
- cd frontend
51
- cp .env.example .env
52
- # EXPO_PUBLIC_API_URL + Keycloak-URLs anpassen
53
- npm install
54
- npm start
55
- ```
56
-
57
- ## API Endpoints
58
-
59
- ### Trips
60
- | Method | Path | Beschreibung |
61
- |---|---|---|
62
- | GET | `/api/v1/trips` | Alle Trips des Users |
63
- | POST | `/api/v1/trips` | Neuen Trip anlegen |
64
- | GET | `/api/v1/trips/{id}` | Trip Details |
65
- | PATCH | `/api/v1/trips/{id}` | Trip updaten |
66
- | DELETE | `/api/v1/trips/{id}` | Trip löschen |
67
-
68
- ### Trip Items (Timeline)
69
- | Method | Path | Beschreibung |
70
- |---|---|---|
71
- | GET | `/api/v1/trips/{id}/items` | Timeline-Einträge |
72
- | POST | `/api/v1/trips/{id}/items` | Manuell hinzufügen |
73
- | PATCH | `/api/v1/trips/{id}/items/{item_id}` | Item updaten |
74
- | DELETE | `/api/v1/trips/{id}/items/{item_id}` | Item löschen |
75
-
76
- ### AI Parsing
77
- | Method | Path | Beschreibung |
78
- |---|---|---|
79
- | POST | `/api/v1/parse/file` | PDF / Bild / Text-Datei parsen |
80
- | POST | `/api/v1/parse/text` | Raw-Text parsen |
81
-
82
- ### Chaos Inbox
83
- | Method | Path | Beschreibung |
84
- |---|---|---|
85
- | GET | `/api/v1/inbox` | Unsortierten Eingang anzeigen |
86
- | POST | `/api/v1/inbox/{id}/assign` | Item einem Trip zuweisen |
87
- | DELETE | `/api/v1/inbox/{id}` | Item ablehnen |
88
-
89
- ## Cachly Integration
90
-
91
- ### Redis-Cache für Ollama-Ergebnisse (Kernintegration)
92
-
93
- TCO nutzt **Cachly's Redis** als Deduplizierungs-Cache für Ollama-Parse-Ergebnisse.
94
- Dasselbe PDF zweimal hochgeladen → sofortige Antwort aus dem Cache, kein zweiter AI-Call.
95
-
96
- ```
97
- ┌─────────────┐ parse_text(content) ┌──────────────────┐
98
- │ TCO Backend│ ──── cache hit? ────────► │ Cachly Redis │
99
- │ │ ◄─── hit: return dict ─── │ (tco:parse:*) │
100
- │ │ miss: call Ollama └──────────────────┘
101
- └─────────────┘ └── store result ──────────────────►┘
102
- ```
103
-
104
- **Setup:**
105
- ```bash
106
- # In apps/travel-chaos-organizer/.env
107
- CACHLY_REDIS_URL=redis://:<password>@<host>.cachly.dev:6380/0
108
- ```
109
-
110
- Die Redis-URL findest du in deiner Cachly-Instanz unter *Connection String*.
111
- `/health` zeigt `cachly_cache: enabled` sobald die Verbindung steht.
112
-
113
- ### MCP-Bridge (Power-User, optional)
114
-
115
- Für Claude-Nutzer mit cachly-mcp: TCO-Tools sind als MCP-Tools verfügbar.
116
- Da beide Dienste dieselbe Keycloak-Instanz teilen, wird das JWT direkt forwarded.
117
-
118
- ```bash
119
- # In cachly-mcp env
120
- TCO_API_URL=http://localhost:8000
121
- ```
122
-
123
- Verfügbare Tools: `tco_list_trips`, `tco_create_trip`, `tco_get_timeline`,
124
- `tco_inbox_list`, `tco_inbox_assign`, `tco_parse_url`, `tco_import_email` u.a.
125
-
126
- ## Aus dem Repo herauslösen
127
-
128
- Das Projekt ist vollständig isoliert in `apps/travel-chaos-organizer/`.
129
- Zum Herauslösen als eigenes Repo:
130
-
131
- ```bash
132
- # Aus dem Monorepo extrahieren
133
- git subtree split --prefix=apps/travel-chaos-organizer -b standalone-tco
134
- git push <neues-remote> standalone-tco:main
135
- ```
136
-
137
- Keine Abhängigkeiten zu cachly-mcp Code.
138
-
139
- ## Datenstruktur
140
-
141
- ```
142
- trips user_id, name, start_date, end_date
143
- └── trip_items type, title, parsed_data (JSONB), event_at
144
- └── attachments file_path, mime_type
145
-
146
- chaos_inbox raw_content, parsed_data, status
147
- └── attachments
148
- ```
149
-
150
- ## Ollama Modell konfigurieren
151
-
152
- In `.env`:
153
- ```
154
- OLLAMA_URL=http://dein-server:11434
155
- OLLAMA_MODEL=llama3.2-vision # oder llava, bakllava, etc.
156
- ```
157
-
158
- Das Modell muss Vision-Fähigkeit haben für Screenshot-Parsing.
159
- Für reines Text/PDF-Parsing reicht auch ein Text-only Modell.
@@ -1,10 +0,0 @@
1
- # Sentry (optional — get DSN at sentry.io)
2
- # SENTRY_DSN=https://...@sentry.io/...
3
- ENVIRONMENT=production
4
-
5
- # Stripe (https://dashboard.stripe.com/apikeys)
6
- # STRIPE_SECRET_KEY=sk_live_...
7
- # STRIPE_WEBHOOK_SECRET=whsec_...
8
- # STRIPE_PRO_PRICE_ID=price_...
9
- STRIPE_SUCCESS_URL=https://YOUR_DOMAIN/upgrade/success
10
- STRIPE_CANCEL_URL=https://YOUR_DOMAIN/upgrade/cancel
@@ -1,25 +0,0 @@
1
- FROM python:3.12-slim
2
-
3
- # system deps for PyMuPDF and python-magic
4
- RUN apt-get update && apt-get install -y --no-install-recommends \
5
- libmagic1 \
6
- && rm -rf /var/lib/apt/lists/*
7
-
8
- WORKDIR /app
9
-
10
- # Install shared monorepo package first (build context = repo root)
11
- COPY packages/telegram-notify /packages/telegram-notify
12
- RUN pip install --no-cache-dir /packages/telegram-notify
13
-
14
- COPY apps/travel-chaos-organizer/backend/requirements.txt .
15
- # Strip the file:// line — package is already installed above
16
- RUN grep -v "telegram-notify" requirements.txt | pip install --no-cache-dir -r /dev/stdin
17
-
18
- COPY apps/travel-chaos-organizer/backend/app/ ./app/
19
-
20
- ENV PYTHONUNBUFFERED=1 \
21
- PYTHONDONTWRITEBYTECODE=1
22
-
23
- EXPOSE 8000
24
-
25
- CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
@@ -1,56 +0,0 @@
1
- import asyncio
2
- import os
3
- from logging.config import fileConfig
4
- from sqlalchemy.ext.asyncio import async_engine_from_config
5
- from sqlalchemy import pool
6
- from alembic import context
7
-
8
- config = context.config
9
-
10
- if config.config_file_name is not None:
11
- fileConfig(config.config_file_name)
12
-
13
- # Allow DATABASE_URL env var to override alembic.ini
14
- db_url = os.getenv("DATABASE_URL", config.get_main_option("sqlalchemy.url"))
15
- config.set_main_option("sqlalchemy.url", db_url)
16
-
17
- target_metadata = None
18
-
19
-
20
- def run_migrations_offline() -> None:
21
- url = config.get_main_option("sqlalchemy.url")
22
- context.configure(
23
- url=url,
24
- target_metadata=target_metadata,
25
- literal_binds=True,
26
- dialect_opts={"paramstyle": "named"},
27
- )
28
- with context.begin_transaction():
29
- context.run_migrations()
30
-
31
-
32
- def do_run_migrations(connection):
33
- context.configure(connection=connection, target_metadata=target_metadata)
34
- with context.begin_transaction():
35
- context.run_migrations()
36
-
37
-
38
- async def run_async_migrations() -> None:
39
- connectable = async_engine_from_config(
40
- config.get_section(config.config_ini_section, {}),
41
- prefix="sqlalchemy.",
42
- poolclass=pool.NullPool,
43
- )
44
- async with connectable.connect() as connection:
45
- await connection.run_sync(do_run_migrations)
46
- await connectable.dispose()
47
-
48
-
49
- def run_migrations_online() -> None:
50
- asyncio.run(run_async_migrations())
51
-
52
-
53
- if context.is_offline_mode():
54
- run_migrations_offline()
55
- else:
56
- run_migrations_online()
@@ -1,24 +0,0 @@
1
- """${message}
2
-
3
- Revision ID: ${up_revision}
4
- Revises: ${down_revision | comma,n}
5
- Create Date: ${create_date}
6
-
7
- """
8
- from typing import Sequence, Union
9
- from alembic import op
10
- import sqlalchemy as sa
11
- ${imports if imports else ""}
12
-
13
- revision: str = ${repr(up_revision)}
14
- down_revision: Union[str, None] = ${repr(down_revision)}
15
- branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
16
- depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
17
-
18
-
19
- def upgrade() -> None:
20
- ${upgrades if upgrades else "pass"}
21
-
22
-
23
- def downgrade() -> None:
24
- ${downgrades if downgrades else "pass"}
@@ -1,24 +0,0 @@
1
- """add stripe_customer_id to users
2
-
3
- Revision ID: 0001
4
- Revises:
5
- Create Date: 2025-01-01 00:00:00.000000
6
- """
7
- from typing import Sequence, Union
8
- from alembic import op
9
- import sqlalchemy as sa
10
-
11
- revision: str = '0001'
12
- down_revision: Union[str, None] = None
13
- branch_labels: Union[str, Sequence[str], None] = None
14
- depends_on: Union[str, Sequence[str], None] = None
15
-
16
-
17
- def upgrade() -> None:
18
- op.add_column('users', sa.Column('stripe_customer_id', sa.Text(), nullable=True))
19
- op.create_index('idx_users_stripe_customer_id', 'users', ['stripe_customer_id'])
20
-
21
-
22
- def downgrade() -> None:
23
- op.drop_index('idx_users_stripe_customer_id', 'users')
24
- op.drop_column('users', 'stripe_customer_id')
@@ -1,24 +0,0 @@
1
- """add telegram_chat_id to users
2
-
3
- Revision ID: 0002
4
- Revises: 0001
5
- Create Date: 2025-01-02 00:00:00.000000
6
- """
7
- from typing import Sequence, Union
8
- from alembic import op
9
- import sqlalchemy as sa
10
-
11
- revision: str = '0002'
12
- down_revision: Union[str, None] = '0001'
13
- branch_labels: Union[str, Sequence[str], None] = None
14
- depends_on: Union[str, Sequence[str], None] = None
15
-
16
-
17
- def upgrade() -> None:
18
- op.add_column('users', sa.Column('telegram_chat_id', sa.Text(), nullable=True))
19
- op.create_index('ix_users_telegram_chat_id', 'users', ['telegram_chat_id'], unique=True)
20
-
21
-
22
- def downgrade() -> None:
23
- op.drop_index('ix_users_telegram_chat_id', 'users')
24
- op.drop_column('users', 'telegram_chat_id')
@@ -1,39 +0,0 @@
1
- [alembic]
2
- script_location = alembic
3
- prepend_sys_path = .
4
- version_path_separator = os
5
- sqlalchemy.url = postgresql+asyncpg://tco:tco@localhost:5432/tco
6
-
7
- [loggers]
8
- keys = root,sqlalchemy,alembic
9
-
10
- [handlers]
11
- keys = console
12
-
13
- [formatters]
14
- keys = generic
15
-
16
- [logger_root]
17
- level = WARN
18
- handlers = console
19
- qualname =
20
-
21
- [logger_sqlalchemy]
22
- level = WARN
23
- handlers =
24
- qualname = sqlalchemy.engine
25
-
26
- [logger_alembic]
27
- level = INFO
28
- handlers =
29
- qualname = alembic
30
-
31
- [handler_console]
32
- class = StreamHandler
33
- args = (sys.stderr,)
34
- level = NOTSET
35
- formatter = generic
36
-
37
- [formatter_generic]
38
- format = %(levelname)-5.5s [%(name)s] %(message)s
39
- datefmt = %H:%M:%S
@@ -1,81 +0,0 @@
1
- from datetime import datetime, timedelta, timezone
2
- from typing import Annotated
3
- import httpx
4
- from fastapi import Depends, HTTPException, Request, status
5
- from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
6
- from jose import JWTError, jwt
7
- from app.config import get_settings
8
- from app.db.database import get_db
9
- from sqlalchemy.ext.asyncio import AsyncSession
10
-
11
- settings = get_settings()
12
- bearer_scheme = HTTPBearer()
13
-
14
- _jwks_cache: dict | None = None
15
- _jwks_cached_at: datetime | None = None
16
- _JWKS_TTL = timedelta(hours=1) # refresh every hour to pick up key rotations
17
-
18
-
19
- async def _get_jwks() -> dict:
20
- global _jwks_cache, _jwks_cached_at
21
- now = datetime.now(timezone.utc)
22
- if _jwks_cache and _jwks_cached_at and (now - _jwks_cached_at) < _JWKS_TTL:
23
- return _jwks_cache
24
- url = f"{settings.keycloak_url}/realms/{settings.keycloak_realm}/protocol/openid-connect/certs"
25
- async with httpx.AsyncClient() as client:
26
- resp = await client.get(url, timeout=10)
27
- resp.raise_for_status()
28
- _jwks_cache = resp.json()
29
- _jwks_cached_at = now
30
- return _jwks_cache
31
-
32
-
33
- async def get_current_user(
34
- credentials: Annotated[HTTPAuthorizationCredentials, Depends(bearer_scheme)],
35
- ) -> dict:
36
- token = credentials.credentials
37
- try:
38
- jwks = await _get_jwks()
39
- unverified_header = jwt.get_unverified_header(token)
40
- key = next(
41
- (k for k in jwks["keys"] if k["kid"] == unverified_header.get("kid")),
42
- None,
43
- )
44
- if key is None:
45
- raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Unknown signing key")
46
-
47
- payload = jwt.decode(
48
- token,
49
- key,
50
- algorithms=["RS256"],
51
- audience=settings.keycloak_client_id,
52
- options={"verify_exp": True},
53
- )
54
- return payload
55
- except JWTError as exc:
56
- raise HTTPException(
57
- status_code=status.HTTP_401_UNAUTHORIZED,
58
- detail=f"Invalid token: {exc}",
59
- ) from exc
60
-
61
-
62
- def user_id(user: Annotated[dict, Depends(get_current_user)]) -> str:
63
- return user["sub"]
64
-
65
-
66
- async def user_id_or_bot(request: Request, db: AsyncSession = Depends(get_db)) -> str:
67
- """Accept either JWT auth or X-User-Id header (when X-Bot-Token matches)."""
68
- s = get_settings()
69
- bot_token = request.headers.get("X-Bot-Token", "")
70
- if bot_token and s.telegram_bot_token and bot_token == s.telegram_bot_token:
71
- uid = request.headers.get("X-User-Id")
72
- if uid:
73
- return uid
74
- # Fall back to normal JWT auth — extract bearer token from request directly
75
- auth_header = request.headers.get("Authorization", "")
76
- if not auth_header.startswith("Bearer "):
77
- raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated")
78
- from fastapi.security import HTTPAuthorizationCredentials
79
- credentials = HTTPAuthorizationCredentials(scheme="Bearer", credentials=auth_header[7:])
80
- user = await get_current_user(credentials)
81
- return user["sub"]
@@ -1,66 +0,0 @@
1
- from pydantic_settings import BaseSettings
2
- from functools import lru_cache
3
-
4
-
5
- class Settings(BaseSettings):
6
- # App
7
- app_name: str = "Travel Chaos Organizer API"
8
- debug: bool = False
9
- upload_dir: str = "/data/uploads"
10
- app_url: str = "https://tco.app"
11
-
12
- # Database
13
- database_url: str = "postgresql+asyncpg://tco:tco@localhost:5432/tco"
14
-
15
- # Keycloak
16
- keycloak_url: str = "http://localhost:8080"
17
- keycloak_realm: str = "travel-chaos"
18
- keycloak_client_id: str = "tco-backend"
19
-
20
- # Ollama
21
- ollama_url: str = "http://localhost:11434"
22
- ollama_model: str = "llama3.2-vision"
23
- ollama_timeout: int = 120
24
-
25
- # Cachly Redis (optional) — caches Ollama parse results by content hash.
26
- # Set to your Cachly Redis connection string to enable deduplication.
27
- # Format: redis://:<password>@<host>:<port>/0 or rediss:// for TLS
28
- cachly_redis_url: str = ""
29
-
30
- # CORS
31
- cors_origins: str = "*" # Set to your domain in production: https://yourapp.com
32
-
33
- # Telegram notifier (optional)
34
- telegram_bot_token: str = ""
35
- telegram_chat_id: str = "" # default chat; per-app override below
36
- tco_telegram_chat_id: str = "" # if set, overrides telegram_chat_id for TCO events
37
-
38
- # Email (Resend)
39
- resend_api_key: str = ""
40
- resend_from: str = "noreply@tco.app"
41
-
42
- # Admin
43
- admin_user: str = "admin"
44
- admin_password: str = "changeme"
45
-
46
- # Sentry (optional)
47
- sentry_dsn: str = ""
48
- environment: str = "production"
49
-
50
- # Upload
51
- max_upload_bytes: int = 20 * 1024 * 1024 # 20 MB
52
-
53
- # Stripe
54
- stripe_secret_key: str = ""
55
- stripe_webhook_secret: str = ""
56
- stripe_pro_price_id: str = "price_YOUR_PRICE_ID"
57
- stripe_success_url: str = "tco://upgrade/success"
58
- stripe_cancel_url: str = "tco://upgrade/cancel"
59
-
60
- class Config:
61
- env_file = ".env"
62
-
63
-
64
- @lru_cache
65
- def get_settings() -> Settings:
66
- return Settings()
@@ -1,20 +0,0 @@
1
- from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
2
- from sqlalchemy.orm import DeclarativeBase
3
- from app.config import get_settings
4
-
5
- settings = get_settings()
6
-
7
- engine = create_async_engine(settings.database_url, echo=settings.debug)
8
- AsyncSessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
9
-
10
-
11
- class Base(DeclarativeBase):
12
- pass
13
-
14
-
15
- async def get_db() -> AsyncSession:
16
- async with AsyncSessionLocal() as session:
17
- try:
18
- yield session
19
- finally:
20
- await session.close()
@@ -1,71 +0,0 @@
1
- -- Travel Chaos Organizer — Initial Schema
2
-
3
- CREATE EXTENSION IF NOT EXISTS "pgcrypto";
4
-
5
- CREATE TABLE IF NOT EXISTS trips (
6
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7
- user_id TEXT NOT NULL,
8
- name TEXT NOT NULL,
9
- description TEXT,
10
- start_date DATE,
11
- end_date DATE,
12
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
13
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
14
- );
15
-
16
- CREATE INDEX idx_trips_user_id ON trips(user_id);
17
-
18
- CREATE TYPE item_type AS ENUM (
19
- 'flight', 'train', 'bus', 'hotel', 'rental_car',
20
- 'activity', 'transfer', 'document', 'other'
21
- );
22
-
23
- CREATE TABLE IF NOT EXISTS trip_items (
24
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
25
- trip_id UUID NOT NULL REFERENCES trips(id) ON DELETE CASCADE,
26
- user_id TEXT NOT NULL,
27
- type item_type NOT NULL DEFAULT 'other',
28
- title TEXT NOT NULL,
29
- raw_text TEXT,
30
- parsed_data JSONB,
31
- event_at TIMESTAMPTZ,
32
- event_end_at TIMESTAMPTZ,
33
- booking_ref TEXT,
34
- provider TEXT,
35
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
36
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
37
- );
38
-
39
- CREATE INDEX idx_trip_items_trip_id ON trip_items(trip_id);
40
- CREATE INDEX idx_trip_items_event_at ON trip_items(event_at);
41
- CREATE INDEX idx_trip_items_parsed_data ON trip_items USING gin(parsed_data);
42
-
43
- CREATE TABLE IF NOT EXISTS attachments (
44
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
45
- trip_item_id UUID REFERENCES trip_items(id) ON DELETE CASCADE,
46
- inbox_id UUID,
47
- user_id TEXT NOT NULL,
48
- file_path TEXT NOT NULL,
49
- file_name TEXT NOT NULL,
50
- mime_type TEXT NOT NULL,
51
- size_bytes BIGINT,
52
- created_at TIMESTAMPTZ NOT NULL DEFAULT now()
53
- );
54
-
55
- CREATE INDEX idx_attachments_trip_item_id ON attachments(trip_item_id);
56
-
57
- CREATE TYPE inbox_status AS ENUM ('pending', 'processed', 'rejected', 'assigned');
58
-
59
- CREATE TABLE IF NOT EXISTS chaos_inbox (
60
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
61
- user_id TEXT NOT NULL,
62
- raw_content TEXT,
63
- source TEXT,
64
- status inbox_status NOT NULL DEFAULT 'pending',
65
- parsed_data JSONB,
66
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
67
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
68
- );
69
-
70
- CREATE INDEX idx_chaos_inbox_user_id ON chaos_inbox(user_id);
71
- CREATE INDEX idx_chaos_inbox_status ON chaos_inbox(status);
@@ -1,31 +0,0 @@
1
- -- users table: freemium plan tracking. id = Keycloak sub.
2
- CREATE TABLE IF NOT EXISTS users (
3
- id TEXT PRIMARY KEY,
4
- email TEXT,
5
- plan TEXT NOT NULL DEFAULT 'free',
6
- plan_expires_at TIMESTAMPTZ,
7
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
8
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
9
- );
10
-
11
- -- events table: telemetry. user_id nullable for anonymous/server events.
12
- CREATE TABLE IF NOT EXISTS events (
13
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
14
- user_id TEXT,
15
- event_name TEXT NOT NULL,
16
- properties JSONB,
17
- platform TEXT,
18
- app_version TEXT,
19
- created_at TIMESTAMPTZ NOT NULL DEFAULT now()
20
- );
21
- CREATE INDEX idx_events_user_id ON events(user_id);
22
- CREATE INDEX idx_events_name ON events(event_name);
23
- CREATE INDEX idx_events_created ON events(created_at DESC);
24
-
25
- -- waitlist: email capture from landing page (no auth required)
26
- CREATE TABLE IF NOT EXISTS waitlist (
27
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
28
- email TEXT NOT NULL UNIQUE,
29
- source TEXT DEFAULT 'landing',
30
- created_at TIMESTAMPTZ NOT NULL DEFAULT now()
31
- );
@@ -1,4 +0,0 @@
1
- -- Add telegram_chat_id column to users table.
2
- -- This column was referenced in the application but missing from the initial schema.
3
- ALTER TABLE users ADD COLUMN IF NOT EXISTS telegram_chat_id TEXT;
4
- CREATE INDEX IF NOT EXISTS idx_users_telegram_chat_id ON users(telegram_chat_id) WHERE telegram_chat_id IS NOT NULL;
@@ -1,5 +0,0 @@
1
- -- Add stripe_customer_id to users table.
2
- -- Used by payments.py to link Stripe customer to user in webhook handlers.
3
- -- Missing column causes crash on every Stripe webhook (checkout, subscription cancel, renewal, payment failed).
4
- ALTER TABLE users ADD COLUMN IF NOT EXISTS stripe_customer_id TEXT;
5
- CREATE INDEX IF NOT EXISTS idx_users_stripe_customer_id ON users(stripe_customer_id) WHERE stripe_customer_id IS NOT NULL;
@@ -1,4 +0,0 @@
1
- from slowapi import Limiter
2
- from slowapi.util import get_remote_address
3
-
4
- limiter = Limiter(key_func=get_remote_address)