@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.
- package/.github/workflows/publish.yml +2 -2
- package/README.md +33 -5
- package/dist/__tests__/auth.test.js.map +1 -0
- package/dist/{src/__tests__ → __tests__}/brain-flow.test.js +0 -141
- package/dist/__tests__/brain-flow.test.js.map +1 -0
- package/dist/__tests__/brain-predict-failures.test.d.ts +17 -0
- package/dist/__tests__/brain-predict-failures.test.js +339 -0
- package/dist/__tests__/brain-predict-failures.test.js.map +1 -0
- package/dist/__tests__/confidence.test.js.map +1 -0
- package/dist/__tests__/e2e/api-auth.test.js.map +1 -0
- package/dist/__tests__/e2e/api-health.test.js.map +1 -0
- package/dist/__tests__/e2e/cli.test.js.map +1 -0
- package/dist/__tests__/e2e/config.js.map +1 -0
- package/dist/__tests__/e2e/funnel.test.js.map +1 -0
- package/dist/__tests__/e2e/mcp-tools.test.js.map +1 -0
- package/dist/__tests__/e2e/provisioning.test.js.map +1 -0
- package/dist/{src/__tests__ → __tests__}/handlers-unit.test.js +2 -0
- package/dist/__tests__/handlers-unit.test.js.map +1 -0
- package/dist/__tests__/namespace.test.js.map +1 -0
- package/dist/auth.js.map +1 -0
- package/dist/ckg.js.map +1 -0
- package/dist/confidence.js.map +1 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/handlers/advanced.js.map +1 -0
- package/dist/{src/handlers → handlers}/brain.js +141 -135
- package/dist/handlers/brain.js.map +1 -0
- package/dist/handlers/cache.js.map +1 -0
- package/dist/{src/handlers → handlers}/context.js +4 -9
- package/dist/handlers/context.js.map +1 -0
- package/dist/{src/handlers → handlers}/fedbrain.d.ts +0 -6
- package/dist/{src/handlers → handlers}/fedbrain.js +7 -19
- package/dist/handlers/fedbrain.js.map +1 -0
- package/dist/handlers/instances.js.map +1 -0
- package/dist/{src/handlers → handlers}/roadmap.js +3 -7
- package/dist/handlers/roadmap.js.map +1 -0
- package/dist/handlers/syndicate.js.map +1 -0
- package/dist/{src/handlers → handlers}/team.js +3 -1
- package/dist/handlers/team.js.map +1 -0
- package/dist/{src/index.js → index.js} +428 -206
- package/dist/index.js.map +1 -0
- package/dist/namespace.js.map +1 -0
- package/dist/search.js.map +1 -0
- package/dist/search.test.js.map +1 -0
- package/dist/{src/tools.d.ts → tools.d.ts} +0 -196
- package/dist/{src/tools.js → tools.js} +0 -178
- package/dist/tools.js.map +1 -0
- package/dist/utils.js.map +1 -0
- package/package.json +3 -3
- package/smithery.yaml +16 -27
- package/src/__tests__/brain-flow.test.ts +0 -174
- package/src/__tests__/brain-predict-failures.test.ts +430 -0
- package/src/__tests__/handlers-unit.test.ts +2 -1
- package/src/handlers/brain.ts +142 -142
- package/src/handlers/context.ts +4 -9
- package/src/handlers/fedbrain.ts +7 -21
- package/src/handlers/roadmap.ts +3 -7
- package/src/handlers/team.ts +3 -1
- package/src/index.ts +415 -221
- package/src/tools.ts +0 -191
- package/tsconfig.json +3 -2
- package/.github/workflows/eas-build-android.yml +0 -58
- package/.github/workflows/eas-update.yml +0 -55
- package/STRATEGY.md +0 -209
- package/apps/travel-chaos-organizer/.env.example +0 -49
- package/apps/travel-chaos-organizer/DEPLOY.md +0 -328
- package/apps/travel-chaos-organizer/Makefile +0 -57
- package/apps/travel-chaos-organizer/README.md +0 -159
- package/apps/travel-chaos-organizer/backend/.env.example +0 -10
- package/apps/travel-chaos-organizer/backend/Dockerfile +0 -25
- package/apps/travel-chaos-organizer/backend/alembic/env.py +0 -56
- package/apps/travel-chaos-organizer/backend/alembic/script.py.mako +0 -24
- package/apps/travel-chaos-organizer/backend/alembic/versions/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/backend/alembic/versions/0001_stripe_customer_id.py +0 -24
- package/apps/travel-chaos-organizer/backend/alembic/versions/0002_telegram_chat_id.py +0 -24
- package/apps/travel-chaos-organizer/backend/alembic.ini +0 -39
- package/apps/travel-chaos-organizer/backend/app/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/auth/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/auth/keycloak.py +0 -81
- package/apps/travel-chaos-organizer/backend/app/config.py +0 -66
- package/apps/travel-chaos-organizer/backend/app/db/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/db/database.py +0 -20
- package/apps/travel-chaos-organizer/backend/app/db/migrations/001_init.sql +0 -71
- package/apps/travel-chaos-organizer/backend/app/db/migrations/002_telemetry_freemium.sql +0 -31
- package/apps/travel-chaos-organizer/backend/app/db/migrations/003_telegram_chat_id.sql +0 -4
- package/apps/travel-chaos-organizer/backend/app/db/migrations/004_stripe_and_email.sql +0 -5
- package/apps/travel-chaos-organizer/backend/app/limiter.py +0 -4
- package/apps/travel-chaos-organizer/backend/app/logging_config.py +0 -25
- package/apps/travel-chaos-organizer/backend/app/main.py +0 -77
- package/apps/travel-chaos-organizer/backend/app/models/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/models/schemas.py +0 -142
- package/apps/travel-chaos-organizer/backend/app/routers/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/routers/admin.py +0 -237
- package/apps/travel-chaos-organizer/backend/app/routers/cache.py +0 -13
- package/apps/travel-chaos-organizer/backend/app/routers/events.py +0 -29
- package/apps/travel-chaos-organizer/backend/app/routers/export.py +0 -122
- package/apps/travel-chaos-organizer/backend/app/routers/inbox.py +0 -122
- package/apps/travel-chaos-organizer/backend/app/routers/items.py +0 -130
- package/apps/travel-chaos-organizer/backend/app/routers/mail.py +0 -108
- package/apps/travel-chaos-organizer/backend/app/routers/parse.py +0 -303
- package/apps/travel-chaos-organizer/backend/app/routers/payments.py +0 -179
- package/apps/travel-chaos-organizer/backend/app/routers/trips.py +0 -134
- package/apps/travel-chaos-organizer/backend/app/routers/users.py +0 -169
- package/apps/travel-chaos-organizer/backend/app/routers/waitlist.py +0 -37
- package/apps/travel-chaos-organizer/backend/app/services/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/app/services/cache.py +0 -131
- package/apps/travel-chaos-organizer/backend/app/services/drip.py +0 -128
- package/apps/travel-chaos-organizer/backend/app/services/email.py +0 -61
- package/apps/travel-chaos-organizer/backend/app/services/errors.py +0 -44
- package/apps/travel-chaos-organizer/backend/app/services/notifier.py +0 -10
- package/apps/travel-chaos-organizer/backend/app/services/ollama.py +0 -101
- package/apps/travel-chaos-organizer/backend/app/services/parser.py +0 -22
- package/apps/travel-chaos-organizer/backend/app/services/quota.py +0 -85
- package/apps/travel-chaos-organizer/backend/app/services/sentry.py +0 -11
- package/apps/travel-chaos-organizer/backend/app/services/telemetry.py +0 -35
- package/apps/travel-chaos-organizer/backend/pytest.ini +0 -4
- package/apps/travel-chaos-organizer/backend/requirements-dev.txt +0 -6
- package/apps/travel-chaos-organizer/backend/requirements.txt +0 -25
- package/apps/travel-chaos-organizer/backend/tests/__init__.py +0 -0
- package/apps/travel-chaos-organizer/backend/tests/conftest.py +0 -223
- package/apps/travel-chaos-organizer/backend/tests/test_admin.py +0 -99
- package/apps/travel-chaos-organizer/backend/tests/test_cache.py +0 -142
- package/apps/travel-chaos-organizer/backend/tests/test_drip.py +0 -32
- package/apps/travel-chaos-organizer/backend/tests/test_e2e_chain.py +0 -121
- package/apps/travel-chaos-organizer/backend/tests/test_export.py +0 -48
- package/apps/travel-chaos-organizer/backend/tests/test_inbox.py +0 -107
- package/apps/travel-chaos-organizer/backend/tests/test_items.py +0 -138
- package/apps/travel-chaos-organizer/backend/tests/test_mail.py +0 -113
- package/apps/travel-chaos-organizer/backend/tests/test_ollama.py +0 -145
- package/apps/travel-chaos-organizer/backend/tests/test_parse_url.py +0 -98
- package/apps/travel-chaos-organizer/backend/tests/test_parser.py +0 -72
- package/apps/travel-chaos-organizer/backend/tests/test_payments.py +0 -163
- package/apps/travel-chaos-organizer/backend/tests/test_quota.py +0 -46
- package/apps/travel-chaos-organizer/backend/tests/test_search.py +0 -67
- package/apps/travel-chaos-organizer/backend/tests/test_trips.py +0 -123
- package/apps/travel-chaos-organizer/backend/tests/test_users.py +0 -52
- package/apps/travel-chaos-organizer/backups/.gitkeep +0 -0
- package/apps/travel-chaos-organizer/caddy/Caddyfile +0 -27
- package/apps/travel-chaos-organizer/docker-compose.node1.yml +0 -31
- package/apps/travel-chaos-organizer/docker-compose.override.yml +0 -14
- package/apps/travel-chaos-organizer/docker-compose.yml +0 -128
- package/apps/travel-chaos-organizer/frontend/.env.example +0 -13
- package/apps/travel-chaos-organizer/frontend/app/(app)/_layout.tsx +0 -80
- package/apps/travel-chaos-organizer/frontend/app/(app)/inbox.tsx +0 -166
- package/apps/travel-chaos-organizer/frontend/app/(app)/search.tsx +0 -130
- package/apps/travel-chaos-organizer/frontend/app/(app)/settings.tsx +0 -381
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips/[id].tsx +0 -346
- package/apps/travel-chaos-organizer/frontend/app/(app)/trips.tsx +0 -363
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/cancel.tsx +0 -34
- package/apps/travel-chaos-organizer/frontend/app/(app)/upgrade/success.tsx +0 -35
- package/apps/travel-chaos-organizer/frontend/app/(auth)/login.tsx +0 -91
- package/apps/travel-chaos-organizer/frontend/app/_layout.tsx +0 -71
- package/apps/travel-chaos-organizer/frontend/app/auth.tsx +0 -29
- package/apps/travel-chaos-organizer/frontend/app/index.tsx +0 -16
- package/apps/travel-chaos-organizer/frontend/app/onboarding.tsx +0 -119
- package/apps/travel-chaos-organizer/frontend/app.config.ts +0 -54
- package/apps/travel-chaos-organizer/frontend/assets/adaptive-icon.svg +0 -66
- package/apps/travel-chaos-organizer/frontend/assets/icon.svg +0 -79
- package/apps/travel-chaos-organizer/frontend/assets/splash.svg +0 -15
- package/apps/travel-chaos-organizer/frontend/components/BottomSheet.tsx +0 -102
- package/apps/travel-chaos-organizer/frontend/components/ConfettiCannon.tsx +0 -107
- package/apps/travel-chaos-organizer/frontend/components/ConfirmDialog.tsx +0 -109
- package/apps/travel-chaos-organizer/frontend/components/ErrorBoundary.tsx +0 -45
- package/apps/travel-chaos-organizer/frontend/components/FileUploadButton.tsx +0 -19
- package/apps/travel-chaos-organizer/frontend/components/ImportSheet.tsx +0 -155
- package/apps/travel-chaos-organizer/frontend/components/OfflineBadge.tsx +0 -55
- package/apps/travel-chaos-organizer/frontend/components/QRCodeViewer.tsx +0 -80
- package/apps/travel-chaos-organizer/frontend/components/ScoreRing.tsx +0 -39
- package/apps/travel-chaos-organizer/frontend/components/Screen.tsx +0 -39
- package/apps/travel-chaos-organizer/frontend/components/Skeleton.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/SwipeableInboxItem.tsx +0 -121
- package/apps/travel-chaos-organizer/frontend/components/SwipeableTimelineItem.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/TimelineItem.tsx +0 -73
- package/apps/travel-chaos-organizer/frontend/components/TimelineItemDetail.tsx +0 -130
- package/apps/travel-chaos-organizer/frontend/components/Toast.tsx +0 -60
- package/apps/travel-chaos-organizer/frontend/components/ToastContext.tsx +0 -42
- package/apps/travel-chaos-organizer/frontend/components/TripCard.tsx +0 -146
- package/apps/travel-chaos-organizer/frontend/components/TripQRModal.tsx +0 -70
- package/apps/travel-chaos-organizer/frontend/components/UpgradeBanner.tsx +0 -44
- package/apps/travel-chaos-organizer/frontend/eas.json +0 -22
- package/apps/travel-chaos-organizer/frontend/hooks/useInbox.ts +0 -24
- package/apps/travel-chaos-organizer/frontend/hooks/useNetworkSync.ts +0 -60
- package/apps/travel-chaos-organizer/frontend/hooks/useTrips.ts +0 -112
- package/apps/travel-chaos-organizer/frontend/lib/api.ts +0 -223
- package/apps/travel-chaos-organizer/frontend/lib/auth.ts +0 -93
- package/apps/travel-chaos-organizer/frontend/lib/db.ts +0 -86
- package/apps/travel-chaos-organizer/frontend/lib/fileCache.ts +0 -54
- package/apps/travel-chaos-organizer/frontend/lib/haptics.ts +0 -13
- package/apps/travel-chaos-organizer/frontend/lib/notifications.ts +0 -112
- package/apps/travel-chaos-organizer/frontend/lib/offlineQueue.ts +0 -145
- package/apps/travel-chaos-organizer/frontend/lib/quota.tsx +0 -43
- package/apps/travel-chaos-organizer/frontend/lib/sentry.ts +0 -28
- package/apps/travel-chaos-organizer/frontend/lib/shareIntent.ts +0 -44
- package/apps/travel-chaos-organizer/frontend/package-lock.json +0 -13037
- package/apps/travel-chaos-organizer/frontend/package.json +0 -44
- package/apps/travel-chaos-organizer/frontend/tsconfig.json +0 -23
- package/apps/travel-chaos-organizer/keycloak/realm-export.json +0 -59
- package/apps/travel-chaos-organizer/landing/index.html +0 -773
- package/apps/travel-chaos-organizer/scripts/backup.sh +0 -14
- package/apps/travel-chaos-organizer/scripts/configure-env.sh +0 -82
- package/apps/travel-chaos-organizer/scripts/deploy.sh +0 -54
- package/apps/travel-chaos-organizer/scripts/health-check.sh +0 -36
- package/apps/travel-chaos-organizer/scripts/migrate.sh +0 -7
- package/apps/travel-chaos-organizer/scripts/server-setup.sh +0 -85
- package/apps/travel-chaos-organizer/scripts/smoke-test.sh +0 -29
- package/apps/travel-chaos-organizer/scripts/verify-tracking.sh +0 -71
- package/apps/travel-chaos-organizer/telegram-bot/.env.example +0 -3
- package/apps/travel-chaos-organizer/telegram-bot/Dockerfile +0 -6
- package/apps/travel-chaos-organizer/telegram-bot/bot.py +0 -504
- package/apps/travel-chaos-organizer/telegram-bot/requirements.txt +0 -3
- package/dist/packages/telegram-notify/client.d.ts +0 -19
- package/dist/packages/telegram-notify/client.js +0 -75
- package/dist/packages/telegram-notify/client.js.map +0 -1
- package/dist/src/__tests__/auth.test.js.map +0 -1
- package/dist/src/__tests__/brain-flow.test.js.map +0 -1
- package/dist/src/__tests__/confidence.test.js.map +0 -1
- package/dist/src/__tests__/e2e/api-auth.test.js.map +0 -1
- package/dist/src/__tests__/e2e/api-health.test.js.map +0 -1
- package/dist/src/__tests__/e2e/cli.test.js.map +0 -1
- package/dist/src/__tests__/e2e/config.js.map +0 -1
- package/dist/src/__tests__/e2e/funnel.test.js.map +0 -1
- package/dist/src/__tests__/e2e/mcp-tools.test.js.map +0 -1
- package/dist/src/__tests__/e2e/provisioning.test.js.map +0 -1
- package/dist/src/__tests__/handlers-unit.test.js.map +0 -1
- package/dist/src/__tests__/namespace.test.js.map +0 -1
- package/dist/src/auth.js.map +0 -1
- package/dist/src/ckg.js.map +0 -1
- package/dist/src/confidence.js.map +0 -1
- package/dist/src/embeddings.js.map +0 -1
- package/dist/src/handlers/advanced.js.map +0 -1
- package/dist/src/handlers/brain.js.map +0 -1
- package/dist/src/handlers/cache.js.map +0 -1
- package/dist/src/handlers/context.js.map +0 -1
- package/dist/src/handlers/fedbrain.js.map +0 -1
- package/dist/src/handlers/instances.js.map +0 -1
- package/dist/src/handlers/roadmap.js.map +0 -1
- package/dist/src/handlers/syndicate.js.map +0 -1
- package/dist/src/handlers/tco.d.ts +0 -16
- package/dist/src/handlers/tco.js +0 -303
- package/dist/src/handlers/tco.js.map +0 -1
- package/dist/src/handlers/team.js.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/namespace.js.map +0 -1
- package/dist/src/notifier.d.ts +0 -5
- package/dist/src/notifier.js +0 -6
- package/dist/src/notifier.js.map +0 -1
- package/dist/src/search.js.map +0 -1
- package/dist/src/search.test.js.map +0 -1
- package/dist/src/tools.js.map +0 -1
- package/dist/src/utils.js.map +0 -1
- package/packages/telegram-notify/SPLIT_PLAN.md +0 -106
- package/packages/telegram-notify/client.ts +0 -88
- package/packages/telegram-notify/emojis.json +0 -22
- package/packages/telegram-notify/pyproject.toml +0 -17
- package/packages/telegram-notify/telegram_notify/__init__.py +0 -3
- package/packages/telegram-notify/telegram_notify/client.py +0 -87
- package/packages/telegram-notify/telegram_notify/emojis.json +0 -22
- package/scripts/generate-icons.js +0 -28
- package/src/handlers/tco.ts +0 -347
- package/src/notifier.ts +0 -5
- /package/dist/{src/__tests__ → __tests__}/auth.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/auth.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/brain-flow.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/confidence.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/confidence.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/api-auth.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/api-auth.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/api-health.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/api-health.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/cli.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/cli.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/config.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/config.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/funnel.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/funnel.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/mcp-tools.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/mcp-tools.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/provisioning.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/e2e/provisioning.test.js +0 -0
- /package/dist/{src/__tests__ → __tests__}/handlers-unit.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/namespace.test.d.ts +0 -0
- /package/dist/{src/__tests__ → __tests__}/namespace.test.js +0 -0
- /package/dist/{src/auth.d.ts → auth.d.ts} +0 -0
- /package/dist/{src/auth.js → auth.js} +0 -0
- /package/dist/{src/ckg.d.ts → ckg.d.ts} +0 -0
- /package/dist/{src/ckg.js → ckg.js} +0 -0
- /package/dist/{src/confidence.d.ts → confidence.d.ts} +0 -0
- /package/dist/{src/confidence.js → confidence.js} +0 -0
- /package/dist/{src/embeddings.d.ts → embeddings.d.ts} +0 -0
- /package/dist/{src/embeddings.js → embeddings.js} +0 -0
- /package/dist/{src/handlers → handlers}/advanced.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/advanced.js +0 -0
- /package/dist/{src/handlers → handlers}/brain.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/cache.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/cache.js +0 -0
- /package/dist/{src/handlers → handlers}/context.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/instances.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/instances.js +0 -0
- /package/dist/{src/handlers → handlers}/roadmap.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/syndicate.d.ts +0 -0
- /package/dist/{src/handlers → handlers}/syndicate.js +0 -0
- /package/dist/{src/handlers → handlers}/team.d.ts +0 -0
- /package/dist/{src/index.d.ts → index.d.ts} +0 -0
- /package/dist/{src/namespace.d.ts → namespace.d.ts} +0 -0
- /package/dist/{src/namespace.js → namespace.js} +0 -0
- /package/dist/{src/search.d.ts → search.d.ts} +0 -0
- /package/dist/{src/search.js → search.js} +0 -0
- /package/dist/{src/search.test.d.ts → search.test.d.ts} +0 -0
- /package/dist/{src/search.test.js → search.test.js} +0 -0
- /package/dist/{src/utils.d.ts → utils.d.ts} +0 -0
- /package/dist/{src/utils.js → utils.js} +0 -0
package/src/handlers/brain.ts
CHANGED
|
@@ -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
|
-
|
|
9
|
+
indexVocab as _indexVocab } from '../search.js';
|
|
10
10
|
import type { KeywordMatch } from '../search.js';
|
|
11
|
-
import { computeEmbedding, hasEmbedProvider
|
|
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.
|
|
14
|
+
const MCP_VERSION = '0.10.56';
|
|
16
15
|
const WHATS_NEW: Record<string, string[]> = {
|
|
17
|
-
'0.10.
|
|
18
|
-
`🆕 **What's new in
|
|
19
|
-
`
|
|
20
|
-
`
|
|
21
|
-
`
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
`
|
|
26
|
-
`
|
|
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',
|
|
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);
|
|
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, -
|
|
217
|
-
await redis.expire(listKey,
|
|
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
|
|
1065
|
-
|
|
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.
|
|
1140
|
-
|
|
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
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
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
|
|
package/src/handlers/context.ts
CHANGED
|
@@ -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
|
-
|
|
67
|
+
await fetch(`${vectorUrl}/entries`, {
|
|
68
68
|
method: 'POST',
|
|
69
69
|
headers: { 'Content-Type': 'application/json' },
|
|
70
70
|
body: JSON.stringify(body),
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
package/src/handlers/fedbrain.ts
CHANGED
|
@@ -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({
|
|
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:'/
|
|
380
|
-
lines.push(` headers:{'Content-Type':'application/json','
|
|
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(`
|
|
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
|
-
|
|
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` : '',
|
package/src/handlers/roadmap.ts
CHANGED
|
@@ -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
|
-
.
|
|
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 || (
|
|
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
|
|
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 [
|
package/src/handlers/team.ts
CHANGED
|
@@ -109,7 +109,9 @@ export async function handleTeamTool(
|
|
|
109
109
|
file_paths: file_paths ?? [],
|
|
110
110
|
commands: commands ?? [],
|
|
111
111
|
tags: [...(tags ?? []), 'team'],
|
|
112
|
-
|
|
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
|
};
|