@cachly-dev/mcp-server 0.10.65 → 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 (269) 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 -113
  13. package/CHANGELOG.md +0 -653
  14. package/Dockerfile +0 -16
  15. package/LAUNCH_TEXTS.md +0 -182
  16. package/PROGRESS.md +0 -141
  17. package/STRATEGY.md +0 -228
  18. package/VISION_10X.md +0 -133
  19. package/apps/travel-chaos-organizer/.env.example +0 -49
  20. package/apps/travel-chaos-organizer/DEPLOY.md +0 -328
  21. package/apps/travel-chaos-organizer/Makefile +0 -57
  22. package/apps/travel-chaos-organizer/README.md +0 -159
  23. package/apps/travel-chaos-organizer/backend/.env.example +0 -10
  24. package/apps/travel-chaos-organizer/backend/Dockerfile +0 -25
  25. package/apps/travel-chaos-organizer/backend/alembic/env.py +0 -56
  26. package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +0 -24
  27. package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
  28. package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +0 -24
  29. package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +0 -24
  30. package/apps/travel-chaos-organizer/backend/alembic.ini +0 -39
  31. package/apps/travel-chaos-organizer/backend/app/__init__.py +0 -0
  32. package/apps/travel-chaos-organizer/backend/app/auth/__init__.py +0 -0
  33. package/apps/travel-chaos-organizer/backend/app/auth/keycloak.py +0 -81
  34. package/apps/travel-chaos-organizer/backend/app/config.py +0 -66
  35. package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
  36. package/apps/travel-chaos-organizer/backend/app/db/database.py +0 -20
  37. package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +0 -71
  38. package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +0 -31
  39. package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +0 -4
  40. package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +0 -5
  41. package/apps/travel-chaos-organizer/backend/app/limiter.py +0 -4
  42. package/apps/travel-chaos-organizer/backend/app/logging_config.py +0 -25
  43. package/apps/travel-chaos-organizer/backend/app/main.py +0 -77
  44. package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
  45. package/apps/travel-chaos-organizer/backend/app/models/schemas.py +0 -142
  46. package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
  47. package/apps/travel-chaos-organizer/backend/app/routers/admin.py +0 -237
  48. package/apps/travel-chaos-organizer/backend/app/routers/cache.py +0 -13
  49. package/apps/travel-chaos-organizer/backend/app/routers/events.py +0 -29
  50. package/apps/travel-chaos-organizer/backend/app/routers/export.py +0 -122
  51. package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +0 -122
  52. package/apps/travel-chaos-organizer/backend/app/routers/items.py +0 -130
  53. package/apps/travel-chaos-organizer/backend/app/routers/mail.py +0 -108
  54. package/apps/travel-chaos-organizer/backend/app/routers/parse.py +0 -303
  55. package/apps/travel-chaos-organizer/backend/app/routers/payments.py +0 -179
  56. package/apps/travel-chaos-organizer/backend/app/routers/trips.py +0 -134
  57. package/apps/travel-chaos-organizer/backend/app/routers/users.py +0 -169
  58. package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +0 -37
  59. package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
  60. package/apps/travel-chaos-organizer/backend/app/services/cache.py +0 -131
  61. package/apps/travel-chaos-organizer/backend/app/services/drip.py +0 -128
  62. package/apps/travel-chaos-organizer/backend/app/services/email.py +0 -61
  63. package/apps/travel-chaos-organizer/backend/app/services/errors.py +0 -44
  64. package/apps/travel-chaos-organizer/backend/app/services/notifier.py +0 -10
  65. package/apps/travel-chaos-organizer/backend/app/services/ollama.py +0 -101
  66. package/apps/travel-chaos-organizer/backend/app/services/parser.py +0 -22
  67. package/apps/travel-chaos-organizer/backend/app/services/quota.py +0 -85
  68. package/apps/travel-chaos-organizer/backend/app/services/sentry.py +0 -11
  69. package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +0 -35
  70. package/apps/travel-chaos-organizer/backend/pytest.ini +0 -4
  71. package/apps/travel-chaos-organizer/backend/requirements-dev.txt +0 -6
  72. package/apps/travel-chaos-organizer/backend/requirements.txt +0 -25
  73. package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
  74. package/apps/travel-chaos-organizer/backend/tests/conftest.py +0 -223
  75. package/apps/travel-chaos-organizer/backend/tests/test_admin.py +0 -99
  76. package/apps/travel-chaos-organizer/backend/tests/test_cache.py +0 -142
  77. package/apps/travel-chaos-organizer/backend/tests/test_drip.py +0 -32
  78. package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +0 -121
  79. package/apps/travel-chaos-organizer/backend/tests/test_export.py +0 -48
  80. package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +0 -107
  81. package/apps/travel-chaos-organizer/backend/tests/test_items.py +0 -138
  82. package/apps/travel-chaos-organizer/backend/tests/test_mail.py +0 -113
  83. package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +0 -145
  84. package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +0 -98
  85. package/apps/travel-chaos-organizer/backend/tests/test_parser.py +0 -72
  86. package/apps/travel-chaos-organizer/backend/tests/test_payments.py +0 -163
  87. package/apps/travel-chaos-organizer/backend/tests/test_quota.py +0 -46
  88. package/apps/travel-chaos-organizer/backend/tests/test_search.py +0 -67
  89. package/apps/travel-chaos-organizer/backend/tests/test_trips.py +0 -123
  90. package/apps/travel-chaos-organizer/backend/tests/test_users.py +0 -52
  91. package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
  92. package/apps/travel-chaos-organizer/caddy/Caddyfile +0 -27
  93. package/apps/travel-chaos-organizer/docker-compose.node1.yml +0 -31
  94. package/apps/travel-chaos-organizer/docker-compose.override.yml +0 -14
  95. package/apps/travel-chaos-organizer/docker-compose.yml +0 -128
  96. package/apps/travel-chaos-organizer/frontend/.env.example +0 -13
  97. package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +0 -80
  98. package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +0 -166
  99. package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +0 -130
  100. package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +0 -381
  101. package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +0 -346
  102. package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +0 -363
  103. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +0 -34
  104. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +0 -35
  105. package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +0 -91
  106. package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +0 -71
  107. package/apps/travel-chaos-organizer/frontend/app/auth.tsx +0 -29
  108. package/apps/travel-chaos-organizer/frontend/app/index.tsx +0 -16
  109. package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +0 -119
  110. package/apps/travel-chaos-organizer/frontend/app.config.ts +0 -54
  111. package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +0 -66
  112. package/apps/travel-chaos-organizer/frontend/assets/icon.svg +0 -79
  113. package/apps/travel-chaos-organizer/frontend/assets/splash.svg +0 -15
  114. package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +0 -102
  115. package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +0 -107
  116. package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +0 -109
  117. package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +0 -45
  118. package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +0 -19
  119. package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +0 -155
  120. package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +0 -55
  121. package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +0 -80
  122. package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +0 -39
  123. package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +0 -39
  124. package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +0 -70
  125. package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +0 -121
  126. package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +0 -70
  127. package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +0 -73
  128. package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +0 -130
  129. package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +0 -60
  130. package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +0 -42
  131. package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +0 -146
  132. package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +0 -70
  133. package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +0 -44
  134. package/apps/travel-chaos-organizer/frontend/eas.json +0 -22
  135. package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +0 -24
  136. package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +0 -60
  137. package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +0 -112
  138. package/apps/travel-chaos-organizer/frontend/lib/api.ts +0 -223
  139. package/apps/travel-chaos-organizer/frontend/lib/auth.ts +0 -93
  140. package/apps/travel-chaos-organizer/frontend/lib/db.ts +0 -86
  141. package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +0 -54
  142. package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +0 -13
  143. package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +0 -112
  144. package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +0 -145
  145. package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +0 -43
  146. package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +0 -28
  147. package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +0 -44
  148. package/apps/travel-chaos-organizer/frontend/package-lock.json +0 -13221
  149. package/apps/travel-chaos-organizer/frontend/package.json +0 -44
  150. package/apps/travel-chaos-organizer/frontend/tsconfig.json +0 -23
  151. package/apps/travel-chaos-organizer/keycloak/realm-export.json +0 -59
  152. package/apps/travel-chaos-organizer/landing/index.html +0 -773
  153. package/apps/travel-chaos-organizer/scripts/backup.sh +0 -14
  154. package/apps/travel-chaos-organizer/scripts/configure-env.sh +0 -82
  155. package/apps/travel-chaos-organizer/scripts/deploy.sh +0 -54
  156. package/apps/travel-chaos-organizer/scripts/health-check.sh +0 -36
  157. package/apps/travel-chaos-organizer/scripts/migrate.sh +0 -7
  158. package/apps/travel-chaos-organizer/scripts/server-setup.sh +0 -85
  159. package/apps/travel-chaos-organizer/scripts/smoke-test.sh +0 -29
  160. package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +0 -71
  161. package/apps/travel-chaos-organizer/telegram-bot/.env.example +0 -3
  162. package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +0 -6
  163. package/apps/travel-chaos-organizer/telegram-bot/bot.py +0 -504
  164. package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +0 -3
  165. package/dist/src/__tests__/auth.test.d.ts +0 -1
  166. package/dist/src/__tests__/auth.test.js +0 -107
  167. package/dist/src/__tests__/auth.test.js.map +0 -1
  168. package/dist/src/__tests__/brain-flow.test.d.ts +0 -12
  169. package/dist/src/__tests__/brain-flow.test.js +0 -1241
  170. package/dist/src/__tests__/brain-flow.test.js.map +0 -1
  171. package/dist/src/__tests__/confidence.test.d.ts +0 -13
  172. package/dist/src/__tests__/confidence.test.js +0 -233
  173. package/dist/src/__tests__/confidence.test.js.map +0 -1
  174. package/dist/src/__tests__/e2e/api-auth.test.d.ts +0 -7
  175. package/dist/src/__tests__/e2e/api-auth.test.js +0 -162
  176. package/dist/src/__tests__/e2e/api-auth.test.js.map +0 -1
  177. package/dist/src/__tests__/e2e/api-health.test.d.ts +0 -7
  178. package/dist/src/__tests__/e2e/api-health.test.js +0 -95
  179. package/dist/src/__tests__/e2e/api-health.test.js.map +0 -1
  180. package/dist/src/__tests__/e2e/cli.test.d.ts +0 -10
  181. package/dist/src/__tests__/e2e/cli.test.js +0 -204
  182. package/dist/src/__tests__/e2e/cli.test.js.map +0 -1
  183. package/dist/src/__tests__/e2e/config.d.ts +0 -35
  184. package/dist/src/__tests__/e2e/config.js +0 -53
  185. package/dist/src/__tests__/e2e/config.js.map +0 -1
  186. package/dist/src/__tests__/e2e/funnel.test.d.ts +0 -13
  187. package/dist/src/__tests__/e2e/funnel.test.js +0 -90
  188. package/dist/src/__tests__/e2e/funnel.test.js.map +0 -1
  189. package/dist/src/__tests__/e2e/mcp-tools.test.d.ts +0 -7
  190. package/dist/src/__tests__/e2e/mcp-tools.test.js +0 -129
  191. package/dist/src/__tests__/e2e/mcp-tools.test.js.map +0 -1
  192. package/dist/src/__tests__/e2e/provisioning.test.d.ts +0 -15
  193. package/dist/src/__tests__/e2e/provisioning.test.js +0 -123
  194. package/dist/src/__tests__/e2e/provisioning.test.js.map +0 -1
  195. package/dist/src/__tests__/handlers-unit.test.d.ts +0 -12
  196. package/dist/src/__tests__/handlers-unit.test.js +0 -505
  197. package/dist/src/__tests__/handlers-unit.test.js.map +0 -1
  198. package/dist/src/__tests__/namespace.test.d.ts +0 -1
  199. package/dist/src/__tests__/namespace.test.js +0 -114
  200. package/dist/src/__tests__/namespace.test.js.map +0 -1
  201. package/dist/src/__tests__/rerank.test.d.ts +0 -1
  202. package/dist/src/__tests__/rerank.test.js +0 -125
  203. package/dist/src/__tests__/rerank.test.js.map +0 -1
  204. package/dist/src/__tests__/utils.test.d.ts +0 -1
  205. package/dist/src/__tests__/utils.test.js +0 -83
  206. package/dist/src/__tests__/utils.test.js.map +0 -1
  207. package/dist/src/bench/cachly-bench.d.ts +0 -39
  208. package/dist/src/bench/cachly-bench.js +0 -223
  209. package/dist/src/bench/cachly-bench.js.map +0 -1
  210. package/dist/src/bench/fixtures.d.ts +0 -37
  211. package/dist/src/bench/fixtures.js +0 -225
  212. package/dist/src/bench/fixtures.js.map +0 -1
  213. package/dist/src/search.test.d.ts +0 -1
  214. package/dist/src/search.test.js +0 -713
  215. package/dist/src/search.test.js.map +0 -1
  216. package/eslint.config.js +0 -16
  217. package/glama.json +0 -36
  218. package/llms.txt +0 -155
  219. package/packages/telegram-notify/SPLIT_PLAN.md +0 -106
  220. package/packages/telegram-notify/client.ts +0 -88
  221. package/packages/telegram-notify/emojis.json +0 -22
  222. package/packages/telegram-notify/pyproject.toml +0 -17
  223. package/packages/telegram-notify/telegram_notify/__init__.py +0 -3
  224. package/packages/telegram-notify/telegram_notify/client.py +0 -87
  225. package/packages/telegram-notify/telegram_notify/emojis.json +0 -22
  226. package/scripts/e2e-run.sh +0 -160
  227. package/scripts/generate-icons.js +0 -28
  228. package/smithery.yaml +0 -45
  229. package/src/__tests__/auth.test.ts +0 -147
  230. package/src/__tests__/brain-flow.test.ts +0 -1472
  231. package/src/__tests__/confidence.test.ts +0 -285
  232. package/src/__tests__/e2e/api-auth.test.ts +0 -182
  233. package/src/__tests__/e2e/api-health.test.ts +0 -103
  234. package/src/__tests__/e2e/cli.test.ts +0 -228
  235. package/src/__tests__/e2e/config.ts +0 -53
  236. package/src/__tests__/e2e/funnel.test.ts +0 -99
  237. package/src/__tests__/e2e/mcp-tools.test.ts +0 -191
  238. package/src/__tests__/e2e/provisioning.test.ts +0 -128
  239. package/src/__tests__/handlers-unit.test.ts +0 -677
  240. package/src/__tests__/namespace.test.ts +0 -126
  241. package/src/__tests__/rerank.test.ts +0 -141
  242. package/src/__tests__/utils.test.ts +0 -81
  243. package/src/auth.ts +0 -46
  244. package/src/bench/cachly-bench.ts +0 -263
  245. package/src/bench/fixtures.ts +0 -256
  246. package/src/ckg.ts +0 -103
  247. package/src/confidence.ts +0 -38
  248. package/src/embeddings.ts +0 -217
  249. package/src/handlers/advanced.ts +0 -647
  250. package/src/handlers/brain.ts +0 -2622
  251. package/src/handlers/cache.ts +0 -633
  252. package/src/handlers/context.ts +0 -222
  253. package/src/handlers/fedbrain.ts +0 -1232
  254. package/src/handlers/instances.ts +0 -180
  255. package/src/handlers/roadmap.ts +0 -201
  256. package/src/handlers/syndicate.ts +0 -460
  257. package/src/handlers/tco.ts +0 -345
  258. package/src/handlers/team.ts +0 -1249
  259. package/src/index.ts +0 -2815
  260. package/src/namespace.ts +0 -128
  261. package/src/notifier.ts +0 -5
  262. package/src/rerank.ts +0 -148
  263. package/src/search.test.ts +0 -848
  264. package/src/search.ts +0 -1781
  265. package/src/tools.ts +0 -2056
  266. package/src/utils.ts +0 -90
  267. package/test-features.cjs +0 -23
  268. package/tsconfig.json +0 -16
  269. 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)