@cachly-dev/mcp-server 0.1.0
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/CHANGELOG.md +45 -0
- package/README.md +348 -0
- package/dist/__tests__/namespace.test.d.ts +1 -0
- package/dist/__tests__/namespace.test.js +114 -0
- package/dist/__tests__/namespace.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2879 -0
- package/dist/index.js.map +1 -0
- package/dist/namespace.d.ts +20 -0
- package/dist/namespace.js +128 -0
- package/dist/namespace.js.map +1 -0
- package/package.json +51 -0
- package/run-mcp.sh +57 -0
- package/src/__tests__/namespace.test.ts +126 -0
- package/src/index.ts +3327 -0
- package/src/namespace.ts +128 -0
- package/tsconfig.json +17 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog – cachly SDK (mcp)
|
|
2
|
+
|
|
3
|
+
**Language:** MCP (Model Context Protocol)
|
|
4
|
+
**Package:** `@cachly-dev/mcp` on **npm**
|
|
5
|
+
|
|
6
|
+
> Full cross-SDK release notes: [../CHANGELOG.md](../CHANGELOG.md)
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [0.2.0] – 2026-04-07
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Broken `index_project` tool schema – properties were accidentally placed outside the `TOOLS` array
|
|
15
|
+
- Unused `openai` variable removed from `cache_warmup` handler
|
|
16
|
+
- `readdir` type mismatch (`Dirent<string>` vs. `NonSharedBuffer`) fixed
|
|
17
|
+
- Version bumped to `0.3.0` in server metadata
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## [0.1.0] – 2026-04-07
|
|
22
|
+
|
|
23
|
+
Initial release.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- MCP tool: `cache_set` – store a value with optional TTL
|
|
28
|
+
- MCP tool: `cache_get` – retrieve a cached value
|
|
29
|
+
- MCP tool: `cache_delete` – remove a key
|
|
30
|
+
- MCP tool: `semantic_search` – vector-similarity lookup for LLM response caching
|
|
31
|
+
- MCP tool: `cache_clear` – flush namespace or entire cache
|
|
32
|
+
- Compatible with Claude Desktop, Cursor, Windsurf, and any MCP-capable host
|
|
33
|
+
- API-key-based authentication
|
|
34
|
+
- EU data residency (German servers, DSGVO compliant)
|
|
35
|
+
|
|
36
|
+
### Known limitations
|
|
37
|
+
|
|
38
|
+
- ~~Streaming tools not yet supported~~ (tracked for a future release)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## [Unreleased]
|
|
43
|
+
|
|
44
|
+
See [../CHANGELOG.md](../CHANGELOG.md) for upcoming features.
|
|
45
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# cachly MCP Server
|
|
2
|
+
|
|
3
|
+
> Manage your [cachly.dev](https://cachly.dev) cache instances directly from **GitHub Copilot, Claude, Cursor, Windsurf** and any other MCP-compatible AI assistant.
|
|
4
|
+
|
|
5
|
+
## 🚀 One-Click Setup for GitHub Copilot
|
|
6
|
+
|
|
7
|
+
Stop your AI from re-reading your entire codebase every time. One command enables **context memory**:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Create a free cachly instance at https://cachly.dev
|
|
11
|
+
# 2. Copy your JWT token from Settings
|
|
12
|
+
# 3. Add to .vscode/mcp.json:
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"servers": {
|
|
18
|
+
"cachly": {
|
|
19
|
+
"type": "stdio",
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "@cachly-dev/mcp-server"],
|
|
22
|
+
"env": {
|
|
23
|
+
"CACHLY_JWT": "your-jwt-token-here"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then add to `.github/copilot-instructions.md`:
|
|
31
|
+
|
|
32
|
+
```markdown
|
|
33
|
+
## Cachly AI Brain
|
|
34
|
+
|
|
35
|
+
At the START of every session — single call:
|
|
36
|
+
session_start(instance_id = "<your-instance-id>", focus = "<what you're working on>")
|
|
37
|
+
|
|
38
|
+
At the END of every session:
|
|
39
|
+
session_end(instance_id = "<your-instance-id>", summary = "...", files_changed = [...])
|
|
40
|
+
|
|
41
|
+
After any bug fix or deploy:
|
|
42
|
+
learn_from_attempts(instance_id = "<your-instance-id>", topic = "category:keyword",
|
|
43
|
+
outcome = "success", what_worked = "...", what_failed = "...", severity = "major")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Result:** 60% fewer file reads, instant context across sessions, zero re-discovery.
|
|
47
|
+
|
|
48
|
+
## What you can do
|
|
49
|
+
|
|
50
|
+
Once connected, just talk to your AI assistant:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
"Create a free cachly instance called my-app-cache"
|
|
54
|
+
"List all my cache instances"
|
|
55
|
+
"Get the connection string for instance abc-123"
|
|
56
|
+
"Delete my test-cache instance"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Available Tools
|
|
60
|
+
|
|
61
|
+
### 🧠 AI Brain — Session & Memory
|
|
62
|
+
|
|
63
|
+
| Tool | Description |
|
|
64
|
+
|---|---|
|
|
65
|
+
| **`session_start`** | Single call returning full briefing: last session, relevant lessons, open failures, brain health. Call at the start of every session. |
|
|
66
|
+
| **`session_end`** | Save session summary, files changed, duration. Call at the end of every session. |
|
|
67
|
+
| **`learn_from_attempts`** | Store structured lessons after any bug fix or deploy. Supports severity, file_paths, commands, tags. Deduplicates by topic. |
|
|
68
|
+
| **`recall_best_solution`** | Retrieve the best known solution for a topic (increments recall count). |
|
|
69
|
+
| **`remember_context`** | Cache any analysis or architecture finding for future sessions. |
|
|
70
|
+
| **`recall_context`** | Retrieve cached context by exact key (supports glob: `"file:*"`). |
|
|
71
|
+
| **`smart_recall`** | Semantic search across all cached context by meaning/keywords. |
|
|
72
|
+
| **`list_remembered`** | List all cached context entries. |
|
|
73
|
+
| **`forget_context`** | Delete stale context. |
|
|
74
|
+
|
|
75
|
+
### ⚙️ Instance Management
|
|
76
|
+
|
|
77
|
+
| Tool | Description |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `list_instances` | List all your cache instances |
|
|
80
|
+
| `create_instance` | Create a new instance (free or paid tier) |
|
|
81
|
+
| `get_instance` | Get details for a specific instance |
|
|
82
|
+
| `get_connection_string` | Get the `redis://` connection URL |
|
|
83
|
+
| `delete_instance` | Permanently delete an instance |
|
|
84
|
+
|
|
85
|
+
### 🗄️ Cache Operations
|
|
86
|
+
|
|
87
|
+
| Tool | Description |
|
|
88
|
+
|---|---|
|
|
89
|
+
| `cache_get` / `cache_set` / `cache_delete` | Live cache operations |
|
|
90
|
+
| `cache_exists` / `cache_ttl` / `cache_keys` | Key inspection |
|
|
91
|
+
| `cache_stats` | Memory, hit rate, ops/sec |
|
|
92
|
+
| `cache_mget` / `cache_mset` | Bulk pipeline operations |
|
|
93
|
+
| `cache_lock_acquire` / `cache_lock_release` | Distributed locks (Redlock-lite) |
|
|
94
|
+
| `cache_stream_set` / `cache_stream_get` | LLM token streaming cache |
|
|
95
|
+
|
|
96
|
+
### 🔍 Semantic & AI
|
|
97
|
+
|
|
98
|
+
| Tool | Description |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `semantic_search` | Vector similarity search (Speed/Business tier) |
|
|
101
|
+
| `detect_namespace` | Auto-classify prompt into semantic namespace |
|
|
102
|
+
| `cache_warmup` | Pre-warm semantic cache with known Q&A pairs |
|
|
103
|
+
| `index_project` | Index local source files for AI semantic search |
|
|
104
|
+
| `get_api_status` | Check API health + JWT auth info |
|
|
105
|
+
|
|
106
|
+
## Setup
|
|
107
|
+
|
|
108
|
+
### 1. Build
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm install
|
|
112
|
+
npm run build
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### 2. Get your API token
|
|
116
|
+
|
|
117
|
+
Go to **[cachly.dev/settings](https://cachly.dev/settings)** → API Tokens → Generate token.
|
|
118
|
+
|
|
119
|
+
### 3. Configure your AI client
|
|
120
|
+
|
|
121
|
+
#### GitHub Copilot (VS Code)
|
|
122
|
+
|
|
123
|
+
Add to `.vscode/mcp.json` in your project (or global user settings):
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"servers": {
|
|
128
|
+
"cachly": {
|
|
129
|
+
"type": "stdio",
|
|
130
|
+
"command": "node",
|
|
131
|
+
"args": ["/absolute/path/to/sdk/mcp/dist/index.js"],
|
|
132
|
+
"env": {
|
|
133
|
+
"CACHLY_JWT": "your-jwt-token-here",
|
|
134
|
+
"CACHLY_API_URL": "https://api.cachly.dev"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Then in VS Code: **Ctrl/Cmd+Shift+P → "MCP: List Servers"** → start `cachly`.
|
|
142
|
+
|
|
143
|
+
#### Claude Desktop
|
|
144
|
+
|
|
145
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"mcpServers": {
|
|
150
|
+
"cachly": {
|
|
151
|
+
"command": "node",
|
|
152
|
+
"args": ["/absolute/path/to/sdk/mcp/dist/index.js"],
|
|
153
|
+
"env": {
|
|
154
|
+
"CACHLY_JWT": "your-jwt-token-here"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Cursor / Windsurf / Continue.dev
|
|
162
|
+
|
|
163
|
+
Add to their respective MCP config (same `stdio` format as above).
|
|
164
|
+
|
|
165
|
+
#### Via npx (no local build needed, once published to npm)
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"command": "npx",
|
|
170
|
+
"args": ["-y", "@cachly-dev/mcp-server"],
|
|
171
|
+
"env": { "CACHLY_JWT": "your-token" }
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Environment Variables
|
|
176
|
+
|
|
177
|
+
| Variable | Required | Default | Description |
|
|
178
|
+
|---|---|---|---|
|
|
179
|
+
| `CACHLY_JWT` | ✅ | – | Your Keycloak JWT from cachly.dev/settings |
|
|
180
|
+
| `CACHLY_API_URL` | ❌ | `https://api.cachly.dev` | Override for local dev |
|
|
181
|
+
|
|
182
|
+
## Example Session
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
User: Create a free cache instance for my OpenAI project
|
|
186
|
+
|
|
187
|
+
Copilot: I'll create a free cachly instance for you.
|
|
188
|
+
[calls create_instance(name="openai-cache", tier="free")]
|
|
189
|
+
|
|
190
|
+
✅ Instance **openai-cache** (FREE) created and provisioning started!
|
|
191
|
+
ID: `a1b2c3d4-...`
|
|
192
|
+
Status: provisioning
|
|
193
|
+
|
|
194
|
+
Use `get_connection_string` to get your Redis URL in ~30 seconds.
|
|
195
|
+
|
|
196
|
+
User: Get the connection string
|
|
197
|
+
|
|
198
|
+
Copilot: [calls get_connection_string(instance_id="a1b2c3d4-...")]
|
|
199
|
+
|
|
200
|
+
Connection string for openai-cache:
|
|
201
|
+
redis://:password@my-node.cachly.dev:30101
|
|
202
|
+
|
|
203
|
+
Environment variable:
|
|
204
|
+
REDIS_URL="redis://:password@my-node.cachly.dev:30101"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Local Development
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Run against local API
|
|
211
|
+
CACHLY_JWT=your-token CACHLY_API_URL=http://localhost:3001 npm run dev
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Real-World Use Cases
|
|
217
|
+
|
|
218
|
+
### 🧠 Stop Re-Reading Your Codebase — "Thinking Cache"
|
|
219
|
+
|
|
220
|
+
**The Problem:** Every time you ask Copilot about your codebase, it runs "Ich verschaffe mir einen Überblick über die Codebasis" and re-reads hundreds of files.
|
|
221
|
+
|
|
222
|
+
**The Solution:** Cache your AI's "thinking" results:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
You: "Analyze the authentication architecture"
|
|
226
|
+
AI: [reads 47 files, takes 30 seconds]
|
|
227
|
+
The auth uses Keycloak with JWT tokens. The flow is:
|
|
228
|
+
1. User hits /sign-in → NextAuth redirect
|
|
229
|
+
2. Keycloak validates credentials
|
|
230
|
+
3. JWT returned, stored in session
|
|
231
|
+
|
|
232
|
+
[calls remember_context("auth_architecture", "The auth uses Keycloak...")]
|
|
233
|
+
🧠 Context saved for future sessions.
|
|
234
|
+
|
|
235
|
+
--- Next day, new session ---
|
|
236
|
+
|
|
237
|
+
You: "How does auth work?"
|
|
238
|
+
AI: [calls smart_recall("auth")]
|
|
239
|
+
🧠 Found cached context:
|
|
240
|
+
The auth uses Keycloak with JWT tokens...
|
|
241
|
+
|
|
242
|
+
(No file reading needed — instant answer!)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Setup in 2 minutes:**
|
|
246
|
+
|
|
247
|
+
1. Add to `.github/copilot-instructions.md` (or `CLAUDE.md` for Claude Code):
|
|
248
|
+
```markdown
|
|
249
|
+
## Cachly AI Brain
|
|
250
|
+
|
|
251
|
+
At the START of every session:
|
|
252
|
+
session_start(instance_id = "<id>", focus = "<what you plan to work on>")
|
|
253
|
+
|
|
254
|
+
At the END of every session:
|
|
255
|
+
session_end(instance_id = "<id>", summary = "...", files_changed = [...])
|
|
256
|
+
|
|
257
|
+
After any bug fix: learn_from_attempts(instance_id = "<id>", topic = "category:keyword",
|
|
258
|
+
outcome = "success", what_worked = "...", severity = "major")
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
2. From now on: your AI calls `session_start` first and never re-reads what it already knows.
|
|
262
|
+
|
|
263
|
+
### 1. AI-Assisted Development — "Which caches am I using?"
|
|
264
|
+
|
|
265
|
+
You're building a microservice that uses multiple cachly instances. Ask your AI assistant directly:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
You: "List all my cachly instances and their status"
|
|
269
|
+
AI: Using cachly_list_instances...
|
|
270
|
+
|
|
271
|
+
You have 3 instances:
|
|
272
|
+
1. prod-api (Pro, running) — redis://:***@prod.cachly.dev:30101
|
|
273
|
+
2. staging (Dev, running) — redis://:***@staging.cachly.dev:30102
|
|
274
|
+
3. ml-pipeline (Speed, running) — redis://:***@ml.cachly.dev:30103
|
|
275
|
+
|
|
276
|
+
Total MRR: €72/month
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### 2. Cache Debugging — "Why is my hit rate dropping?"
|
|
280
|
+
|
|
281
|
+
Your semantic cache hit rate dropped overnight. Debug it without leaving your editor:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
You: "Check the analytics for my prod-api instance"
|
|
285
|
+
AI: Using cachly_semantic_stats...
|
|
286
|
+
|
|
287
|
+
⚠️ Hit rate dropped 23% in the last 24h (82% → 63%)
|
|
288
|
+
|
|
289
|
+
Anomaly detected: near-miss spike (+140%)
|
|
290
|
+
→ 47 queries are hitting similarity 0.80-0.84 (just below your 0.85 threshold)
|
|
291
|
+
|
|
292
|
+
Recommendation: Lower threshold to 0.82 to capture these near-misses.
|
|
293
|
+
|
|
294
|
+
You: "Do it"
|
|
295
|
+
AI: Using cachly_set_threshold... ✅ Threshold set to 0.82 for namespace cachly:sem
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 3. Deployment Cache Warmup — "Pre-fill the cache for the new release"
|
|
299
|
+
|
|
300
|
+
After deploying a new version, warm the semantic cache with common queries:
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
You: "Warm up the staging cache with our top 50 support questions"
|
|
304
|
+
AI: Using cachly_batch_index with your FAQ embeddings...
|
|
305
|
+
|
|
306
|
+
✅ Indexed 50 entries in 340ms (batch pipeline)
|
|
307
|
+
Namespace: cachly:sem:qa
|
|
308
|
+
|
|
309
|
+
Your cache is ready — first users will get instant responses.
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 4. Cost Monitoring — "How much am I saving?"
|
|
313
|
+
|
|
314
|
+
Track your LLM cost savings directly in your IDE:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
You: "How much has cachly saved me this month?"
|
|
318
|
+
AI: Using cachly_semantic_stats...
|
|
319
|
+
|
|
320
|
+
📊 This month's savings:
|
|
321
|
+
- Total cache hits: 12,847
|
|
322
|
+
- Estimated savings: $384.21 (vs. direct LLM calls)
|
|
323
|
+
- Efficiency score: 84/100 (Grade: A)
|
|
324
|
+
- Best namespace: cachly:sem:qa (94% hit rate)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### 5. CI Pipeline Integration — "Check cache health before deploy"
|
|
328
|
+
|
|
329
|
+
Add cache health checks to your deployment workflow:
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
You: "Check if any cache anomalies would block a deploy"
|
|
333
|
+
AI: Using cachly_analytics_anomalies...
|
|
334
|
+
|
|
335
|
+
✅ No critical anomalies detected.
|
|
336
|
+
1 info-level notice: stale cache in namespace "translations"
|
|
337
|
+
(12 near-misses/24h, 0 new entries)
|
|
338
|
+
|
|
339
|
+
Recommendation: Run warmup after deploy for translations namespace.
|
|
340
|
+
Deploy is safe to proceed.
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## License
|
|
346
|
+
|
|
347
|
+
MIT © [cachly.dev](https://cachly.dev)
|
|
348
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { detectNamespace } from '../namespace.js';
|
|
3
|
+
// ── Namespace Auto-Detection ───────────────────────────────────────────────
|
|
4
|
+
describe('detectNamespace', () => {
|
|
5
|
+
// ── Code ────────────────────────────────────────────────────────────────────
|
|
6
|
+
describe('code detection', () => {
|
|
7
|
+
it.each([
|
|
8
|
+
['python def', 'def process(data): return data * 2'],
|
|
9
|
+
['js const arrow', 'const handler = () => response.send(200)'],
|
|
10
|
+
['ts class', 'class UserService { constructor(private repo: Repo) {} }'],
|
|
11
|
+
['import statement', 'import { useState } from "react"'],
|
|
12
|
+
['shebang line', '#!/usr/bin/env python3\nprint("hello")'],
|
|
13
|
+
['go func', 'func main() { fmt.Println("hello") }'],
|
|
14
|
+
['cpp include', '#include <iostream>\nint main() { return 0; }'],
|
|
15
|
+
['interface block', 'interface ICache { get(key: string): void; }'],
|
|
16
|
+
['struct block', 'struct Config { host string }'],
|
|
17
|
+
['async def', 'async def fetch_data(url: str) -> dict:'],
|
|
18
|
+
['lambda', 'fn = lambda x: x * 2'],
|
|
19
|
+
['package decl', 'package com.example.service;'],
|
|
20
|
+
])('detects code: %s', (_, prompt) => {
|
|
21
|
+
expect(detectNamespace(prompt)).toBe('cachly:sem:code');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
// ── Translation ─────────────────────────────────────────────────────────────
|
|
25
|
+
describe('translation detection', () => {
|
|
26
|
+
it.each([
|
|
27
|
+
['translate', 'translate this paragraph to Spanish'],
|
|
28
|
+
['übersetze', 'übersetze diesen Text bitte'],
|
|
29
|
+
['auf deutsch', 'Schreib das auf deutsch'],
|
|
30
|
+
['in english', 'Please write this in english'],
|
|
31
|
+
['ins deutsche', 'Bitte übersetze ins Deutsche'],
|
|
32
|
+
['traduce', 'traduce este texto al alemán'],
|
|
33
|
+
['traduis', 'traduis ce texte en anglais'],
|
|
34
|
+
['vertaal', 'vertaal dit naar het Nederlands'],
|
|
35
|
+
])('detects translation: %s', (_, prompt) => {
|
|
36
|
+
expect(detectNamespace(prompt)).toBe('cachly:sem:translation');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
// ── Summary ──────────────────────────────────────────────────────────────────
|
|
40
|
+
describe('summary detection', () => {
|
|
41
|
+
it.each([
|
|
42
|
+
['summarize', 'summarize this article for me'],
|
|
43
|
+
['summarise', 'summarise the key points'],
|
|
44
|
+
['tl;dr', 'tl;dr of the following blog post:'],
|
|
45
|
+
['tldr', 'tldr of this document'],
|
|
46
|
+
['key points', 'what are the key points?'],
|
|
47
|
+
['zusammenfass', 'fasse zusammen worum es geht'],
|
|
48
|
+
['give me a brief', 'give me a brief overview'],
|
|
49
|
+
['in a nutshell', 'explain machine learning in a nutshell'],
|
|
50
|
+
['stichpunkte', 'Gib mir die wichtigsten Stichpunkte'],
|
|
51
|
+
])('detects summary: %s', (_, prompt) => {
|
|
52
|
+
expect(detectNamespace(prompt)).toBe('cachly:sem:summary');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
// ── Q&A ──────────────────────────────────────────────────────────────────────
|
|
56
|
+
describe('qa detection', () => {
|
|
57
|
+
it.each([
|
|
58
|
+
['what is', 'what is the capital of France?'],
|
|
59
|
+
['how does', 'how does photosynthesis work?'],
|
|
60
|
+
['why is', 'why is the sky blue?'],
|
|
61
|
+
['who invented', 'who invented the internet?'],
|
|
62
|
+
['where is', 'where is Mount Everest located?'],
|
|
63
|
+
['when was', 'when was the Eiffel Tower built?'],
|
|
64
|
+
['can you', 'can you explain recursion?'],
|
|
65
|
+
['is redis', 'is Redis single-threaded?'],
|
|
66
|
+
['does postgres', 'does postgres support JSON natively?'],
|
|
67
|
+
['wer ist', 'wer ist der aktuelle Bundeskanzler?'],
|
|
68
|
+
['wie funktioniert', 'wie funktioniert ein JWT Token?'],
|
|
69
|
+
['trailing ?', 'Redis vs Memcached?'],
|
|
70
|
+
])('detects q&a: %s', (_, prompt) => {
|
|
71
|
+
expect(detectNamespace(prompt)).toBe('cachly:sem:qa');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
// ── Creative ─────────────────────────────────────────────────────────────────
|
|
75
|
+
describe('creative fallback', () => {
|
|
76
|
+
it.each([
|
|
77
|
+
['poem request', 'Write a short poem about autumn leaves'],
|
|
78
|
+
['story request', 'Tell me a fantasy story about dragons'],
|
|
79
|
+
['product copy', 'Generate a product description for running shoes'],
|
|
80
|
+
['greeting', 'Good morning, how are you today'],
|
|
81
|
+
['general task', 'Help me brainstorm names for my startup'],
|
|
82
|
+
])('falls back to creative: %s', (_, prompt) => {
|
|
83
|
+
expect(detectNamespace(prompt)).toBe('cachly:sem:creative');
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
// ── Edge cases ────────────────────────────────────────────────────────────────
|
|
87
|
+
describe('edge cases', () => {
|
|
88
|
+
it('is case-insensitive', () => {
|
|
89
|
+
expect(detectNamespace('CONST x = 1')).toBe('cachly:sem:code');
|
|
90
|
+
expect(detectNamespace('TRANSLATE THIS')).toBe('cachly:sem:translation');
|
|
91
|
+
expect(detectNamespace('SUMMARIZE PLEASE')).toBe('cachly:sem:summary');
|
|
92
|
+
expect(detectNamespace('WHAT IS GRAVITY?')).toBe('cachly:sem:qa');
|
|
93
|
+
});
|
|
94
|
+
it('trims surrounding whitespace', () => {
|
|
95
|
+
expect(detectNamespace(' what is Redis? ')).toBe('cachly:sem:qa');
|
|
96
|
+
expect(detectNamespace(' const x = 1 ')).toBe('cachly:sem:code');
|
|
97
|
+
});
|
|
98
|
+
it('code keyword takes priority over translation', () => {
|
|
99
|
+
// Both "translate" and "def" present – code wins (checked first)
|
|
100
|
+
expect(detectNamespace('translate this function: def foo(): pass')).toBe('cachly:sem:code');
|
|
101
|
+
});
|
|
102
|
+
it('code keyword takes priority over summary', () => {
|
|
103
|
+
expect(detectNamespace('summarize this class MyService { }'))
|
|
104
|
+
.toBe('cachly:sem:code');
|
|
105
|
+
});
|
|
106
|
+
it('handles empty string as creative', () => {
|
|
107
|
+
expect(detectNamespace('')).toBe('cachly:sem:creative');
|
|
108
|
+
});
|
|
109
|
+
it('a single ? at end is qa', () => {
|
|
110
|
+
expect(detectNamespace('Interesting concept?')).toBe('cachly:sem:qa');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=namespace.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace.test.js","sourceRoot":"","sources":["../../src/__tests__/namespace.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED