@cachly-dev/mcp-server 0.10.121 β 0.10.123
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/README.md +31 -15
- package/dist/src/ambient-deps.d.ts +26 -0
- package/dist/src/ambient-deps.js +55 -0
- package/dist/src/ambient-deps.js.map +1 -0
- package/dist/src/ambient-hooks.d.ts +11 -2
- package/dist/src/ambient-hooks.js +11 -2
- package/dist/src/ambient-hooks.js.map +1 -1
- package/dist/src/ambient-ledger.js +2 -2
- package/dist/src/ambient-ledger.js.map +1 -1
- package/dist/src/ambient-memory.js +2 -2
- package/dist/src/ambient-memory.js.map +1 -1
- package/dist/src/auth.js +2 -1
- package/dist/src/auth.js.map +1 -1
- package/dist/src/brain-export.d.ts +40 -0
- package/dist/src/brain-export.js +89 -0
- package/dist/src/brain-export.js.map +1 -0
- package/dist/src/cachly-url.d.ts +68 -0
- package/dist/src/cachly-url.js +21 -0
- package/dist/src/cachly-url.js.map +1 -0
- package/dist/src/credentials.d.ts +37 -0
- package/dist/src/credentials.js +85 -0
- package/dist/src/credentials.js.map +1 -0
- package/dist/src/doctor.js +2 -1
- package/dist/src/doctor.js.map +1 -1
- package/dist/src/first-recall-proof.d.ts +19 -0
- package/dist/src/first-recall-proof.js +41 -0
- package/dist/src/first-recall-proof.js.map +1 -0
- package/dist/src/handlers/advanced.js +13 -29
- package/dist/src/handlers/advanced.js.map +1 -1
- package/dist/src/handlers/brain.js +132 -41
- package/dist/src/handlers/brain.js.map +1 -1
- package/dist/src/handlers/cache.js +3 -2
- package/dist/src/handlers/cache.js.map +1 -1
- package/dist/src/handlers/fedbrain.js +15 -4
- package/dist/src/handlers/fedbrain.js.map +1 -1
- package/dist/src/handlers/share.js +4 -3
- package/dist/src/handlers/share.js.map +1 -1
- package/dist/src/handlers/team.js +2 -1
- package/dist/src/handlers/team.js.map +1 -1
- package/dist/src/index.d.ts +32 -2
- package/dist/src/index.js +308 -94
- package/dist/src/index.js.map +1 -1
- package/dist/src/kostprobe.d.ts +25 -0
- package/dist/src/kostprobe.js +125 -0
- package/dist/src/kostprobe.js.map +1 -0
- package/dist/src/telemetry-types.d.ts +1 -1
- package/dist/src/tools.d.ts +0 -99
- package/dist/src/tools.js +0 -110
- package/dist/src/tools.js.map +1 -1
- package/dist/src/toolspecs.d.ts +1 -1
- package/dist/src/toolspecs.js +1 -1
- package/dist/src/upgrade-nudge.d.ts +15 -0
- package/dist/src/upgrade-nudge.js +29 -0
- package/dist/src/upgrade-nudge.js.map +1 -0
- package/glama.json +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.js +1 -1
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# π§ cachly AI Brain β MCP Server
|
|
2
2
|
|
|
3
|
-
> ###
|
|
4
|
-
>
|
|
5
|
-
>
|
|
6
|
-
>
|
|
3
|
+
> ### ChatGPT and Claude remember your conversations.
|
|
4
|
+
> ### cachly remembers your codebase.
|
|
5
|
+
>
|
|
6
|
+
> The bug you fixed. Why you chose Postgres. The deploy step that always breaks β and
|
|
7
|
+
> everything your teammates learned. **It stays when someone leaves the team, and it
|
|
8
|
+
> comes along when you switch assistants.**
|
|
7
9
|
|
|
8
10
|
<p align="center">
|
|
9
11
|
<a href="https://www.npmjs.com/package/@cachly-dev/mcp-server">
|
|
@@ -22,7 +24,7 @@
|
|
|
22
24
|
<img src="https://img.shields.io/badge/GDPR-EU%20servers-green" alt="GDPR: EU servers" />
|
|
23
25
|
</a>
|
|
24
26
|
|
|
25
|
-
<img src="https://img.shields.io/badge/
|
|
27
|
+
<img src="https://img.shields.io/badge/122_MCP_tools-violet" alt="122 MCP tools" />
|
|
26
28
|
|
|
27
29
|
<img src="https://img.shields.io/badge/License-Apache--2.0-yellow" alt="License: Apache-2.0" />
|
|
28
30
|
</p>
|
|
@@ -145,7 +147,10 @@ arrives pre-briefed β every session, automatically.
|
|
|
145
147
|
> ```
|
|
146
148
|
|
|
147
149
|
**Our agreement with you:** Free forever tier. GDPR, EU servers. No model lock-in β
|
|
148
|
-
leave anytime and take your data
|
|
150
|
+
leave anytime and take your data: `npx @cachly-dev/mcp-server@latest export` writes
|
|
151
|
+
every lesson to `lessons.md` (to read) and `lessons.jsonl` (to reuse). Code excerpts
|
|
152
|
+
are stored only if you call `index_project` yourself β and only on your own EU
|
|
153
|
+
instance.
|
|
149
154
|
|
|
150
155
|
---
|
|
151
156
|
|
|
@@ -277,9 +282,10 @@ Every CI run is a lesson: a redβgreen transition is a proven fix, a greenβre
|
|
|
277
282
|
known cause. Ready-to-paste templates live in
|
|
278
283
|
[`src/ci-integration/`](./src/ci-integration/):
|
|
279
284
|
|
|
280
|
-
- **GitHub Actions** β copy [`brain-from-ci-action.yml`](
|
|
285
|
+
- **GitHub Actions** β copy [`brain-from-ci-action.yml`](../github-action/templates/brain-from-ci-action.yml)
|
|
281
286
|
into `.github/workflows/`. It triggers on `workflow_run` (completed) and pushes the
|
|
282
|
-
outcome to your Brain. Requires `
|
|
287
|
+
outcome to your Brain. Requires `CACHLY_API_KEY` + `CACHLY_BRAIN_INSTANCE_ID` secrets
|
|
288
|
+
(`CACHLY_JWT` still works as a fallback).
|
|
283
289
|
- **GitLab CI** β copy [`brain-from-ci-gitlab.yml`](./src/ci-integration/brain-from-ci-gitlab.yml)
|
|
284
290
|
into your pipeline: two `.post` jobs (`on_success` / `on_failure`) with `allow_failure: true`.
|
|
285
291
|
Want more than outcome pushes? The full GitLab template
|
|
@@ -295,7 +301,7 @@ MCP tool β bulk-ingests past outcomes the same way `brain_from_git` ingests co
|
|
|
295
301
|
|
|
296
302
|
---
|
|
297
303
|
|
|
298
|
-
## MCP Tools (
|
|
304
|
+
## MCP Tools (122 total)
|
|
299
305
|
|
|
300
306
|
The full tool catalog is generated from `sdk/mcp/src/tools.ts`. Cross-surface
|
|
301
307
|
coverage is tracked in [`../../docs/generated/surface-parity.md`](../../docs/generated/surface-parity.md),
|
|
@@ -349,7 +355,7 @@ and pinned OpenAPI/OpenAI/Anthropic/LangChain projections live in
|
|
|
349
355
|
| Tool | What it does |
|
|
350
356
|
|------|-------------|
|
|
351
357
|
| **`brain_seed_starter`** | Seed 16 universal lessons so your **first** `smart_recall` hits β auto-runs on a fresh repo |
|
|
352
|
-
| **`brain_share`** |
|
|
358
|
+
| **`brain_share`** | Publish a Brain snapshot as a shareable link (public or unlisted) β a link to show off, not your data. For that, run `npx @cachly-dev/mcp-server export` |
|
|
353
359
|
| **`brain_import`** | Import any shared Brain into yours β `topic_prefix`, `min_confidence`, `dry_run` |
|
|
354
360
|
| `brain_share_list` / `brain_unshare` | List your shares Β· revoke a share (link goes dead) |
|
|
355
361
|
| **`brain_discover`** | Search the Brain marketplace for ready-made knowledge bases |
|
|
@@ -384,8 +390,11 @@ Yes β that's the point. `team_learn` / `team_recall`, or
|
|
|
384
390
|
`npx @cachly-dev/mcp-server@latest invite teammate@example.com`.
|
|
385
391
|
|
|
386
392
|
**Is my code sent to cachly servers?**
|
|
387
|
-
|
|
388
|
-
|
|
393
|
+
Only if you call `index_project` yourself: it stores a short excerpt (up to
|
|
394
|
+
`summary_chars`, default 1200 characters) per indexed file, on your own EU
|
|
395
|
+
instance. Every other tool stores lesson text, commit messages, session
|
|
396
|
+
summaries, and key-value context β no source code. All data on EU servers,
|
|
397
|
+
GDPR-compliant.
|
|
389
398
|
|
|
390
399
|
**What is `causal_trace` and why is it unique?**
|
|
391
400
|
Given any error, it walks the Causal Knowledge Graph to find root cause, intermediate
|
|
@@ -535,7 +544,7 @@ keep talking to your backend on every editor launch. All data stays in your infr
|
|
|
535
544
|
| **Speed** | 900 MB + Dragonfly | β¬79/mo | AI-heavy workloads |
|
|
536
545
|
| **Business** | 7 GB | β¬199/mo | Scale-ups |
|
|
537
546
|
|
|
538
|
-
β
All plans: **EU servers Β· GDPR-compliant Β·
|
|
547
|
+
β
All plans: **EU servers Β· GDPR-compliant Β· No credit card for Free**
|
|
539
548
|
|
|
540
549
|
---
|
|
541
550
|
|
|
@@ -546,7 +555,7 @@ keep talking to your backend on every editor launch. All data stays in your infr
|
|
|
546
555
|
| `CACHLY_JWT` | β | API token (set by wizard automatically) |
|
|
547
556
|
| `CACHLY_BRAIN_INSTANCE_ID` | β | Default instance UUID (optional β auto-resolved) |
|
|
548
557
|
| `CACHLY_API_URL` | `https://api.cachly.dev` | Override for self-hosted |
|
|
549
|
-
| `CACHLY_NO_TELEMETRY` | unset | Set to `1` to disable
|
|
558
|
+
| `CACHLY_NO_TELEMETRY` | unset | Set to `1` to disable usage pings (these include your API token and up to 80 characters of `smart_recall` queries) |
|
|
550
559
|
|
|
551
560
|
---
|
|
552
561
|
|
|
@@ -572,9 +581,16 @@ straight into your editor β your lessons follow you across all of them.
|
|
|
572
581
|
| **[`@cachly-dev/mcp-server`](https://www.npmjs.com/package/@cachly-dev/mcp-server)** | β you are here Β· works with Claude, Cursor, Copilot, Windsurf, Cline, Zed |
|
|
573
582
|
| **[Cachly Brain for VS Code](https://marketplace.visualstudio.com/items?itemName=cachly-dev.cachly-brain)** | One-click memory in the editor β status bar, lessons view, ambient learning. No terminal needed. |
|
|
574
583
|
| **[Cachly Brain for JetBrains](https://plugins.jetbrains.com/plugin/32059-cachly-brain)** | Same brain for IntelliJ / PyCharm / GoLand / WebStorm / Rider β status bar, brain health, lessons view. |
|
|
575
|
-
| **[`@cachly-dev/openclaw`](https://www.npmjs.com/package/@cachly-dev/openclaw)** | Cut LLM costs
|
|
584
|
+
| **[`@cachly-dev/openclaw`](https://www.npmjs.com/package/@cachly-dev/openclaw)** | Cut LLM costs with semantic caching in JS/TS apps |
|
|
576
585
|
| **[cachly-dev/cachly-action](https://github.com/cachly-dev/cachly-action)** | GitHub Action: auto-setup, PR risk scan, auto-learn from merged PRs, weekly hygiene |
|
|
577
586
|
|
|
587
|
+
Prefer a visual view over the terminal? The VS Code companion extension shows the
|
|
588
|
+
same Brain, live, in the editor:
|
|
589
|
+
|
|
590
|
+

|
|
591
|
+
|
|
592
|
+
*The Lessons view in the VS Code companion extension β the same lessons this server stores, browsable without leaving the editor.*
|
|
593
|
+
|
|
578
594
|
- π [cachly.dev](https://cachly.dev) β Dashboard & free signup
|
|
579
595
|
- π [Docs](https://cachly.dev/docs/ai-memory) β Full documentation
|
|
580
596
|
- πΊοΈ [Public Roadmap](https://cachly.dev/roadmap) β what's coming next
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type AmbientDeps } from './ambient-cli.js';
|
|
2
|
+
import { type RecallMemory } from './ambient-recall.js';
|
|
3
|
+
export interface BuildAmbientDepsOptions {
|
|
4
|
+
/** Brain instance to recall from. Missing/empty β recall is a no-op (never calls `smartRecall`). */
|
|
5
|
+
instanceId?: string;
|
|
6
|
+
/** The raw `smart_recall` call (already scoped to `instanceId` by the caller). */
|
|
7
|
+
smartRecall: (query: string) => Promise<string>;
|
|
8
|
+
/** Optional trigger memory (dedupe + quiet-budget). Stateless when omitted. */
|
|
9
|
+
loadMemory?: () => RecallMemory | null | undefined;
|
|
10
|
+
saveMemory?: (m: RecallMemory) => void;
|
|
11
|
+
/** Auto-backoff probe (Β§6.3 guardrail 3). */
|
|
12
|
+
backoff?: () => boolean | Promise<boolean>;
|
|
13
|
+
/** Called with the estimated injected tokens whenever context is emitted. */
|
|
14
|
+
onInject?: (tokens: number, event: string) => void;
|
|
15
|
+
/** Hard latency budget for the whole recall step (ms). Default 3000. */
|
|
16
|
+
timeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Builds the ONE production `AmbientDeps` used by the `ambient-recall` CLI
|
|
20
|
+
* entrypoint. This is the exact mapping that used to be inlined at the call
|
|
21
|
+
* site: a miss-detection heuristic, a token-truncated summary, and a
|
|
22
|
+
* content-derived candidate id β wrapped around whatever `smartRecall`
|
|
23
|
+
* implementation the caller passes in (production: `handleTool('smart_recall', ...)`;
|
|
24
|
+
* tests: a stub).
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildAmbientDeps(opts: BuildAmbientDepsOptions): AmbientDeps;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Ambient Recall β the production `AmbientDeps` factory.
|
|
2
|
+
//
|
|
3
|
+
// ambient-cli.ts (`runAmbient`) is dependency-injected on purpose so it can be
|
|
4
|
+
// unit-tested without a network. This module is the OTHER half of that seam:
|
|
5
|
+
// the one place that turns a raw `smart_recall` string reply into the
|
|
6
|
+
// `AmbientDeps.recall` candidates the gate understands β miss-detection,
|
|
7
|
+
// truncation and content-based IDs (PR #241 regression: the id must come from
|
|
8
|
+
// the summary, never a constant like 'ambient', or "same lesson twice" and
|
|
9
|
+
// "different lesson" become indistinguishable in `RecallMemory`).
|
|
10
|
+
//
|
|
11
|
+
// Previously this mapping lived inline at the `ambient-recall` CLI call site
|
|
12
|
+
// in index.ts. Moved here so the exact production wiring β not a hand-copied
|
|
13
|
+
// approximation of it β is what the seam test (SDK-003) exercises across
|
|
14
|
+
// multiple turns.
|
|
15
|
+
import { truncateToTokens } from './ambient-cli.js';
|
|
16
|
+
import { candidateIdFor } from './ambient-recall.js';
|
|
17
|
+
/** A brain reply that carries no usable lesson β same heuristic as smart_recall's own callers. */
|
|
18
|
+
const NO_LESSONS_RE = /No lessons found|no lessons|No matches found/i;
|
|
19
|
+
/** Below this length a `smart_recall` reply is boilerplate, not a real lesson. */
|
|
20
|
+
const MIN_LESSON_CHARS = 80;
|
|
21
|
+
/** Hard cap on how much of one recalled lesson may be injected (Β§6.2 budget). */
|
|
22
|
+
const MAX_LESSON_TOKENS = 500;
|
|
23
|
+
/**
|
|
24
|
+
* Builds the ONE production `AmbientDeps` used by the `ambient-recall` CLI
|
|
25
|
+
* entrypoint. This is the exact mapping that used to be inlined at the call
|
|
26
|
+
* site: a miss-detection heuristic, a token-truncated summary, and a
|
|
27
|
+
* content-derived candidate id β wrapped around whatever `smartRecall`
|
|
28
|
+
* implementation the caller passes in (production: `handleTool('smart_recall', ...)`;
|
|
29
|
+
* tests: a stub).
|
|
30
|
+
*/
|
|
31
|
+
export function buildAmbientDeps(opts) {
|
|
32
|
+
const { instanceId, smartRecall, loadMemory, saveMemory, backoff, onInject, timeoutMs } = opts;
|
|
33
|
+
return {
|
|
34
|
+
timeoutMs: timeoutMs ?? 3000, // Β§6.3 guardrail 4: never stall the prompt on a slow brain
|
|
35
|
+
// Ambient injection budget: one relevance-ranked briefing, hard-capped.
|
|
36
|
+
// smart_recall already returns its hits best-first, so the capped head is
|
|
37
|
+
// the high-signal part. Per-lesson structured candidates are a future slice.
|
|
38
|
+
gate: { topK: 1, maxTokens: MAX_LESSON_TOKENS },
|
|
39
|
+
loadMemory,
|
|
40
|
+
saveMemory,
|
|
41
|
+
backoff,
|
|
42
|
+
onInject,
|
|
43
|
+
recall: async (query) => {
|
|
44
|
+
if (!instanceId)
|
|
45
|
+
return [];
|
|
46
|
+
const text = String((await smartRecall(query)) ?? '');
|
|
47
|
+
const miss = text.length < MIN_LESSON_CHARS || NO_LESSONS_RE.test(text);
|
|
48
|
+
if (miss)
|
|
49
|
+
return [];
|
|
50
|
+
const summary = truncateToTokens(text, MAX_LESSON_TOKENS);
|
|
51
|
+
return [{ id: candidateIdFor(summary), summary, confidence: 0.9, score: 0.9 }];
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=ambient-deps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ambient-deps.js","sourceRoot":"","sources":["../../src/ambient-deps.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,sEAAsE;AACtE,yEAAyE;AACzE,8EAA8E;AAC9E,2EAA2E;AAC3E,kEAAkE;AAClE,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,kBAAkB;AAElB,OAAO,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAqB,MAAM,qBAAqB,CAAC;AAExE,kGAAkG;AAClG,MAAM,aAAa,GAAG,+CAA+C,CAAC;AAEtE,kFAAkF;AAClF,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B,iFAAiF;AACjF,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAkB9B;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAA6B;IAC5D,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC/F,OAAO;QACL,SAAS,EAAE,SAAS,IAAI,IAAI,EAAE,2DAA2D;QACzF,wEAAwE;QACxE,0EAA0E;QAC1E,6EAA6E;QAC7E,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,iBAAiB,EAAE;QAC/C,UAAU;QACV,UAAU;QACV,OAAO;QACP,QAAQ;QACR,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACtB,IAAI,CAAC,UAAU;gBAAE,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,gBAAgB,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxE,IAAI,IAAI;gBAAE,OAAO,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC1D,OAAO,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QACjF,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
* scripts silently never ran on native Windows (no /bin/sh); Node is already a
|
|
6
6
|
* hard requirement of this package, so the hook now runs identically on
|
|
7
7
|
* Windows, macOS and Linux.
|
|
8
|
+
* v4 (GROW-015): the script no longer embeds the caller's key as a string
|
|
9
|
+
* literal. It resolves CACHLY_JWT at run time from the environment instead,
|
|
10
|
+
* so a `.claude/hooks/` script that gets committed to a repo never leaks a
|
|
11
|
+
* secret. Bumping the version replaces old v1-v3 scripts (which DID embed
|
|
12
|
+
* the key) the next time setup/autopilot runs.
|
|
8
13
|
*/
|
|
9
|
-
export declare const AMBIENT_HOOK_VERSION = "
|
|
14
|
+
export declare const AMBIENT_HOOK_VERSION = "v4";
|
|
10
15
|
/**
|
|
11
16
|
* The CLI subcommand the hooks pipe their payload to. It reads the hook JSON on
|
|
12
17
|
* stdin, runs smart_recall through the relevance gate (ambient-recall.ts), and
|
|
@@ -17,7 +22,11 @@ export declare const AMBIENT_CLI_SUBCOMMAND = "ambient-recall";
|
|
|
17
22
|
export type AmbientHookEvent = 'SessionStart' | 'UserPromptSubmit' | 'PreToolUse' | 'Stop';
|
|
18
23
|
export interface AmbientHookOptions {
|
|
19
24
|
instanceId: string;
|
|
20
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Accepted for backward compatibility but never embedded in the generated
|
|
27
|
+
* script (GROW-015): the hook resolves its key at run time from
|
|
28
|
+
* CACHLY_JWT/CACHLY_API_KEY in the environment instead.
|
|
29
|
+
*/
|
|
21
30
|
apiKey?: string;
|
|
22
31
|
/**
|
|
23
32
|
* Command that resolves the ambient-recall CLI. Defaults to the published
|
|
@@ -25,8 +25,13 @@ import { resolve } from 'node:path';
|
|
|
25
25
|
* scripts silently never ran on native Windows (no /bin/sh); Node is already a
|
|
26
26
|
* hard requirement of this package, so the hook now runs identically on
|
|
27
27
|
* Windows, macOS and Linux.
|
|
28
|
+
* v4 (GROW-015): the script no longer embeds the caller's key as a string
|
|
29
|
+
* literal. It resolves CACHLY_JWT at run time from the environment instead,
|
|
30
|
+
* so a `.claude/hooks/` script that gets committed to a repo never leaks a
|
|
31
|
+
* secret. Bumping the version replaces old v1-v3 scripts (which DID embed
|
|
32
|
+
* the key) the next time setup/autopilot runs.
|
|
28
33
|
*/
|
|
29
|
-
export const AMBIENT_HOOK_VERSION = '
|
|
34
|
+
export const AMBIENT_HOOK_VERSION = 'v4';
|
|
30
35
|
/**
|
|
31
36
|
* The CLI subcommand the hooks pipe their payload to. It reads the hook JSON on
|
|
32
37
|
* stdin, runs smart_recall through the relevance gate (ambient-recall.ts), and
|
|
@@ -49,7 +54,11 @@ function buildHook(event, opts) {
|
|
|
49
54
|
`// the agent: every failure path exits 0 with no output (graceful degrade).`,
|
|
50
55
|
`import { spawn } from 'node:child_process';`,
|
|
51
56
|
`process.env.CACHLY_BRAIN_INSTANCE_ID = '${jsString(opts.instanceId)}';`,
|
|
52
|
-
|
|
57
|
+
// GROW-015: never embed the caller's key as a string literal here β read
|
|
58
|
+
// it at run time instead, so a committed .claude/hooks/ script can never
|
|
59
|
+
// leak a secret. Only the key's origin changed: same events, same
|
|
60
|
+
// output, same 3s budget, errors still swallowed.
|
|
61
|
+
`if (!process.env.CACHLY_JWT && process.env.CACHLY_API_KEY) process.env.CACHLY_JWT = process.env.CACHLY_API_KEY;`,
|
|
53
62
|
`process.env.CACHLY_HOOK_EVENT = '${jsString(event)}';`,
|
|
54
63
|
`try {`,
|
|
55
64
|
// Claude Code delivers the hook payload as JSON on stdin; stdio 'inherit'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambient-hooks.js","sourceRoot":"","sources":["../../src/ambient-hooks.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,mEAAmE;AACnE,2EAA2E;AAC3E,yEAAyE;AACzE,4EAA4E;AAC5E,oCAAoC;AACpC,EAAE;AACF,8BAA8B;AAC9B,uDAAuD;AACvD,2EAA2E;AAC3E,6EAA6E;AAC7E,oCAAoC;AACpC,8DAA8D;AAC9D,gFAAgF;AAChF,+EAA+E;AAC/E,0BAA0B;AAE1B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC
|
|
1
|
+
{"version":3,"file":"ambient-hooks.js","sourceRoot":"","sources":["../../src/ambient-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
// Everything here is best-effort: a broken ledger must never break a hook.
|
|
16
16
|
import { appendFile, readFile, rename, writeFile } from 'node:fs/promises';
|
|
17
17
|
import { mkdir } from 'node:fs/promises';
|
|
18
|
+
import { homedir } from 'node:os';
|
|
18
19
|
import { dirname, resolve } from 'node:path';
|
|
19
20
|
/** Default ledger location; overridable for tests via explicit path args. */
|
|
20
21
|
export function defaultLedgerPath() {
|
|
21
|
-
|
|
22
|
-
return resolve(home, '.cachly', 'ambient-ledger.jsonl');
|
|
22
|
+
return resolve(homedir(), '.cachly', 'ambient-ledger.jsonl');
|
|
23
23
|
}
|
|
24
24
|
/** One JSONL line for an entry. Pure. */
|
|
25
25
|
export function serializeEntry(e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambient-ledger.js","sourceRoot":"","sources":["../../src/ambient-ledger.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,kFAAkF;AAClF,8EAA8E;AAC9E,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,gFAAgF;AAChF,gFAAgF;AAChF,oEAAoE;AACpE,EAAE;AACF,2EAA2E;AAE3E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAY7C,6EAA6E;AAC7E,MAAM,UAAU,iBAAiB;IAC/B,
|
|
1
|
+
{"version":3,"file":"ambient-ledger.js","sourceRoot":"","sources":["../../src/ambient-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
2
3
|
import { resolve } from 'node:path';
|
|
3
4
|
import { emptyMemory } from './ambient-recall.js';
|
|
4
5
|
const MEMORY_FILE_NAME = 'ambient-memory.json';
|
|
5
6
|
const MAX_MEMORY_BYTES = 64 * 1024;
|
|
6
7
|
function defaultAmbientMemoryDir() {
|
|
7
|
-
|
|
8
|
-
return resolve(home, '.cachly');
|
|
8
|
+
return resolve(homedir(), '.cachly');
|
|
9
9
|
}
|
|
10
10
|
function isFiniteNumberRecord(value) {
|
|
11
11
|
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambient-memory.js","sourceRoot":"","sources":["../../src/ambient-memory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAErE,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;AAC/C,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC,SAAS,uBAAuB;IAC9B,
|
|
1
|
+
{"version":3,"file":"ambient-memory.js","sourceRoot":"","sources":["../../src/ambient-memory.ts"],"names":[],"mappings":"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"}
|
package/dist/src/auth.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { cachlyUrl } from './cachly-url.js';
|
|
2
3
|
export function jwtExpiryMs(token) {
|
|
3
4
|
try {
|
|
4
5
|
const parts = token.split('.');
|
|
@@ -26,7 +27,7 @@ export function isLongLivedApiKey(token) {
|
|
|
26
27
|
}
|
|
27
28
|
// Refresh a token this close to expiry (or already expired) the moment we touch it.
|
|
28
29
|
export const NEAR_EXPIRY_MS = 10 * 60 * 1000; // 10 minutes
|
|
29
|
-
const SETUP_URL = '
|
|
30
|
+
const SETUP_URL = cachlyUrl('/setup-ai', 'auth-diagnosis');
|
|
30
31
|
/**
|
|
31
32
|
* Diagnose the current credential without making any network call. Pure +
|
|
32
33
|
* deterministic (pass `now` in tests).
|
package/dist/src/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns raw Brain lessons into the two files `cachly export` writes: a
|
|
3
|
+
* human-readable Markdown dump and a machine-readable JSONL dump. Pure by
|
|
4
|
+
* design β no network, no filesystem. The `export` CLI command in index.ts
|
|
5
|
+
* fetches the lessons and writes the files these functions build.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* One lesson as exported from the Brain. Only `topic` is required β every
|
|
9
|
+
* other field is optional because not every lesson (or every API response)
|
|
10
|
+
* carries all of them, and a missing field must never crash the export.
|
|
11
|
+
*/
|
|
12
|
+
export interface ExportLesson {
|
|
13
|
+
topic: string;
|
|
14
|
+
outcome?: string;
|
|
15
|
+
severity?: string;
|
|
16
|
+
whatWorked?: string;
|
|
17
|
+
whatFailed?: string;
|
|
18
|
+
filePaths?: string[];
|
|
19
|
+
tags?: string[];
|
|
20
|
+
ts?: string;
|
|
21
|
+
author?: string;
|
|
22
|
+
recallCount?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds the human-readable Markdown dump: one `##` section per topic
|
|
26
|
+
* category (the part of `topic` before the first `:`, or "Ungrouped" when
|
|
27
|
+
* there is none), one `###` subsection per lesson listing outcome, severity,
|
|
28
|
+
* date and files. Never throws β an empty list renders a plain "no lessons
|
|
29
|
+
* yet" line instead of an empty document, and any text in a lesson (however
|
|
30
|
+
* unusual) is written as-is without breaking the surrounding structure.
|
|
31
|
+
*/
|
|
32
|
+
export declare function buildLessonsMarkdown(lessons: ExportLesson[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* Builds the machine-readable JSONL dump: one JSON object per line, one
|
|
35
|
+
* line per lesson, snake_case keys matching `learn_from_attempts` so the
|
|
36
|
+
* file can be grepped, jq'd or re-imported without a schema lookup. Fields
|
|
37
|
+
* that are absent on a lesson are simply omitted from its line. An empty
|
|
38
|
+
* list returns an empty string (a zero-line file), never throws.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildLessonsJsonl(lessons: ExportLesson[]): string;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns raw Brain lessons into the two files `cachly export` writes: a
|
|
3
|
+
* human-readable Markdown dump and a machine-readable JSONL dump. Pure by
|
|
4
|
+
* design β no network, no filesystem. The `export` CLI command in index.ts
|
|
5
|
+
* fetches the lessons and writes the files these functions build.
|
|
6
|
+
*/
|
|
7
|
+
const UNGROUPED_HEADING = 'Ungrouped';
|
|
8
|
+
function groupByCategory(lessons) {
|
|
9
|
+
const groups = new Map();
|
|
10
|
+
for (const lesson of lessons) {
|
|
11
|
+
const colonIdx = lesson.topic.indexOf(':');
|
|
12
|
+
const category = colonIdx > 0 ? lesson.topic.slice(0, colonIdx) : UNGROUPED_HEADING;
|
|
13
|
+
const bucket = groups.get(category);
|
|
14
|
+
if (bucket) {
|
|
15
|
+
bucket.push(lesson);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
groups.set(category, [lesson]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return groups;
|
|
22
|
+
}
|
|
23
|
+
function renderLesson(lesson) {
|
|
24
|
+
const fields = [];
|
|
25
|
+
if (lesson.outcome)
|
|
26
|
+
fields.push(`- **Outcome:** ${lesson.outcome}`);
|
|
27
|
+
if (lesson.severity)
|
|
28
|
+
fields.push(`- **Severity:** ${lesson.severity}`);
|
|
29
|
+
if (lesson.ts)
|
|
30
|
+
fields.push(`- **Date:** ${lesson.ts}`);
|
|
31
|
+
if (lesson.filePaths && lesson.filePaths.length > 0)
|
|
32
|
+
fields.push(`- **Files:** ${lesson.filePaths.join(', ')}`);
|
|
33
|
+
if (lesson.author)
|
|
34
|
+
fields.push(`- **Author:** ${lesson.author}`);
|
|
35
|
+
if (lesson.tags && lesson.tags.length > 0)
|
|
36
|
+
fields.push(`- **Tags:** ${lesson.tags.join(', ')}`);
|
|
37
|
+
const body = [];
|
|
38
|
+
if (lesson.whatWorked)
|
|
39
|
+
body.push(lesson.whatWorked);
|
|
40
|
+
if (lesson.whatFailed)
|
|
41
|
+
body.push(`**What failed:** ${lesson.whatFailed}`);
|
|
42
|
+
return [`### ${lesson.topic}`, '', ...fields, '', ...body].join('\n').trimEnd();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Builds the human-readable Markdown dump: one `##` section per topic
|
|
46
|
+
* category (the part of `topic` before the first `:`, or "Ungrouped" when
|
|
47
|
+
* there is none), one `###` subsection per lesson listing outcome, severity,
|
|
48
|
+
* date and files. Never throws β an empty list renders a plain "no lessons
|
|
49
|
+
* yet" line instead of an empty document, and any text in a lesson (however
|
|
50
|
+
* unusual) is written as-is without breaking the surrounding structure.
|
|
51
|
+
*/
|
|
52
|
+
export function buildLessonsMarkdown(lessons) {
|
|
53
|
+
if (lessons.length === 0) {
|
|
54
|
+
return '# Your Cachly Brain\n\nNo lessons yet β nothing to export.\n';
|
|
55
|
+
}
|
|
56
|
+
const groups = groupByCategory(lessons);
|
|
57
|
+
const categories = [...groups.keys()].sort((a, b) => a.localeCompare(b));
|
|
58
|
+
const sections = categories.map((category) => {
|
|
59
|
+
const entries = groups.get(category).map(renderLesson).join('\n\n');
|
|
60
|
+
return `## ${category}\n\n${entries}`;
|
|
61
|
+
});
|
|
62
|
+
const count = lessons.length;
|
|
63
|
+
const heading = `# Your Cachly Brain\n\n${count} lesson${count === 1 ? '' : 's'}, grouped by topic.`;
|
|
64
|
+
return [heading, ...sections].join('\n\n') + '\n';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Builds the machine-readable JSONL dump: one JSON object per line, one
|
|
68
|
+
* line per lesson, snake_case keys matching `learn_from_attempts` so the
|
|
69
|
+
* file can be grepped, jq'd or re-imported without a schema lookup. Fields
|
|
70
|
+
* that are absent on a lesson are simply omitted from its line. An empty
|
|
71
|
+
* list returns an empty string (a zero-line file), never throws.
|
|
72
|
+
*/
|
|
73
|
+
export function buildLessonsJsonl(lessons) {
|
|
74
|
+
if (lessons.length === 0)
|
|
75
|
+
return '';
|
|
76
|
+
return lessons.map((lesson) => JSON.stringify({
|
|
77
|
+
topic: lesson.topic,
|
|
78
|
+
outcome: lesson.outcome,
|
|
79
|
+
severity: lesson.severity,
|
|
80
|
+
what_worked: lesson.whatWorked,
|
|
81
|
+
what_failed: lesson.whatFailed,
|
|
82
|
+
file_paths: lesson.filePaths,
|
|
83
|
+
tags: lesson.tags,
|
|
84
|
+
ts: lesson.ts,
|
|
85
|
+
author: lesson.author,
|
|
86
|
+
recall_count: lesson.recallCount,
|
|
87
|
+
})).join('\n') + '\n';
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=brain-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-export.js","sourceRoot":"","sources":["../../src/brain-export.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Closed vocabulary for the `utm_source` tag on every cachly.dev link. A
|
|
3
|
+
* value here must name the actual place the click starts, never a guessed
|
|
4
|
+
* command β an entry point that is not on this list fails at the typecheck,
|
|
5
|
+
* not months later in Plausible.
|
|
6
|
+
*/
|
|
7
|
+
export type UrlQuelle =
|
|
8
|
+
/** `cachly setup` / `cachly autosetup` β the interactive onboarding wizard. */
|
|
9
|
+
'setup'
|
|
10
|
+
/** `cachly autopilot` β the same wizard, fully automatic, no prompts. */
|
|
11
|
+
| 'autopilot'
|
|
12
|
+
/** `cachly demo` β the zero-signup preview built from local git history. */
|
|
13
|
+
| 'demo'
|
|
14
|
+
/** `cachly health` β the quick inline credential/instance check. */
|
|
15
|
+
| 'health'
|
|
16
|
+
/** `cachly doctor` β the longer, step-by-step setup diagnosis. */
|
|
17
|
+
| 'doctor'
|
|
18
|
+
/** `cachly digest` β the weekly git-history summary. */
|
|
19
|
+
| 'digest'
|
|
20
|
+
/** `cachly invite` β the user's personal referral link. */
|
|
21
|
+
| 'invite'
|
|
22
|
+
/** `cachly join <token>` β redeeming a team invite. */
|
|
23
|
+
| 'join'
|
|
24
|
+
/** `cachly bench` β the recall-quality benchmark. */
|
|
25
|
+
| 'bench'
|
|
26
|
+
/** `cachly init` β manual config without the wizard. */
|
|
27
|
+
| 'init'
|
|
28
|
+
/** `cachly badge` β the embeddable README/lesson-count badge. */
|
|
29
|
+
| 'badge'
|
|
30
|
+
/** `cachly publish` β a public, importable Brain snapshot. */
|
|
31
|
+
| 'publish'
|
|
32
|
+
/** `cachly share` β the ASCII stats card + tweet text. */
|
|
33
|
+
| 'share'
|
|
34
|
+
/** A tier/feature-gate nudge β triggered by a limit, not by a command. */
|
|
35
|
+
| 'upgrade'
|
|
36
|
+
/** The `brain_briefing` tool's proactive risk warning. */
|
|
37
|
+
| 'briefing'
|
|
38
|
+
/** The `get_api_status` tool's inline diagnostic. */
|
|
39
|
+
| 'api-status'
|
|
40
|
+
/** Any tool call whose background instance turns out unreachable. */
|
|
41
|
+
| 'instance-error'
|
|
42
|
+
/** The silent device-flow sign-in a tool call starts when no JWT is set. */
|
|
43
|
+
| 'ambient-signin'
|
|
44
|
+
/** The shared, pure credential diagnosis in auth.ts, reused by many callers. */
|
|
45
|
+
| 'auth-diagnosis'
|
|
46
|
+
/** The zero-args welcome banner shown to a human with no credentials. */
|
|
47
|
+
| 'first-run'
|
|
48
|
+
/** The startup warning that an existing token is expired or expiring soon. */
|
|
49
|
+
| 'jwt-expiry'
|
|
50
|
+
/** The docs link inside the `cache_stats` tool's ROI report. */
|
|
51
|
+
| 'cache-stats'
|
|
52
|
+
/** The `brain_share` tool β publish a share-id snapshot. */
|
|
53
|
+
| 'brain-share'
|
|
54
|
+
/** The `brain_discover` tool β browse public Brains. */
|
|
55
|
+
| 'brain-discover'
|
|
56
|
+
/** The footer link in a generated README / editor-instructions file. */
|
|
57
|
+
| 'team-readme';
|
|
58
|
+
/**
|
|
59
|
+
* Builds a cachly.dev URL that carries a `utm_source` tag naming the place
|
|
60
|
+
* the click came from, so Plausible can group clicks instead of showing
|
|
61
|
+
* every visit as "direct".
|
|
62
|
+
*
|
|
63
|
+
* Pure: no network, no filesystem, no environment access. Existing query
|
|
64
|
+
* parts in `path` are preserved; an existing `utm_source` is replaced, never
|
|
65
|
+
* duplicated. `path` may include a path segment such as an instance ID β
|
|
66
|
+
* `source` must never be anything but a value from {@link UrlQuelle}.
|
|
67
|
+
*/
|
|
68
|
+
export declare function cachlyUrl(path: string, source: UrlQuelle): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const CACHLY_ORIGIN = 'https://cachly.dev';
|
|
2
|
+
/**
|
|
3
|
+
* Builds a cachly.dev URL that carries a `utm_source` tag naming the place
|
|
4
|
+
* the click came from, so Plausible can group clicks instead of showing
|
|
5
|
+
* every visit as "direct".
|
|
6
|
+
*
|
|
7
|
+
* Pure: no network, no filesystem, no environment access. Existing query
|
|
8
|
+
* parts in `path` are preserved; an existing `utm_source` is replaced, never
|
|
9
|
+
* duplicated. `path` may include a path segment such as an instance ID β
|
|
10
|
+
* `source` must never be anything but a value from {@link UrlQuelle}.
|
|
11
|
+
*/
|
|
12
|
+
export function cachlyUrl(path, source) {
|
|
13
|
+
const withSlash = path.startsWith('/') ? path : `/${path}`;
|
|
14
|
+
const questionMark = withSlash.indexOf('?');
|
|
15
|
+
const pathPart = questionMark === -1 ? withSlash : withSlash.slice(0, questionMark);
|
|
16
|
+
const queryPart = questionMark === -1 ? '' : withSlash.slice(questionMark + 1);
|
|
17
|
+
const params = new URLSearchParams(queryPart);
|
|
18
|
+
params.set('utm_source', source);
|
|
19
|
+
return `${CACHLY_ORIGIN}${pathPart}?${params.toString()}`;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=cachly-url.js.map
|