@cachly-dev/mcp-server 0.10.49 → 0.10.56

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 (310) hide show
  1. package/.github/workflows/publish.yml +2 -2
  2. package/README.md +33 -5
  3. package/dist/__tests__/auth.test.js.map +1 -0
  4. package/dist/{src/__tests__ → __tests__}/brain-flow.test.js +0 -141
  5. package/dist/__tests__/brain-flow.test.js.map +1 -0
  6. package/dist/__tests__/brain-predict-failures.test.d.ts +17 -0
  7. package/dist/__tests__/brain-predict-failures.test.js +339 -0
  8. package/dist/__tests__/brain-predict-failures.test.js.map +1 -0
  9. package/dist/__tests__/confidence.test.js.map +1 -0
  10. package/dist/__tests__/e2e/api-auth.test.js.map +1 -0
  11. package/dist/__tests__/e2e/api-health.test.js.map +1 -0
  12. package/dist/__tests__/e2e/cli.test.js.map +1 -0
  13. package/dist/__tests__/e2e/config.js.map +1 -0
  14. package/dist/__tests__/e2e/funnel.test.js.map +1 -0
  15. package/dist/__tests__/e2e/mcp-tools.test.js.map +1 -0
  16. package/dist/__tests__/e2e/provisioning.test.js.map +1 -0
  17. package/dist/{src/__tests__ → __tests__}/handlers-unit.test.js +2 -0
  18. package/dist/__tests__/handlers-unit.test.js.map +1 -0
  19. package/dist/__tests__/namespace.test.js.map +1 -0
  20. package/dist/auth.js.map +1 -0
  21. package/dist/ckg.js.map +1 -0
  22. package/dist/confidence.js.map +1 -0
  23. package/dist/embeddings.js.map +1 -0
  24. package/dist/handlers/advanced.js.map +1 -0
  25. package/dist/{src/handlers → handlers}/brain.js +141 -135
  26. package/dist/handlers/brain.js.map +1 -0
  27. package/dist/handlers/cache.js.map +1 -0
  28. package/dist/{src/handlers → handlers}/context.js +4 -9
  29. package/dist/handlers/context.js.map +1 -0
  30. package/dist/{src/handlers → handlers}/fedbrain.d.ts +0 -6
  31. package/dist/{src/handlers → handlers}/fedbrain.js +7 -19
  32. package/dist/handlers/fedbrain.js.map +1 -0
  33. package/dist/handlers/instances.js.map +1 -0
  34. package/dist/{src/handlers → handlers}/roadmap.js +3 -7
  35. package/dist/handlers/roadmap.js.map +1 -0
  36. package/dist/handlers/syndicate.js.map +1 -0
  37. package/dist/{src/handlers → handlers}/team.js +3 -1
  38. package/dist/handlers/team.js.map +1 -0
  39. package/dist/{src/index.js → index.js} +428 -206
  40. package/dist/index.js.map +1 -0
  41. package/dist/namespace.js.map +1 -0
  42. package/dist/search.js.map +1 -0
  43. package/dist/search.test.js.map +1 -0
  44. package/dist/{src/tools.d.ts → tools.d.ts} +0 -196
  45. package/dist/{src/tools.js → tools.js} +0 -178
  46. package/dist/tools.js.map +1 -0
  47. package/dist/utils.js.map +1 -0
  48. package/package.json +3 -3
  49. package/smithery.yaml +16 -27
  50. package/src/__tests__/brain-flow.test.ts +0 -174
  51. package/src/__tests__/brain-predict-failures.test.ts +430 -0
  52. package/src/__tests__/handlers-unit.test.ts +2 -1
  53. package/src/handlers/brain.ts +142 -142
  54. package/src/handlers/context.ts +4 -9
  55. package/src/handlers/fedbrain.ts +7 -21
  56. package/src/handlers/roadmap.ts +3 -7
  57. package/src/handlers/team.ts +3 -1
  58. package/src/index.ts +415 -221
  59. package/src/tools.ts +0 -191
  60. package/tsconfig.json +3 -2
  61. package/.github/workflows/eas-build-android.yml +0 -58
  62. package/.github/workflows/eas-update.yml +0 -55
  63. package/STRATEGY.md +0 -209
  64. package/apps/travel-chaos-organizer/.env.example +0 -49
  65. package/apps/travel-chaos-organizer/DEPLOY.md +0 -328
  66. package/apps/travel-chaos-organizer/Makefile +0 -57
  67. package/apps/travel-chaos-organizer/README.md +0 -159
  68. package/apps/travel-chaos-organizer/backend/.env.example +0 -10
  69. package/apps/travel-chaos-organizer/backend/Dockerfile +0 -25
  70. package/apps/travel-chaos-organizer/backend/alembic/env.py +0 -56
  71. package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +0 -24
  72. package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
  73. package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +0 -24
  74. package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +0 -24
  75. package/apps/travel-chaos-organizer/backend/alembic.ini +0 -39
  76. package/apps/travel-chaos-organizer/backend/app/__init__.py +0 -0
  77. package/apps/travel-chaos-organizer/backend/app/auth/__init__.py +0 -0
  78. package/apps/travel-chaos-organizer/backend/app/auth/keycloak.py +0 -81
  79. package/apps/travel-chaos-organizer/backend/app/config.py +0 -66
  80. package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
  81. package/apps/travel-chaos-organizer/backend/app/db/database.py +0 -20
  82. package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +0 -71
  83. package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +0 -31
  84. package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +0 -4
  85. package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +0 -5
  86. package/apps/travel-chaos-organizer/backend/app/limiter.py +0 -4
  87. package/apps/travel-chaos-organizer/backend/app/logging_config.py +0 -25
  88. package/apps/travel-chaos-organizer/backend/app/main.py +0 -77
  89. package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
  90. package/apps/travel-chaos-organizer/backend/app/models/schemas.py +0 -142
  91. package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
  92. package/apps/travel-chaos-organizer/backend/app/routers/admin.py +0 -237
  93. package/apps/travel-chaos-organizer/backend/app/routers/cache.py +0 -13
  94. package/apps/travel-chaos-organizer/backend/app/routers/events.py +0 -29
  95. package/apps/travel-chaos-organizer/backend/app/routers/export.py +0 -122
  96. package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +0 -122
  97. package/apps/travel-chaos-organizer/backend/app/routers/items.py +0 -130
  98. package/apps/travel-chaos-organizer/backend/app/routers/mail.py +0 -108
  99. package/apps/travel-chaos-organizer/backend/app/routers/parse.py +0 -303
  100. package/apps/travel-chaos-organizer/backend/app/routers/payments.py +0 -179
  101. package/apps/travel-chaos-organizer/backend/app/routers/trips.py +0 -134
  102. package/apps/travel-chaos-organizer/backend/app/routers/users.py +0 -169
  103. package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +0 -37
  104. package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
  105. package/apps/travel-chaos-organizer/backend/app/services/cache.py +0 -131
  106. package/apps/travel-chaos-organizer/backend/app/services/drip.py +0 -128
  107. package/apps/travel-chaos-organizer/backend/app/services/email.py +0 -61
  108. package/apps/travel-chaos-organizer/backend/app/services/errors.py +0 -44
  109. package/apps/travel-chaos-organizer/backend/app/services/notifier.py +0 -10
  110. package/apps/travel-chaos-organizer/backend/app/services/ollama.py +0 -101
  111. package/apps/travel-chaos-organizer/backend/app/services/parser.py +0 -22
  112. package/apps/travel-chaos-organizer/backend/app/services/quota.py +0 -85
  113. package/apps/travel-chaos-organizer/backend/app/services/sentry.py +0 -11
  114. package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +0 -35
  115. package/apps/travel-chaos-organizer/backend/pytest.ini +0 -4
  116. package/apps/travel-chaos-organizer/backend/requirements-dev.txt +0 -6
  117. package/apps/travel-chaos-organizer/backend/requirements.txt +0 -25
  118. package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
  119. package/apps/travel-chaos-organizer/backend/tests/conftest.py +0 -223
  120. package/apps/travel-chaos-organizer/backend/tests/test_admin.py +0 -99
  121. package/apps/travel-chaos-organizer/backend/tests/test_cache.py +0 -142
  122. package/apps/travel-chaos-organizer/backend/tests/test_drip.py +0 -32
  123. package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +0 -121
  124. package/apps/travel-chaos-organizer/backend/tests/test_export.py +0 -48
  125. package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +0 -107
  126. package/apps/travel-chaos-organizer/backend/tests/test_items.py +0 -138
  127. package/apps/travel-chaos-organizer/backend/tests/test_mail.py +0 -113
  128. package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +0 -145
  129. package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +0 -98
  130. package/apps/travel-chaos-organizer/backend/tests/test_parser.py +0 -72
  131. package/apps/travel-chaos-organizer/backend/tests/test_payments.py +0 -163
  132. package/apps/travel-chaos-organizer/backend/tests/test_quota.py +0 -46
  133. package/apps/travel-chaos-organizer/backend/tests/test_search.py +0 -67
  134. package/apps/travel-chaos-organizer/backend/tests/test_trips.py +0 -123
  135. package/apps/travel-chaos-organizer/backend/tests/test_users.py +0 -52
  136. package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
  137. package/apps/travel-chaos-organizer/caddy/Caddyfile +0 -27
  138. package/apps/travel-chaos-organizer/docker-compose.node1.yml +0 -31
  139. package/apps/travel-chaos-organizer/docker-compose.override.yml +0 -14
  140. package/apps/travel-chaos-organizer/docker-compose.yml +0 -128
  141. package/apps/travel-chaos-organizer/frontend/.env.example +0 -13
  142. package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +0 -80
  143. package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +0 -166
  144. package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +0 -130
  145. package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +0 -381
  146. package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +0 -346
  147. package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +0 -363
  148. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +0 -34
  149. package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +0 -35
  150. package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +0 -91
  151. package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +0 -71
  152. package/apps/travel-chaos-organizer/frontend/app/auth.tsx +0 -29
  153. package/apps/travel-chaos-organizer/frontend/app/index.tsx +0 -16
  154. package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +0 -119
  155. package/apps/travel-chaos-organizer/frontend/app.config.ts +0 -54
  156. package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +0 -66
  157. package/apps/travel-chaos-organizer/frontend/assets/icon.svg +0 -79
  158. package/apps/travel-chaos-organizer/frontend/assets/splash.svg +0 -15
  159. package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +0 -102
  160. package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +0 -107
  161. package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +0 -109
  162. package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +0 -45
  163. package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +0 -19
  164. package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +0 -155
  165. package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +0 -55
  166. package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +0 -80
  167. package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +0 -39
  168. package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +0 -39
  169. package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +0 -70
  170. package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +0 -121
  171. package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +0 -70
  172. package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +0 -73
  173. package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +0 -130
  174. package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +0 -60
  175. package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +0 -42
  176. package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +0 -146
  177. package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +0 -70
  178. package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +0 -44
  179. package/apps/travel-chaos-organizer/frontend/eas.json +0 -22
  180. package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +0 -24
  181. package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +0 -60
  182. package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +0 -112
  183. package/apps/travel-chaos-organizer/frontend/lib/api.ts +0 -223
  184. package/apps/travel-chaos-organizer/frontend/lib/auth.ts +0 -93
  185. package/apps/travel-chaos-organizer/frontend/lib/db.ts +0 -86
  186. package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +0 -54
  187. package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +0 -13
  188. package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +0 -112
  189. package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +0 -145
  190. package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +0 -43
  191. package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +0 -28
  192. package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +0 -44
  193. package/apps/travel-chaos-organizer/frontend/package-lock.json +0 -13037
  194. package/apps/travel-chaos-organizer/frontend/package.json +0 -44
  195. package/apps/travel-chaos-organizer/frontend/tsconfig.json +0 -23
  196. package/apps/travel-chaos-organizer/keycloak/realm-export.json +0 -59
  197. package/apps/travel-chaos-organizer/landing/index.html +0 -773
  198. package/apps/travel-chaos-organizer/scripts/backup.sh +0 -14
  199. package/apps/travel-chaos-organizer/scripts/configure-env.sh +0 -82
  200. package/apps/travel-chaos-organizer/scripts/deploy.sh +0 -54
  201. package/apps/travel-chaos-organizer/scripts/health-check.sh +0 -36
  202. package/apps/travel-chaos-organizer/scripts/migrate.sh +0 -7
  203. package/apps/travel-chaos-organizer/scripts/server-setup.sh +0 -85
  204. package/apps/travel-chaos-organizer/scripts/smoke-test.sh +0 -29
  205. package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +0 -71
  206. package/apps/travel-chaos-organizer/telegram-bot/.env.example +0 -3
  207. package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +0 -6
  208. package/apps/travel-chaos-organizer/telegram-bot/bot.py +0 -504
  209. package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +0 -3
  210. package/dist/packages/telegram-notify/client.d.ts +0 -19
  211. package/dist/packages/telegram-notify/client.js +0 -75
  212. package/dist/packages/telegram-notify/client.js.map +0 -1
  213. package/dist/src/__tests__/auth.test.js.map +0 -1
  214. package/dist/src/__tests__/brain-flow.test.js.map +0 -1
  215. package/dist/src/__tests__/confidence.test.js.map +0 -1
  216. package/dist/src/__tests__/e2e/api-auth.test.js.map +0 -1
  217. package/dist/src/__tests__/e2e/api-health.test.js.map +0 -1
  218. package/dist/src/__tests__/e2e/cli.test.js.map +0 -1
  219. package/dist/src/__tests__/e2e/config.js.map +0 -1
  220. package/dist/src/__tests__/e2e/funnel.test.js.map +0 -1
  221. package/dist/src/__tests__/e2e/mcp-tools.test.js.map +0 -1
  222. package/dist/src/__tests__/e2e/provisioning.test.js.map +0 -1
  223. package/dist/src/__tests__/handlers-unit.test.js.map +0 -1
  224. package/dist/src/__tests__/namespace.test.js.map +0 -1
  225. package/dist/src/auth.js.map +0 -1
  226. package/dist/src/ckg.js.map +0 -1
  227. package/dist/src/confidence.js.map +0 -1
  228. package/dist/src/embeddings.js.map +0 -1
  229. package/dist/src/handlers/advanced.js.map +0 -1
  230. package/dist/src/handlers/brain.js.map +0 -1
  231. package/dist/src/handlers/cache.js.map +0 -1
  232. package/dist/src/handlers/context.js.map +0 -1
  233. package/dist/src/handlers/fedbrain.js.map +0 -1
  234. package/dist/src/handlers/instances.js.map +0 -1
  235. package/dist/src/handlers/roadmap.js.map +0 -1
  236. package/dist/src/handlers/syndicate.js.map +0 -1
  237. package/dist/src/handlers/tco.d.ts +0 -16
  238. package/dist/src/handlers/tco.js +0 -303
  239. package/dist/src/handlers/tco.js.map +0 -1
  240. package/dist/src/handlers/team.js.map +0 -1
  241. package/dist/src/index.js.map +0 -1
  242. package/dist/src/namespace.js.map +0 -1
  243. package/dist/src/notifier.d.ts +0 -5
  244. package/dist/src/notifier.js +0 -6
  245. package/dist/src/notifier.js.map +0 -1
  246. package/dist/src/search.js.map +0 -1
  247. package/dist/src/search.test.js.map +0 -1
  248. package/dist/src/tools.js.map +0 -1
  249. package/dist/src/utils.js.map +0 -1
  250. package/packages/telegram-notify/SPLIT_PLAN.md +0 -106
  251. package/packages/telegram-notify/client.ts +0 -88
  252. package/packages/telegram-notify/emojis.json +0 -22
  253. package/packages/telegram-notify/pyproject.toml +0 -17
  254. package/packages/telegram-notify/telegram_notify/__init__.py +0 -3
  255. package/packages/telegram-notify/telegram_notify/client.py +0 -87
  256. package/packages/telegram-notify/telegram_notify/emojis.json +0 -22
  257. package/scripts/generate-icons.js +0 -28
  258. package/src/handlers/tco.ts +0 -347
  259. package/src/notifier.ts +0 -5
  260. /package/dist/{src/__tests__ → __tests__}/auth.test.d.ts +0 -0
  261. /package/dist/{src/__tests__ → __tests__}/auth.test.js +0 -0
  262. /package/dist/{src/__tests__ → __tests__}/brain-flow.test.d.ts +0 -0
  263. /package/dist/{src/__tests__ → __tests__}/confidence.test.d.ts +0 -0
  264. /package/dist/{src/__tests__ → __tests__}/confidence.test.js +0 -0
  265. /package/dist/{src/__tests__ → __tests__}/e2e/api-auth.test.d.ts +0 -0
  266. /package/dist/{src/__tests__ → __tests__}/e2e/api-auth.test.js +0 -0
  267. /package/dist/{src/__tests__ → __tests__}/e2e/api-health.test.d.ts +0 -0
  268. /package/dist/{src/__tests__ → __tests__}/e2e/api-health.test.js +0 -0
  269. /package/dist/{src/__tests__ → __tests__}/e2e/cli.test.d.ts +0 -0
  270. /package/dist/{src/__tests__ → __tests__}/e2e/cli.test.js +0 -0
  271. /package/dist/{src/__tests__ → __tests__}/e2e/config.d.ts +0 -0
  272. /package/dist/{src/__tests__ → __tests__}/e2e/config.js +0 -0
  273. /package/dist/{src/__tests__ → __tests__}/e2e/funnel.test.d.ts +0 -0
  274. /package/dist/{src/__tests__ → __tests__}/e2e/funnel.test.js +0 -0
  275. /package/dist/{src/__tests__ → __tests__}/e2e/mcp-tools.test.d.ts +0 -0
  276. /package/dist/{src/__tests__ → __tests__}/e2e/mcp-tools.test.js +0 -0
  277. /package/dist/{src/__tests__ → __tests__}/e2e/provisioning.test.d.ts +0 -0
  278. /package/dist/{src/__tests__ → __tests__}/e2e/provisioning.test.js +0 -0
  279. /package/dist/{src/__tests__ → __tests__}/handlers-unit.test.d.ts +0 -0
  280. /package/dist/{src/__tests__ → __tests__}/namespace.test.d.ts +0 -0
  281. /package/dist/{src/__tests__ → __tests__}/namespace.test.js +0 -0
  282. /package/dist/{src/auth.d.ts → auth.d.ts} +0 -0
  283. /package/dist/{src/auth.js → auth.js} +0 -0
  284. /package/dist/{src/ckg.d.ts → ckg.d.ts} +0 -0
  285. /package/dist/{src/ckg.js → ckg.js} +0 -0
  286. /package/dist/{src/confidence.d.ts → confidence.d.ts} +0 -0
  287. /package/dist/{src/confidence.js → confidence.js} +0 -0
  288. /package/dist/{src/embeddings.d.ts → embeddings.d.ts} +0 -0
  289. /package/dist/{src/embeddings.js → embeddings.js} +0 -0
  290. /package/dist/{src/handlers → handlers}/advanced.d.ts +0 -0
  291. /package/dist/{src/handlers → handlers}/advanced.js +0 -0
  292. /package/dist/{src/handlers → handlers}/brain.d.ts +0 -0
  293. /package/dist/{src/handlers → handlers}/cache.d.ts +0 -0
  294. /package/dist/{src/handlers → handlers}/cache.js +0 -0
  295. /package/dist/{src/handlers → handlers}/context.d.ts +0 -0
  296. /package/dist/{src/handlers → handlers}/instances.d.ts +0 -0
  297. /package/dist/{src/handlers → handlers}/instances.js +0 -0
  298. /package/dist/{src/handlers → handlers}/roadmap.d.ts +0 -0
  299. /package/dist/{src/handlers → handlers}/syndicate.d.ts +0 -0
  300. /package/dist/{src/handlers → handlers}/syndicate.js +0 -0
  301. /package/dist/{src/handlers → handlers}/team.d.ts +0 -0
  302. /package/dist/{src/index.d.ts → index.d.ts} +0 -0
  303. /package/dist/{src/namespace.d.ts → namespace.d.ts} +0 -0
  304. /package/dist/{src/namespace.js → namespace.js} +0 -0
  305. /package/dist/{src/search.d.ts → search.d.ts} +0 -0
  306. /package/dist/{src/search.js → search.js} +0 -0
  307. /package/dist/{src/search.test.d.ts → search.test.d.ts} +0 -0
  308. /package/dist/{src/search.test.js → search.test.js} +0 -0
  309. /package/dist/{src/utils.d.ts → utils.d.ts} +0 -0
  310. /package/dist/{src/utils.js → utils.js} +0 -0
@@ -6,24 +6,68 @@ import { ckgSlug, extractProblemConcept, ckgUpsertNode, ckgUpdateEdge } from '..
6
6
  import { safeJsonParse } from '../utils.js';
7
7
  import type { CKGEdge, CKGNode } from '../ckg.js';
8
8
  import { keywordSearch, tokenize, splitMultiQuery, levenshtein,
9
- ZERO_RESULTS_LOG, zeroResultsTotal, indexVocab as _indexVocab } from '../search.js';
9
+ indexVocab as _indexVocab } from '../search.js';
10
10
  import type { KeywordMatch } from '../search.js';
11
- import { computeEmbedding, hasEmbedProvider, embedProviderHint, EMBED_PROVIDER } from '../embeddings.js';
12
- import { detectNamespace } from '../namespace.js';
11
+ import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
13
12
 
14
13
  // ── Changelog (shown once per version in session_start) ──────────────────────
15
- const MCP_VERSION = '0.10.49';
14
+ const MCP_VERSION = '0.10.56';
16
15
  const WHATS_NEW: Record<string, string[]> = {
17
- '0.10.49': [
18
- `🆕 **What's new in v${MCP_VERSION}:**`,
19
- ` ✅ \`brain_from_git\` — auto-seed your Brain from git history in seconds`,
20
- ` ✅ \`brain_predict_failures\` — predict CI/build failures before they happen`,
21
- ` ✅ \`smart_recall\` — semantic + keyword hybrid recall, now in every CLAUDE.md`,
22
- ` ✅ VS Code extension — Brain status bar, ambient learning, CodeLens hints`,
23
- ` ✅ Team Brain — share lessons across your whole engineering team`,
24
- ` ✅ 89 MCP tools — roadmap, A/B tests, cache, index, predict, syndicate`,
25
- ` 🔧 Stability — auto-expiring memory keys, longer provisioning wait, robust recall`,
26
- ` 💡 Run \`brain_from_git\` to seed your Brain from existing commits instantly`,
16
+ '0.10.56': [
17
+ `🆕 **What's new in cachly MCP v0.10.56:**`,
18
+ ` 🎉 session_start now shows a "🎉 Your Brain bootstrapped from X commits" wow moment on second session`,
19
+ ` 📣 Setup flow now surfaces a teammate invite nudge — helps you loop in your team`,
20
+ ` 📝 Smithery listing rewritten: clearer value prop, better first-impression`,
21
+ ],
22
+ '0.10.55': [
23
+ `🆕 **What's new in cachly MCP v0.10.55:**`,
24
+ ` ⚡ UX: API failure now shows a clear error instead of silently blocking for 30s`,
25
+ ` ⚡ UX: provisioning wait reduced from 25s → 8s (Brain is usually ready sooner)`,
26
+ ` 🔧 VS Code: setup spinner is now cancellable — dismiss and MCP auto-connects later`,
27
+ ` 🧠 VS Code: Brain Health panel shows offline-queued lessons with pending sync count`,
28
+ ],
29
+ '0.10.54': [
30
+ `🆕 **What's new in cachly MCP v${MCP_VERSION}:**`,
31
+ ` 👀 Perf: first tool call no longer blocked by auto-session (was freezing for 30-120s on large repos)`,
32
+ ` 👀 Perf: git history bootstrap runs in background — session_start responds instantly`,
33
+ ` 🐞 Fixed: VS Code lessons now include author attribution (broken since launch)`,
34
+ ],
35
+ '0.10.53': [
36
+ `🆕 **What's new in cachly MCP v${MCP_VERSION}:**`,
37
+ ` 🐛 Fixed: Brain bootstrap summary now visible in session_start (was silently discarded)`,
38
+ ` 🐛 Fixed: team lessons now indexed correctly (\`ts\` field was stored as \`timestamp\`)`,
39
+ ` ✨ New: proactive follow-up hints after \`learn_from_attempts\` (CKG co-occurrence patterns)`,
40
+ ` ✨ New: author name attribution for VS Code lessons (set \`cachly.authorName\` in VS Code settings)`,
41
+ ],
42
+ '0.10.52': [
43
+ `🆕 **What's new in cachly MCP v0.10.52:**`,
44
+ ` 🚀 Zero-click setup: Brain activates automatically on first call (no auth prompt needed)`,
45
+ ` 🐛 Fixed: all Brain connections now use decrypted passwords (resolves AUTH errors for all users)`,
46
+ ],
47
+ '0.10.50': [
48
+ `🆕 **What's new in cachly MCP v0.10.50:**`,
49
+ ` 🐛 Fixed: Brain connection now works out of the box (was failing with AUTH error)`,
50
+ ` 🐛 Fixed: TLS defaults to off for free-tier instances (no more TLS handshake failure)`,
51
+ ` ✅ \`get_api_status\` correctly shows API key type instead of "invalid JWT format"`,
52
+ ],
53
+ '0.10.46': [
54
+ `🆕 **What's new in v0.10.46:**`,
55
+ ` ✅ \`brain_from_git\` — auto-learns from your full git history on setup`,
56
+ ` ✅ \`smart_recall\` — semantic + keyword hybrid search, 3× more relevant results`,
57
+ ` ✅ VS Code Extension — Brain persists across all projects, zero config`,
58
+ ` ✅ Device-flow auth — zero-config login, no JWT needed in editor config`,
59
+ ` ✅ Auto-provision — Brain instance created automatically after first login`,
60
+ ` ✅ JWT now persisted to ~/.claude/mcp.json — survives editor restarts`,
61
+ ` ✅ Confidence scoring — every recalled fact shows staleness + reliability`,
62
+ ` ✅ CKG (Causal Knowledge Graph) — root-cause chains between bugs + fixes`,
63
+ ],
64
+ '0.10.0': [
65
+ `🆕 **What's new in v0.10.0:**`,
66
+ ` ✅ Zero-friction setup — auto-provisions your Brain, no manual config needed`,
67
+ ` ✅ 10× faster briefings — batch Redis fetches replace per-key loops`,
68
+ ` ✅ Crash-proof data reads — corrupted cache entries no longer break tools`,
69
+ ` ✅ \`session_end\` warns when called without an active session`,
70
+ ` ✅ \`get_api_status\` now shows live Redis ping + all instance statuses`,
27
71
  ],
28
72
  };
29
73
 
@@ -186,7 +230,7 @@ export async function handleBrainTool(
186
230
  const existing = await redis.get(depKey);
187
231
  const depTopics: string[] = safeJsonParse<string[]>(existing, []);
188
232
  if (!depTopics.includes(topic)) depTopics.push(topic);
189
- await redis.set(depKey, JSON.stringify(depTopics), 'EX', 90 * 86400);
233
+ await redis.set(depKey, JSON.stringify(depTopics), 'EX', 365 * 86400); // 1-year TTL
190
234
  }
191
235
 
192
236
  const lessonObj = {
@@ -210,11 +254,11 @@ export async function handleBrainTool(
210
254
  };
211
255
  const lesson = JSON.stringify(lessonObj);
212
256
 
213
- // Always append to the history list (audit log); keep last 100 entries, 90-day TTL
257
+ // Always append to the history list (audit log); cap at 200 entries to prevent unbounded growth
214
258
  const listKey = `cachly:lessons:${topic}`;
215
259
  await redis.rpush(listKey, lesson);
216
- await redis.ltrim(listKey, -100, -1);
217
- await redis.expire(listKey, 90 * 86400);
260
+ await redis.ltrim(listKey, -200, -1);
261
+ await redis.expire(listKey, 365 * 86400); // 1-year TTL
218
262
 
219
263
  // Update best key for success/partial; for failure only update if no success exists
220
264
  if (outcome === 'success' || outcome === 'partial') {
@@ -347,6 +391,44 @@ export async function handleBrainTool(
347
391
  }
348
392
  } catch { /* CKG updates are non-critical */ }
349
393
 
394
+ // ── Proactive follow-up suggestion (CKG co-occurrence patterns) ─────────
395
+ // After a successful fix, check if related concepts commonly follow it.
396
+ // Uses CKG co-occurs edges with confidence > 0.4 and at least 2 trials.
397
+ const proactiveSuggestions: string[] = [];
398
+ if (outcome === 'success' || outcome === 'partial') {
399
+ try {
400
+ const conceptId = ckgSlug(topic);
401
+ const fromEdgeKeys = await redis.smembers(`cachly:ckg:idx:from:${conceptId}`);
402
+ for (const ek of fromEdgeKeys.slice(0, 20)) {
403
+ const er = await redis.get(ek);
404
+ if (!er) continue;
405
+ const edge = safeJsonParse<CKGEdge | null>(er, null);
406
+ if (!edge || edge.confidence < 0.4 || (edge.trials ?? 0) < 2) continue;
407
+ if (edge.edgeType !== 'co-occurs' && edge.edgeType !== 'causes') continue;
408
+ // Resolve related concept to a lesson key
409
+ const relTopic = edge.to
410
+ .replace(/^cause:/, '')
411
+ .replace(/^tag:/, '')
412
+ .replace(/^problem:/, '')
413
+ .replace(/-/g, ':')
414
+ .replace(/_/g, '-');
415
+ const relRaw = await redis.get(`cachly:lesson:best:${relTopic}`);
416
+ if (!relRaw) continue;
417
+ const relLesson = safeJsonParse<{ topic?: string; what_worked?: string } | null>(relRaw, null);
418
+ const displayTopic = relLesson?.topic ?? relTopic;
419
+ if (!relLesson || !relLesson.what_worked || displayTopic === topic) continue;
420
+ const pct = Math.round(edge.confidence * 100);
421
+ if (proactiveSuggestions.length === 0) proactiveSuggestions.push('');
422
+ proactiveSuggestions.push(
423
+ `🔮 **Pattern detected:** \`${displayTopic}\` tends to follow this (${pct}% co-occurrence across ${edge.trials} sessions)`,
424
+ ` → ${relLesson.what_worked.slice(0, 100)}${relLesson.what_worked.length > 100 ? '…' : ''}`,
425
+ ` → Pre-empt it now: \`recall_best_solution(topic="${displayTopic}")\``,
426
+ );
427
+ break; // one proactive hint is enough
428
+ }
429
+ } catch { /* non-critical */ }
430
+ }
431
+
350
432
  const emoji = outcome === 'success' ? '✅' : outcome === 'partial' ? '⚠️' : '❌';
351
433
  const sevEmoji = severity === 'critical' ? '🔴' : severity === 'major' ? '🟡' : '🟢';
352
434
  const action = isUpdate ? 'updated' : 'stored';
@@ -369,6 +451,7 @@ export async function handleBrainTool(
369
451
  : '',
370
452
  ...templateWarnings,
371
453
  ...iWasWrongWarning,
454
+ ...proactiveSuggestions,
372
455
  ].filter(l => l !== '').join('\n');
373
456
  }
374
457
 
@@ -422,27 +505,8 @@ export async function handleBrainTool(
422
505
  ? `📌 **You've looked this up 3 times.** Consider pinning it for instant access: add \`pinned: true\` via \`learn_from_attempts\` to always surface it first.`
423
506
  : '';
424
507
 
425
- // ── Trust signal (today-safe consensus layer) ───────────────────────
426
- // A lesson recalled many times — or confirmed by multiple distinct
427
- // authors — has proven its value. Surface that as social proof.
428
- const lessonAuthors = (lesson as { authors?: string[]; author?: string }).authors
429
- ?? ((lesson as { author?: string }).author ? [(lesson as { author?: string }).author!] : []);
430
- const distinctAuthors = [...new Set(lessonAuthors.filter(Boolean))];
431
- const rc = updatedLesson.recall_count;
432
- let trustBadge = '';
433
- if (distinctAuthors.length >= 2 && rc >= 5) {
434
- trustBadge = `🏆 **Battle-tested** — recalled ${rc}× · verified by ${distinctAuthors.length} developers. Trust this.`;
435
- } else if (rc >= 10) {
436
- trustBadge = `🏆 **Battle-tested** — recalled ${rc}×. This is one of your most-proven solutions.`;
437
- } else if (distinctAuthors.length >= 2) {
438
- trustBadge = `✅ **Team-verified** — confirmed by ${distinctAuthors.length} developers.`;
439
- } else if (rc >= 5) {
440
- trustBadge = `✅ **Proven** — recalled ${rc}× without contradiction.`;
441
- }
442
-
443
508
  return [
444
509
  rememberWhen,
445
- trustBadge,
446
510
  `${badge} **Best solution for \`${topic}\`** ${sevEmoji}${lesson.severity ? ` (${lesson.severity})` : ''} · recalled ${updatedLesson.recall_count}×`,
447
511
  ``,
448
512
  `**What worked:** ${lesson.what_worked}`,
@@ -507,22 +571,6 @@ export async function handleBrainTool(
507
571
  10,
508
572
  );
509
573
 
510
- // Increment recall_count on matched lessons (fire-and-forget — same as recall_best_solution).
511
- // This ensures the dashboard metric, Proven Laws, and trust badges reflect real smart_recall usage.
512
- const lessonMatches = kwMatches.filter(m => m.key.startsWith('cachly:lesson:best:'));
513
- for (const m of lessonMatches.slice(0, 5)) {
514
- const existing = await redis.get(m.key).catch(() => null);
515
- if (existing) {
516
- const lesson = safeJsonParse(existing, null as null | { recall_count?: number; [k: string]: unknown });
517
- if (lesson) {
518
- const updated = { ...lesson, recall_count: (lesson.recall_count ?? 0) + 1, verified_at: new Date().toISOString() };
519
- redis.set(m.key, JSON.stringify(updated)).catch(() => {});
520
- const savedMins = (lesson.severity as string) === 'critical' ? 240 : (lesson.severity as string) === 'major' ? 60 : 30;
521
- redis.incrbyfloat(`cachly:stats:time_saved_mins:${instance_id}`, savedMins).catch(() => {});
522
- }
523
- }
524
- }
525
-
526
574
  const lines: string[] = [`🧠 **Smart Recall** for: _"${query}"_\n`];
527
575
 
528
576
  // Show sub-query info if multi-topic was detected
@@ -794,6 +842,25 @@ export async function handleBrainTool(
794
842
  lines.push('');
795
843
  }
796
844
 
845
+ // ── Bootstrap wow moment (shown once after first auto git-bootstrap) ──────
846
+ // brain_from_git fires in the background on the first session_start with
847
+ // workspace_path. The result count is stored under a well-known key so the
848
+ // NEXT session can celebrate it — "🎉 Your Brain bootstrapped from 87 commits!"
849
+ if (!isFirstSession) {
850
+ try {
851
+ const bootstrapRaw = await redis.get('cachly:brain_from_git:auto_bootstrap_result');
852
+ if (bootstrapRaw) {
853
+ const br = safeJsonParse<{ count: number; ts: string } | null>(bootstrapRaw, null);
854
+ if (br && br.count > 0) {
855
+ await redis.del('cachly:brain_from_git:auto_bootstrap_result'); // show once
856
+ lines.push(`🎉 **Your Brain bootstrapped from your git history — ${br.count} patterns learned automatically.**`);
857
+ lines.push(` Arrives pre-briefed. No setup needed. Share with a teammate: \`npx @cachly-dev/mcp-server@latest invite\``);
858
+ lines.push('');
859
+ }
860
+ }
861
+ } catch { /* non-critical */ }
862
+ }
863
+
797
864
  // ── Team-virality: first-team-briefing wow moment ────────────────────
798
865
  // When a user joins a team brain (has team lessons from colleagues but
799
866
  // has never been briefed on them), show a dedicated "Welcome to your
@@ -937,31 +1004,6 @@ export async function handleBrainTool(
937
1004
  // Brain health
938
1005
  lines.push(`📊 **Brain:** ${lessons.length} lessons · ${ctxCount} context entries`, '');
939
1006
 
940
- // ── 📌 Proven Laws — auto-crystallized lessons (quick win 3) ─────────────
941
- // A lesson that has proven itself (recalled ≥ CRYSTALLIZE_RECALLS times) or
942
- // was explicitly pinned becomes a "law" — surfaced at the top of every
943
- // briefing so the most battle-tested knowledge is never buried. This is
944
- // the today-safe version of swarm crystallization: enough confirmations
945
- // auto-promote a lesson without any manual step.
946
- {
947
- type LessonPin = typeof lessons[0] & { pinned?: boolean };
948
- const CRYSTALLIZE_RECALLS = 5;
949
- const laws = (lessons as LessonPin[])
950
- .filter(l => l.outcome === 'success' && (l.pinned === true || (l.recall_count ?? 0) >= CRYSTALLIZE_RECALLS))
951
- .sort((a, b) => (b.recall_count ?? 0) - (a.recall_count ?? 0))
952
- .slice(0, 5);
953
- if (laws.length > 0) {
954
- lines.push(`📌 **Proven Laws** (auto-crystallized — your most-trusted knowledge):`);
955
- for (const l of laws) {
956
- const sev = l.severity === 'critical' ? '🔴' : l.severity === 'major' ? '🟡' : '';
957
- const rc = l.recall_count ?? 0;
958
- const why = l.pinned === true ? 'pinned' : `recalled ${rc}×`;
959
- lines.push(` 🏆${sev} \`${l.topic}\` _(${why})_ — ${l.what_worked.slice(0, 100)}`);
960
- }
961
- lines.push('');
962
- }
963
- }
964
-
965
1007
  // ── Layer 7: MCM Domain Coverage Map ────────────────────────────────────
966
1008
  if (lessons.length >= 3) {
967
1009
  const domainMap = new Map<string, { total: number; success: number; critical: number }>();
@@ -1061,14 +1103,8 @@ export async function handleBrainTool(
1061
1103
  for (const l of topRecalled) {
1062
1104
  const emoji = l.outcome === 'success' ? '✅' : l.outcome === 'partial' ? '⚠️' : '❌';
1063
1105
  const sev = l.severity === 'critical' ? '🔴' : l.severity === 'major' ? '🟡' : '';
1064
- const rc = l.recall_count ?? 0;
1065
- const la = (l as { authors?: string[]; author?: string }).authors
1066
- ?? ((l as { author?: string }).author ? [(l as { author?: string }).author!] : []);
1067
- const nAuthors = new Set(la.filter(Boolean)).size;
1068
- const trust = (nAuthors >= 2 && rc >= 5) || rc >= 10 ? ' 🏆'
1069
- : nAuthors >= 2 || rc >= 5 ? ' ✅' : '';
1070
- const rct = rc > 1 ? ` _(${rc}× recalled)_` : '';
1071
- lines.push(` ${emoji}${sev}${trust} \`${l.topic}\`${rct} — ${l.what_worked.slice(0, 100)}`);
1106
+ const rct = l.recall_count && l.recall_count > 1 ? ` _(${l.recall_count}× recalled)_` : '';
1107
+ lines.push(` ${emoji}${sev} \`${l.topic}\`${rct} — ${l.what_worked.slice(0, 100)}`);
1072
1108
  }
1073
1109
  lines.push('');
1074
1110
  }
@@ -1136,63 +1172,27 @@ export async function handleBrainTool(
1136
1172
  }
1137
1173
 
1138
1174
  // ── 🔮 Predictive Pre-Warning — intent-based danger detection ────────────
1139
- // Fires BEFORE work starts. Uses explicit focus when given; otherwise
1140
- // derives the likely work area from the last session's changed files +
1141
- // summary (you usually keep working where you left off). This makes the
1142
- // warning fire even when the caller forgets to pass `focus`.
1143
- {
1175
+ // Fires BEFORE work starts. If focus area has known failure patterns → warn loudly.
1176
+ if (focusTerms.length > 0) {
1144
1177
  type LessonAny = typeof lessons[0] & { author?: string; tags?: string[] };
1145
-
1146
- // Common path noise / extensions to drop when deriving terms from files.
1147
- const PATH_NOISE = new Set([
1148
- 'src', 'lib', 'test', 'tests', 'dist', 'index', 'main', 'app',
1149
- 'internal', 'pkg', 'cmd', 'node_modules', 'components', 'utils',
1150
- 'ts', 'tsx', 'js', 'jsx', 'go', 'py', 'rs', 'java', 'json', 'yaml', 'yml',
1151
- ]);
1152
- const deriveTermsFromFiles = (files: string[]): string[] => {
1153
- const terms = new Set<string>();
1154
- for (const f of files) {
1155
- for (const seg of f.toLowerCase().split(/[/\\._-]/)) {
1156
- if (seg.length > 3 && !PATH_NOISE.has(seg)) terms.add(seg);
1157
- }
1158
- }
1159
- return [...terms];
1160
- };
1161
-
1162
- let warnTerms = focusTerms;
1163
- let warnLabel = focus;
1164
- let derived = false;
1165
- if (warnTerms.length === 0 && lastSession) {
1166
- const fromFiles = deriveTermsFromFiles(lastSession.files_changed ?? []);
1167
- const fromSummary = (lastSession.summary ?? '').toLowerCase()
1168
- .replace(/[^a-z0-9\s:_-]/g, ' ').split(/\s+/).filter(t => t.length > 3 && !PATH_NOISE.has(t));
1169
- warnTerms = [...new Set([...fromFiles, ...fromSummary])];
1170
- warnLabel = 'where you left off last session';
1171
- derived = true;
1172
- }
1173
-
1174
- if (warnTerms.length > 0) {
1175
- const dangerLessons = (lessons as LessonAny[]).filter(l => {
1176
- if (l.outcome === 'success') return false;
1177
- const topicCategory = l.topic.split(':')[0];
1178
- return warnTerms.some(term =>
1179
- l.topic.toLowerCase().includes(term) ||
1180
- topicCategory === term ||
1181
- (l.tags ?? []).some((t: string) => t.toLowerCase() === term),
1182
- );
1183
- });
1184
- if (dangerLessons.length >= 1) {
1185
- const headline = derived
1186
- ? ` You're likely to continue **${warnLabel}** — ${dangerLessons.length} known pitfall${dangerLessons.length > 1 ? 's' : ''} there:`
1187
- : ` Known pitfalls for **"${warnLabel}"** (${dangerLessons.length} past failure${dangerLessons.length > 1 ? 's' : ''}):`;
1188
- const warning = [
1189
- `🚨 **PRE-WARNING** — Read this BEFORE starting:`,
1190
- headline,
1191
- ...dangerLessons.slice(0, 3).map(l => ` ❌ \`${l.topic}\` — ${(l.what_failed ?? l.what_worked).slice(0, 80)}`),
1192
- '',
1193
- ];
1194
- lines.splice(2, 0, ...warning); // after '🧠 **Session Briefing**' + empty line
1195
- }
1178
+ const dangerLessons = (lessons as LessonAny[]).filter(l => {
1179
+ if (l.outcome === 'success') return false;
1180
+ const topicCategory = l.topic.split(':')[0];
1181
+ return focusTerms.some(term =>
1182
+ l.topic.toLowerCase().includes(term) ||
1183
+ topicCategory === term ||
1184
+ (l.tags ?? []).some((t: string) => t.toLowerCase() === term),
1185
+ );
1186
+ });
1187
+ if (dangerLessons.length >= 1) {
1188
+ // Insert warning block right after the title line (index 1 = blank line after title)
1189
+ const warning = [
1190
+ `🚨 **PRE-WARNING** — Read this BEFORE starting:`,
1191
+ ` Known pitfalls for **"${focus}"** (${dangerLessons.length} past failure${dangerLessons.length > 1 ? 's' : ''}):`,
1192
+ ...dangerLessons.slice(0, 3).map(l => ` ❌ \`${l.topic}\` — ${(l.what_failed ?? l.what_worked).slice(0, 80)}`),
1193
+ '',
1194
+ ];
1195
+ lines.splice(2, 0, ...warning); // after '🧠 **Session Briefing**' + empty line
1196
1196
  }
1197
1197
  }
1198
1198
 
@@ -64,18 +64,13 @@ export async function handleContextTool(
64
64
  if (ttl && ttl > 0) {
65
65
  body['expires_at'] = new Date(Date.now() + ttl * 1000).toISOString();
66
66
  }
67
- const res = await fetch(`${vectorUrl}/entries`, {
67
+ await fetch(`${vectorUrl}/entries`, {
68
68
  method: 'POST',
69
69
  headers: { 'Content-Type': 'application/json' },
70
70
  body: JSON.stringify(body),
71
- signal: AbortSignal.timeout(8000),
72
- });
73
- if (!res.ok) {
74
- process.stderr.write(`[cachly] semantic index skipped (HTTP ${res.status}) — smart_recall on this context will be keyword-only\n`);
75
- }
76
- } catch (e) {
77
- // Embedding is optional — keyword recall still works. Log so it's debuggable.
78
- process.stderr.write(`[cachly] semantic index failed: ${e instanceof Error ? e.message : String(e)} — smart_recall on this context will be keyword-only\n`);
71
+ }).catch(() => undefined);
72
+ } catch {
73
+ // Embedding optional — continue silently
79
74
  }
80
75
  }
81
76
 
@@ -9,9 +9,6 @@ import { keywordSearch, tokenize } from '../search.js';
9
9
  import { safeJsonParse } from '../utils.js';
10
10
  import { computeEmbedding, hasEmbedProvider } from '../embeddings.js';
11
11
 
12
- // Last brain_from_git category counts — set after each run so index.ts can include them in telemetry
13
- export let _lastBrainFromGitCounts: { fixes: number; features: number; refactors: number; total: number } | null = null;
14
-
15
12
  // Git concurrency semaphore (for brain_from_git parallel workers)
16
13
  let _gitSemCount = 0;
17
14
  const _GIT_SEM_MAX = 10;
@@ -366,6 +363,8 @@ export async function handleFedbrainTool(
366
363
 
367
364
  if (hooksArr.includes('ci')) {
368
365
  lines.push(`### GitHub Actions CI outcome hook`);
366
+ lines.push(`**Setup:** add a repo secret \`CACHLY_CACHE_TOKEN\` = your instance's cache token`);
367
+ lines.push(`(find it via \`get_connection_string\` — the token in the cache URL).`);
369
368
  lines.push(`**Add at the end of each job** (after build/test steps):`);
370
369
  lines.push('```yaml');
371
370
  lines.push(`- name: cachly CLS — record CI outcome`);
@@ -373,15 +372,14 @@ export async function handleFedbrainTool(
373
372
  lines.push(` run: |`);
374
373
  lines.push(` node -e "`);
375
374
  lines.push(` const r=require('https');`);
376
- lines.push(` const d=JSON.stringify({instance_id:'${instance_id}',source:'ci_outcome',payload:{`);
375
+ lines.push(` const d=JSON.stringify({source:'ci_outcome',payload:{`);
377
376
  lines.push(` status:'\${{ job.status }}',prev_status:'unknown',job:'\${{ github.job }}',`);
378
377
  lines.push(` context:'github-actions run \${{ github.run_number }}'}});`);
379
- lines.push(` r.request({hostname:'api.cachly.dev',path:'/api/v1/cls/ingest',method:'POST',`);
380
- lines.push(` headers:{'Content-Type':'application/json','Authorization':'Bearer $CACHLY_JWT',`);
381
- lines.push(` 'Content-Length':d.length}},()=>{}).end(d);`);
378
+ lines.push(` r.request({hostname:'api.cachly.dev',path:'/v1/cache/'+process.env.CACHLY_CACHE_TOKEN+'/cls/ingest',method:'POST',`);
379
+ lines.push(` headers:{'Content-Type':'application/json','Content-Length':d.length}},()=>{}).end(d);`);
382
380
  lines.push(` " 2>/dev/null || true`);
383
381
  lines.push(` env:`);
384
- lines.push(` CACHLY_JWT: \${{ secrets.CACHLY_JWT }}`);
382
+ lines.push(` CACHLY_CACHE_TOKEN: \${{ secrets.CACHLY_CACHE_TOKEN }}`);
385
383
  lines.push('```');
386
384
  lines.push('');
387
385
  }
@@ -1015,16 +1013,11 @@ export async function handleFedbrainTool(
1015
1013
  // Only store if no existing lesson for this topic (avoid overwriting higher-confidence lessons)
1016
1014
  const existing = await redis.get(`cachly:lesson:best:${topic}`);
1017
1015
  if (!existing) {
1018
- // Auto-inferred git lessons get a 90-day TTL — they self-refresh on the next
1019
- // brain_from_git run, and shouldn't pin memory forever if the repo goes stale.
1020
- await redis.set(`cachly:lesson:best:${topic}`, JSON.stringify(lessonObj), 'EX', 90 * 86400);
1016
+ await redis.set(`cachly:lesson:best:${topic}`, JSON.stringify(lessonObj));
1021
1017
  await redis.rpush(`cachly:lessons:${topic}`, JSON.stringify(lessonObj));
1022
- await redis.ltrim(`cachly:lessons:${topic}`, -100, -1);
1023
- await redis.expire(`cachly:lessons:${topic}`, 90 * 86400);
1024
1018
  }
1025
1019
  await redis.rpush('cachly:lessons:brain_from_git:all', JSON.stringify({ topic, sha: commit.sha.slice(0, 8), subject: commit.subject.slice(0, 60) }));
1026
1020
  await redis.ltrim('cachly:lessons:brain_from_git:all', -500, -1);
1027
- await redis.expire('cachly:lessons:brain_from_git:all', 90 * 86400);
1028
1021
 
1029
1022
  // Update CKG
1030
1023
  const conceptId = ckgSlug(topic);
@@ -1041,13 +1034,6 @@ export async function handleFedbrainTool(
1041
1034
 
1042
1035
  const categoryBreakdown = [...categoryCount.entries()].sort((a, b) => b[1] - a[1]).map(([k, v]) => ` • **${k}** (${v})`).join('\n');
1043
1036
 
1044
- _lastBrainFromGitCounts = {
1045
- fixes: categoryCount.get('fix') ?? 0,
1046
- features: categoryCount.get('feat') ?? 0,
1047
- refactors: categoryCount.get('refactor') ?? 0,
1048
- total: ingested,
1049
- };
1050
-
1051
1037
  return [
1052
1038
  `🔁 **brain_from_git: ${repoDir}**`,
1053
1039
  isIncremental ? `🔄 Incremental mode — only new commits since \`${lastSha.slice(0, 8)}\` were processed` : '',
@@ -157,12 +157,9 @@ export async function handleRoadmapTool(
157
157
  const PRIORITY_ORDER: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3 };
158
158
  const PRIORITY_ICON: Record<string, string> = { critical: '🔴', high: '🟠', medium: '🟡', low: '🔵' };
159
159
  const items = Object.values(all)
160
- .flatMap(v => {
161
- const item = safeJsonParse<Record<string, unknown> | null>(v as string, null);
162
- return item ? [item] : [];
163
- })
160
+ .map(v => JSON.parse(v as string) as Record<string, unknown>)
164
161
  .filter(i => i.status === 'in-progress' || i.status === 'planned')
165
- .filter(i => !filterTag || (Array.isArray(i.tags) ? i.tags : []).includes(filterTag));
162
+ .filter(i => !filterTag || (i.tags as string[]).includes(filterTag));
166
163
  if (items.length === 0) return '🎉 **No open roadmap items!** All tasks are done (or use `roadmap_list` to check).';
167
164
  // in-progress first, then by priority
168
165
  items.sort((a, b) => {
@@ -172,8 +169,7 @@ export async function handleRoadmapTool(
172
169
  });
173
170
  const next = items[0];
174
171
  const remaining = items.length - 1;
175
- const nextTags = Array.isArray(next.tags) ? next.tags as string[] : [];
176
- const tags = nextTags.length ? `\nTags: ${nextTags.join(', ')}` : '';
172
+ const tags = (next.tags as string[]).length ? `\nTags: ${(next.tags as string[]).join(', ')}` : '';
177
173
  const milestone = next.milestone ? `\nMilestone: ${next.milestone}` : '';
178
174
  const notes = next.notes ? `\nNotes: ${(next.notes as string).split('\n').pop()?.slice(0, 120)}` : '';
179
175
  return [
@@ -109,7 +109,9 @@ export async function handleTeamTool(
109
109
  file_paths: file_paths ?? [],
110
110
  commands: commands ?? [],
111
111
  tags: [...(tags ?? []), 'team'],
112
- timestamp: new Date().toISOString(),
112
+ ts: new Date().toISOString(),
113
+ verified_at: outcome === 'success' ? new Date().toISOString() : undefined,
114
+ confidence: 1.0,
113
115
  recall_count: 0,
114
116
  version: 2,
115
117
  };