@cachly-dev/mcp-server 0.10.65 → 0.10.67

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