lynkr 2.0.0 → 3.0.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/README.md +226 -15
- package/docs/index.md +230 -11
- package/install.sh +260 -0
- package/package.json +4 -3
- package/src/clients/databricks.js +158 -0
- package/src/clients/routing.js +13 -1
- package/src/config/index.js +68 -1
- package/src/db/index.js +118 -0
- package/src/memory/extractor.js +350 -0
- package/src/memory/index.js +55 -0
- package/src/memory/retriever.js +266 -0
- package/src/memory/search.js +239 -0
- package/src/memory/store.js +411 -0
- package/src/memory/surprise.js +306 -0
- package/src/memory/tools.js +348 -0
- package/src/orchestrator/index.js +170 -0
- package/test/llamacpp-integration.test.js +686 -0
- package/test/memory/extractor.test.js +360 -0
- package/test/memory/retriever.test.js +583 -0
- package/test/memory/search.test.js +389 -0
- package/test/memory/store.test.js +312 -0
- package/test/memory/surprise.test.js +300 -0
- package/test/memory-performance.test.js +472 -0
- package/test/openai-integration.test.js +681 -0
package/docs/index.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
# Lynkr – Claude Code-Compatible Proxy for Databricks
|
|
8
|
-
#### Lynkr is an open-source Claude Code-compatible proxy that allows the Claude Code CLI to run directly with
|
|
8
|
+
#### Lynkr is an open-source Claude Code-compatible proxy that allows the Claude Code CLI to run directly with any LLMs without losing the features offered by Anthropic backend. It supports MCP servers, Git workflows, repo intelligence, workspace tools, prompt caching for LLM-powered development and many other features.
|
|
9
9
|
<!--
|
|
10
10
|
SEO Keywords:
|
|
11
11
|
Databricks, Claude Code, Anthropic, Azure Anthropic,
|
|
@@ -18,7 +18,6 @@ prompt caching, Node.js
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
# Lynkr
|
|
21
|
-
### Claude Code-Compatible Proxy for Databricks & Azure Anthropic Models
|
|
22
21
|
**MCP • Git Tools • Repo Intelligence • Prompt Caching • Workspace Automation**
|
|
23
22
|
|
|
24
23
|
[⭐ Star on GitHub](https://github.com/vishalveerareddy123/Lynkr) ·
|
|
@@ -58,9 +57,15 @@ Supports **Databricks-hosted Claude Sonnet / Haiku models**, or any LLM served f
|
|
|
58
57
|
### ✔ Supports Azure Anthropic models
|
|
59
58
|
Route Claude Code requests into Azure's `/anthropic/v1/messages` endpoint.
|
|
60
59
|
|
|
60
|
+
### ✔ Supports Azure OpenAI models
|
|
61
|
+
Connect to Azure OpenAI deployments (GPT-4o, etc.) with full tool calling support.
|
|
62
|
+
|
|
61
63
|
### ✔ Supports OpenRouter (100+ models)
|
|
62
64
|
Access GPT-4o, Claude, Gemini, Llama, and more through a single unified API with full tool calling support.
|
|
63
65
|
|
|
66
|
+
### ✔ Supports llama.cpp (Local GGUF Models)
|
|
67
|
+
Run any GGUF model locally with maximum performance using llama.cpp's optimized C++ inference engine.
|
|
68
|
+
|
|
64
69
|
### ✔ Full Model Context Protocol (MCP) integration
|
|
65
70
|
Auto-discovers MCP manifests and exposes them as tools for smart workflows.
|
|
66
71
|
|
|
@@ -79,6 +84,9 @@ Task tracker, file I/O, test runner, index rebuild, etc.
|
|
|
79
84
|
### ✔ Client-Side Tool Execution (Passthrough Mode)
|
|
80
85
|
Tools can execute on the Claude Code CLI side instead of the server, enabling local file operations and commands.
|
|
81
86
|
|
|
87
|
+
### ✔ Titans-Inspired Long-Term Memory System
|
|
88
|
+
Automatic extraction and retrieval of conversation memories using surprise-based filtering, FTS5 semantic search, and multi-signal ranking.
|
|
89
|
+
|
|
82
90
|
### ✔ Fully extensible Node.js architecture
|
|
83
91
|
Add custom tools, policies, or backend adapters.
|
|
84
92
|
|
|
@@ -92,11 +100,13 @@ Add custom tools, policies, or backend adapters.
|
|
|
92
100
|
- [Configuring Providers (Databricks & Azure Anthropic)](#-configuring-providers)
|
|
93
101
|
- [Using Lynkr With Claude Code CLI](#-using-lynkr-with-claude-code-cli)
|
|
94
102
|
- [Repo Intelligence & Indexing](#-repo-intelligence--indexing)
|
|
103
|
+
- [Long-Term Memory System (Titans-Inspired)](#-long-term-memory-system-titans-inspired)
|
|
95
104
|
- [Prompt Caching](#-prompt-caching)
|
|
96
105
|
- [MCP (Model Context Protocol) Integration](#-model-context-protocol-mcp)
|
|
97
106
|
- [Git Tools](#-git-tools)
|
|
98
107
|
- [Client-Side Tool Execution (Passthrough Mode)](#-client-side-tool-execution-passthrough-mode)
|
|
99
108
|
- [API Examples](#-api-examples)
|
|
109
|
+
- [ACE Framework Working Nature](#-ace-framework-working-nature)
|
|
100
110
|
- [Roadmap](#-roadmap)
|
|
101
111
|
- [Links](#-links)
|
|
102
112
|
|
|
@@ -123,7 +133,7 @@ Claude Code CLI
|
|
|
123
133
|
↓
|
|
124
134
|
Lynkr Proxy
|
|
125
135
|
↓
|
|
126
|
-
Databricks / Azure Anthropic / MCP / Tools
|
|
136
|
+
Databricks / Azure Anthropic / OpenRouter / Ollama / llama.cpp / MCP / Tools
|
|
127
137
|
|
|
128
138
|
```
|
|
129
139
|
|
|
@@ -148,6 +158,7 @@ Lynkr Proxy (Node.js + Express)
|
|
|
148
158
|
────────────────────────────────────────
|
|
149
159
|
│ Orchestrator (Agent Loop) │
|
|
150
160
|
│ ├─ Tool Execution Pipeline │
|
|
161
|
+
│ ├─ Long-Term Memory System │
|
|
151
162
|
│ ├─ MCP Registry + Sandbox │
|
|
152
163
|
│ ├─ Prompt Cache (LRU + TTL) │
|
|
153
164
|
│ ├─ Session Store (SQLite) │
|
|
@@ -155,17 +166,18 @@ Lynkr Proxy (Node.js + Express)
|
|
|
155
166
|
│ ├─ Policy Engine │
|
|
156
167
|
────────────────────────────────────────
|
|
157
168
|
↓
|
|
158
|
-
Databricks / Azure Anthropic /
|
|
169
|
+
Databricks / Azure Anthropic / OpenRouter / Ollama / llama.cpp
|
|
159
170
|
|
|
160
171
|
````
|
|
161
172
|
|
|
162
173
|
Key directories:
|
|
163
174
|
|
|
164
|
-
- `src/api` → Claude-compatible API proxy
|
|
165
|
-
- `src/orchestrator` → LLM agent runtime loop
|
|
166
|
-
- `src/
|
|
167
|
-
- `src/
|
|
168
|
-
- `src/
|
|
175
|
+
- `src/api` → Claude-compatible API proxy
|
|
176
|
+
- `src/orchestrator` → LLM agent runtime loop
|
|
177
|
+
- `src/memory` → Long-term memory system (Titans-inspired)
|
|
178
|
+
- `src/mcp` → Model Context Protocol tooling
|
|
179
|
+
- `src/tools` → Git, diff, test, tasks, fs tools
|
|
180
|
+
- `src/cache` → prompt caching backend
|
|
169
181
|
- `src/indexer` → repo intelligence
|
|
170
182
|
|
|
171
183
|
---
|
|
@@ -220,6 +232,17 @@ WORKSPACE_ROOT=/path/to/repo
|
|
|
220
232
|
PORT=8080
|
|
221
233
|
```
|
|
222
234
|
|
|
235
|
+
## Azure OpenAI Setup
|
|
236
|
+
|
|
237
|
+
```env
|
|
238
|
+
MODEL_PROVIDER=azure-openai
|
|
239
|
+
AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com
|
|
240
|
+
AZURE_OPENAI_API_KEY=<api-key>
|
|
241
|
+
AZURE_OPENAI_DEPLOYMENT=gpt-4o
|
|
242
|
+
PORT=8080
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
|
|
223
246
|
## OpenRouter Setup
|
|
224
247
|
|
|
225
248
|
**What is OpenRouter?**
|
|
@@ -257,6 +280,59 @@ See [https://openrouter.ai/models](https://openrouter.ai/models) for complete li
|
|
|
257
280
|
4. Add credits (minimum $5)
|
|
258
281
|
5. Configure Lynkr as shown above
|
|
259
282
|
|
|
283
|
+
## llama.cpp Setup
|
|
284
|
+
|
|
285
|
+
**What is llama.cpp?**
|
|
286
|
+
|
|
287
|
+
llama.cpp is a high-performance C++ inference engine for running GGUF models locally. Benefits:
|
|
288
|
+
- ✅ **Maximum performance** – Optimized C++ inference
|
|
289
|
+
- ✅ **Any GGUF model** – Run any model from HuggingFace
|
|
290
|
+
- ✅ **Lower memory usage** – Advanced quantization options (Q2_K to Q8_0)
|
|
291
|
+
- ✅ **Multi-GPU support** – CUDA, Metal, ROCm, Vulkan
|
|
292
|
+
- ✅ **OpenAI-compatible API** – Seamless integration
|
|
293
|
+
- ✅ **Full tool calling** – Grammar-based, reliable
|
|
294
|
+
|
|
295
|
+
**Configuration:**
|
|
296
|
+
|
|
297
|
+
```env
|
|
298
|
+
MODEL_PROVIDER=llamacpp
|
|
299
|
+
LLAMACPP_ENDPOINT=http://localhost:8080 # llama-server default port
|
|
300
|
+
LLAMACPP_MODEL=qwen2.5-coder-7b # Model name (for logging)
|
|
301
|
+
LLAMACPP_TIMEOUT_MS=120000 # Request timeout
|
|
302
|
+
PORT=8080
|
|
303
|
+
WORKSPACE_ROOT=/path/to/your/repo
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Setup Steps:**
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# 1. Build llama.cpp (or download pre-built binary)
|
|
310
|
+
git clone https://github.com/ggerganov/llama.cpp
|
|
311
|
+
cd llama.cpp && make
|
|
312
|
+
|
|
313
|
+
# 2. Download a GGUF model (example: Qwen2.5-Coder)
|
|
314
|
+
wget https://huggingface.co/Qwen/Qwen2.5-Coder-7B-Instruct-GGUF/resolve/main/qwen2.5-coder-7b-instruct-q4_k_m.gguf
|
|
315
|
+
|
|
316
|
+
# 3. Start llama-server
|
|
317
|
+
./llama-server -m qwen2.5-coder-7b-instruct-q4_k_m.gguf --port 8080
|
|
318
|
+
|
|
319
|
+
# 4. Verify server is running
|
|
320
|
+
curl http://localhost:8080/health
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**llama.cpp vs Ollama:**
|
|
324
|
+
|
|
325
|
+
| Feature | Ollama | llama.cpp |
|
|
326
|
+
|---------|--------|-----------|
|
|
327
|
+
| Setup | Easy (app) | Manual (compile/download) |
|
|
328
|
+
| Model Format | Ollama-specific | Any GGUF model |
|
|
329
|
+
| Performance | Good | Excellent |
|
|
330
|
+
| Memory Usage | Higher | Lower (quantization) |
|
|
331
|
+
| API | Custom | OpenAI-compatible |
|
|
332
|
+
| Flexibility | Limited models | Any GGUF from HuggingFace |
|
|
333
|
+
|
|
334
|
+
Choose llama.cpp when you need maximum performance, specific quantization options, or GGUF models not available in Ollama.
|
|
335
|
+
|
|
260
336
|
---
|
|
261
337
|
|
|
262
338
|
# 💬 Using Lynkr With Claude Code CLI
|
|
@@ -275,7 +351,7 @@ claude review
|
|
|
275
351
|
claude apply
|
|
276
352
|
```
|
|
277
353
|
|
|
278
|
-
Everything routes through your Databricks or
|
|
354
|
+
Everything routes through your configured model provider (Databricks, Azure, OpenRouter, Ollama, or llama.cpp).
|
|
279
355
|
|
|
280
356
|
---
|
|
281
357
|
|
|
@@ -294,6 +370,121 @@ It generates a structured `CLAUDE.md` so the model always has context.
|
|
|
294
370
|
|
|
295
371
|
---
|
|
296
372
|
|
|
373
|
+
# 🧠 Long-Term Memory System (Titans-Inspired)
|
|
374
|
+
|
|
375
|
+
Lynkr includes a sophisticated long-term memory system inspired by Google's Titans architecture, enabling persistent learning across conversations without model retraining.
|
|
376
|
+
|
|
377
|
+
## How It Works
|
|
378
|
+
|
|
379
|
+
The memory system automatically:
|
|
380
|
+
|
|
381
|
+
1. **Extracts** important information from conversations (preferences, decisions, facts, entities, relationships)
|
|
382
|
+
2. **Filters** using surprise-based scoring to store only novel/important information
|
|
383
|
+
3. **Retrieves** relevant memories using multi-signal ranking (recency + importance + relevance)
|
|
384
|
+
4. **Injects** top memories into each request for contextual continuity
|
|
385
|
+
|
|
386
|
+
## Key Features
|
|
387
|
+
|
|
388
|
+
### 🎯 Surprise-Based Memory Updates (Titans Core Innovation)
|
|
389
|
+
|
|
390
|
+
Memories are scored 0.0-1.0 based on five factors:
|
|
391
|
+
- **Novelty** (30%): New entities/concepts not seen before
|
|
392
|
+
- **Contradiction** (40%): Conflicts with existing memories
|
|
393
|
+
- **Specificity** (15%): Level of detail and technical depth
|
|
394
|
+
- **User Emphasis** (10%): Explicit emphasis markers (IMPORTANT, CRITICAL, etc.)
|
|
395
|
+
- **Context Switch** (5%): Topic changes
|
|
396
|
+
|
|
397
|
+
Only memories exceeding the surprise threshold (default 0.3) are stored, preventing redundancy.
|
|
398
|
+
|
|
399
|
+
### 🔍 FTS5 Semantic Search
|
|
400
|
+
|
|
401
|
+
Uses SQLite's full-text search with Porter stemming for keyword-based semantic search:
|
|
402
|
+
- No external dependencies or embedding models
|
|
403
|
+
- Sub-millisecond search performance
|
|
404
|
+
- Supports Boolean operators (AND, OR, phrase search)
|
|
405
|
+
|
|
406
|
+
### 📊 Multi-Signal Retrieval
|
|
407
|
+
|
|
408
|
+
Ranks memories using weighted combination:
|
|
409
|
+
- **Recency** (30%): Recent memories weighted higher with 7-day exponential decay
|
|
410
|
+
- **Importance** (40%): Stored importance score (preference=0.7, decision=0.8, fact=0.6)
|
|
411
|
+
- **Relevance** (30%): Keyword overlap with current query
|
|
412
|
+
|
|
413
|
+
### 🗂️ Memory Types
|
|
414
|
+
|
|
415
|
+
- **Preferences**: User coding styles, tool choices, frameworks
|
|
416
|
+
- **Decisions**: Architectural choices, agreed approaches
|
|
417
|
+
- **Facts**: Project details, tech stack, configurations
|
|
418
|
+
- **Entities**: Classes, functions, files, libraries mentioned
|
|
419
|
+
- **Relationships**: Dependencies, imports, extends patterns
|
|
420
|
+
|
|
421
|
+
## Configuration
|
|
422
|
+
|
|
423
|
+
All features are enabled by default with sensible defaults:
|
|
424
|
+
|
|
425
|
+
```env
|
|
426
|
+
# Core Settings
|
|
427
|
+
MEMORY_ENABLED=true # Master switch
|
|
428
|
+
MEMORY_RETRIEVAL_LIMIT=5 # Memories per request
|
|
429
|
+
MEMORY_SURPRISE_THRESHOLD=0.3 # Novelty filter (0.0-1.0)
|
|
430
|
+
|
|
431
|
+
# Lifecycle Management
|
|
432
|
+
MEMORY_MAX_AGE_DAYS=90 # Auto-delete old memories
|
|
433
|
+
MEMORY_MAX_COUNT=10000 # Maximum total memories
|
|
434
|
+
MEMORY_DECAY_ENABLED=true # Enable importance decay
|
|
435
|
+
MEMORY_DECAY_HALF_LIFE=30 # Days for 50% importance decay
|
|
436
|
+
|
|
437
|
+
# Retrieval Behavior
|
|
438
|
+
MEMORY_INCLUDE_GLOBAL=true # Include cross-session memories
|
|
439
|
+
MEMORY_INJECTION_FORMAT=system # Where to inject (system/assistant_preamble)
|
|
440
|
+
MEMORY_EXTRACTION_ENABLED=true # Auto-extract from responses
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Performance
|
|
444
|
+
|
|
445
|
+
Exceeds all targets:
|
|
446
|
+
- **Retrieval**: <2ms average (50x faster than 50ms target)
|
|
447
|
+
- **Extraction**: <3ms average (40x faster than 100ms target)
|
|
448
|
+
- **Storage**: ~150 bytes per memory
|
|
449
|
+
- **Search**: Sub-millisecond FTS5 queries
|
|
450
|
+
- **Surprise Calculation**: <1ms average
|
|
451
|
+
|
|
452
|
+
## Example Usage
|
|
453
|
+
|
|
454
|
+
The system works automatically - no manual intervention needed:
|
|
455
|
+
|
|
456
|
+
```bash
|
|
457
|
+
# First conversation
|
|
458
|
+
User: "I prefer Python for data processing"
|
|
459
|
+
Assistant: "I'll remember that you prefer Python..."
|
|
460
|
+
# System extracts: [preference] "prefer Python for data processing" (surprise: 0.85)
|
|
461
|
+
|
|
462
|
+
# Later conversation (same or different session)
|
|
463
|
+
User: "Write a script to process this CSV"
|
|
464
|
+
# System retrieves: [preference] "prefer Python for data processing"
|
|
465
|
+
Assistant: "I'll write a Python script using pandas..."
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Database Tables
|
|
469
|
+
|
|
470
|
+
- **`memories`**: Core memory storage (content, type, importance, surprise_score)
|
|
471
|
+
- **`memories_fts`**: FTS5 full-text search index (auto-synced via triggers)
|
|
472
|
+
- **`memory_entities`**: Entity tracking for novelty detection
|
|
473
|
+
- **`memory_embeddings`**: Optional vector storage (Phase 3, not yet used)
|
|
474
|
+
- **`memory_associations`**: Memory graph relationships (Phase 5, not yet used)
|
|
475
|
+
|
|
476
|
+
## Memory Tools (Optional)
|
|
477
|
+
|
|
478
|
+
Explicit memory management tools available:
|
|
479
|
+
- `memory_search` - Search long-term memories by query
|
|
480
|
+
- `memory_add` - Manually add important facts
|
|
481
|
+
- `memory_forget` - Remove memories matching query
|
|
482
|
+
- `memory_stats` - View memory statistics
|
|
483
|
+
|
|
484
|
+
Enable by exposing tools to the model (configurable in orchestrator).
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
297
488
|
# ⚡ Prompt Caching
|
|
298
489
|
|
|
299
490
|
Lynkr includes an LRU+TTL prompt cache.
|
|
@@ -380,7 +571,7 @@ npm start
|
|
|
380
571
|
|
|
381
572
|
**How it works:**
|
|
382
573
|
|
|
383
|
-
1. Model generates tool calls (from Databricks/OpenRouter/Ollama)
|
|
574
|
+
1. Model generates tool calls (from Databricks/OpenRouter/Ollama/llama.cpp)
|
|
384
575
|
2. Proxy converts to Anthropic format with `tool_use` blocks
|
|
385
576
|
3. Claude Code CLI receives `tool_use` blocks and executes locally
|
|
386
577
|
4. CLI sends `tool_result` blocks back in the next request
|
|
@@ -425,16 +616,44 @@ curl http://localhost:8080/v1/messages \
|
|
|
425
616
|
|
|
426
617
|
---
|
|
427
618
|
|
|
619
|
+
|
|
620
|
+
# 🤖 ACE Framework Working Nature
|
|
621
|
+
|
|
622
|
+
Lynkr's agentic architecture is inspired by the **Autonomous Cognitive Entity (ACE) Framework**, specifically implementing the **Reflector** pattern to enable self-improving capabilities.
|
|
623
|
+
|
|
624
|
+
### The Agentic Loop
|
|
625
|
+
|
|
626
|
+
1. **Input Processing**: The **Orchestrator** receives natural language intent from the user.
|
|
627
|
+
2. **Execution (Agent Model)**: The system executes tools (Git, Search, File Ops) to achieve the goal.
|
|
628
|
+
3. **Reflection (Reflector Role)**: After execution types, the `Reflector` agent analyzes the transcript to extract "skills" and optimize future performance.
|
|
629
|
+
|
|
630
|
+
### The Reflector
|
|
631
|
+
The Reflector (`src/agents/reflector.js`) is an introspective component that analyzes:
|
|
632
|
+
* **Tool Usage Patterns**: Identifying effective tool combinations (e.g., "Search -> Read -> Fix").
|
|
633
|
+
* **Efficiency**: Calculating step-count and token efficiency.
|
|
634
|
+
* **Error Handling**: Learning from recovered errors to suggest robust fallback strategies.
|
|
635
|
+
* **Task Patterns**: Recognizing recurring task types (Refactoring, Testing, Documentation) and their optimal workflows.
|
|
636
|
+
|
|
637
|
+
This "working nature" allows Lynkr to not just execute commands, but to **learn from interaction**, continuously refining its internal heuristics for tool selection and planning.
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
428
641
|
# 🛣 Roadmap
|
|
429
642
|
|
|
430
643
|
## ✅ Recently Completed (December 2025)
|
|
431
644
|
|
|
645
|
+
* **llama.cpp Provider Support** – Run any GGUF model locally with maximum performance using llama.cpp's optimized C++ inference engine with full tool calling support
|
|
646
|
+
* **Titans-Inspired Long-Term Memory System** – Automatic extraction and retrieval of conversation memories using surprise-based filtering, FTS5 semantic search, and multi-signal ranking for persistent learning across sessions
|
|
432
647
|
* **Client-side tool execution** (`TOOL_EXECUTION_MODE=client/passthrough`) – Tools can execute on the Claude Code CLI side, enabling local file operations, commands, and access to local credentials
|
|
433
648
|
* **OpenRouter error resilience** – Graceful handling of malformed OpenRouter responses, preventing crashes during rate limits or service errors
|
|
434
649
|
* **Enhanced format conversion** – Improved Anthropic ↔ OpenRouter format conversion for tool calls with proper `tool_use` block generation
|
|
435
650
|
|
|
436
651
|
## 🔮 Future Features
|
|
437
652
|
|
|
653
|
+
* **Memory System Enhancements**:
|
|
654
|
+
* Local embeddings with ONNX runtime for true semantic search (Phase 3)
|
|
655
|
+
* Memory association graphs for relationship-based retrieval (Phase 5)
|
|
656
|
+
* Memory decay scheduler with background optimization
|
|
438
657
|
* LSP integration (TypeScript, Python, more languages)
|
|
439
658
|
* Per-file diff comments
|
|
440
659
|
* Risk scoring for Git diffs
|
package/install.sh
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Lynkr Installation Script
|
|
4
|
+
# Usage: curl -fsSL https://raw.githubusercontent.com/vishalveerareddy123/Lynkr/main/install.sh | bash
|
|
5
|
+
#
|
|
6
|
+
# This script installs Lynkr, a self-hosted Claude Code proxy with multi-provider support.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
# Colors for output
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
BLUE='\033[0;34m'
|
|
16
|
+
NC='\033[0m' # No Color
|
|
17
|
+
|
|
18
|
+
# Configuration
|
|
19
|
+
REPO_URL="https://github.com/vishalveerareddy123/Lynkr"
|
|
20
|
+
INSTALL_DIR="${LYNKR_INSTALL_DIR:-$HOME/.lynkr}"
|
|
21
|
+
BRANCH="${LYNKR_BRANCH:-main}"
|
|
22
|
+
|
|
23
|
+
# Print colored output
|
|
24
|
+
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
25
|
+
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
26
|
+
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
27
|
+
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
28
|
+
|
|
29
|
+
# Print banner
|
|
30
|
+
print_banner() {
|
|
31
|
+
echo -e "${BLUE}"
|
|
32
|
+
echo " _ _ "
|
|
33
|
+
echo " | | _ _ _ __ | | ___ __ "
|
|
34
|
+
echo " | | | | | | '_ \| |/ / '__|"
|
|
35
|
+
echo " | |__| |_| | | | | <| | "
|
|
36
|
+
echo " |_____\__, |_| |_|_|\_\_| "
|
|
37
|
+
echo " |___/ "
|
|
38
|
+
echo -e "${NC}"
|
|
39
|
+
echo "Self-hosted Claude Code Proxy"
|
|
40
|
+
echo "=============================="
|
|
41
|
+
echo ""
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# Check for required commands
|
|
45
|
+
check_requirements() {
|
|
46
|
+
print_info "Checking requirements..."
|
|
47
|
+
|
|
48
|
+
local missing=()
|
|
49
|
+
|
|
50
|
+
if ! command -v node &> /dev/null; then
|
|
51
|
+
missing+=("node")
|
|
52
|
+
else
|
|
53
|
+
NODE_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
|
|
54
|
+
if [ "$NODE_VERSION" -lt 20 ]; then
|
|
55
|
+
print_error "Node.js version 20 or higher is required (found v$NODE_VERSION)"
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
print_success "Node.js $(node -v) found"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
if ! command -v npm &> /dev/null; then
|
|
62
|
+
missing+=("npm")
|
|
63
|
+
else
|
|
64
|
+
print_success "npm $(npm -v) found"
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if ! command -v git &> /dev/null; then
|
|
68
|
+
missing+=("git")
|
|
69
|
+
else
|
|
70
|
+
print_success "git $(git --version | cut -d' ' -f3) found"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
if [ ${#missing[@]} -ne 0 ]; then
|
|
74
|
+
print_error "Missing required tools: ${missing[*]}"
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Please install the missing tools:"
|
|
77
|
+
for tool in "${missing[@]}"; do
|
|
78
|
+
case $tool in
|
|
79
|
+
node|npm)
|
|
80
|
+
echo " - Node.js: https://nodejs.org/ (v20 or higher)"
|
|
81
|
+
;;
|
|
82
|
+
git)
|
|
83
|
+
echo " - Git: https://git-scm.com/"
|
|
84
|
+
;;
|
|
85
|
+
esac
|
|
86
|
+
done
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Clone or update repository
|
|
92
|
+
clone_or_update() {
|
|
93
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
94
|
+
print_info "Updating existing installation..."
|
|
95
|
+
cd "$INSTALL_DIR"
|
|
96
|
+
git fetch origin
|
|
97
|
+
git checkout "$BRANCH"
|
|
98
|
+
git pull origin "$BRANCH"
|
|
99
|
+
else
|
|
100
|
+
print_info "Cloning Lynkr repository..."
|
|
101
|
+
git clone --depth 1 --branch "$BRANCH" "$REPO_URL" "$INSTALL_DIR"
|
|
102
|
+
cd "$INSTALL_DIR"
|
|
103
|
+
fi
|
|
104
|
+
print_success "Repository ready at $INSTALL_DIR"
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# Install dependencies
|
|
108
|
+
install_dependencies() {
|
|
109
|
+
print_info "Installing dependencies..."
|
|
110
|
+
cd "$INSTALL_DIR"
|
|
111
|
+
npm install --production
|
|
112
|
+
print_success "Dependencies installed"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Create default .env file
|
|
116
|
+
create_env_file() {
|
|
117
|
+
if [ ! -f "$INSTALL_DIR/.env" ]; then
|
|
118
|
+
print_info "Creating default .env file..."
|
|
119
|
+
cp "$INSTALL_DIR/.env.example" "$INSTALL_DIR/.env" 2>/dev/null || cat > "$INSTALL_DIR/.env" << 'EOF'
|
|
120
|
+
# Lynkr Configuration
|
|
121
|
+
# See .env.example for all options
|
|
122
|
+
|
|
123
|
+
# Model Provider (databricks, openai, azure-openai, azure-anthropic, openrouter, ollama)
|
|
124
|
+
MODEL_PROVIDER=ollama
|
|
125
|
+
|
|
126
|
+
# Server Configuration
|
|
127
|
+
PORT=8080
|
|
128
|
+
|
|
129
|
+
# Ollama Configuration (default for local development)
|
|
130
|
+
PREFER_OLLAMA=true
|
|
131
|
+
OLLAMA_MODEL=qwen2.5-coder:7b
|
|
132
|
+
OLLAMA_ENDPOINT=http://localhost:11434
|
|
133
|
+
|
|
134
|
+
# Uncomment and configure your preferred provider:
|
|
135
|
+
# OPENAI_API_KEY=sk-your-key
|
|
136
|
+
# OPENROUTER_API_KEY=your-key
|
|
137
|
+
# DATABRICKS_API_KEY=your-key
|
|
138
|
+
# DATABRICKS_API_BASE=https://your-workspace.databricks.com
|
|
139
|
+
EOF
|
|
140
|
+
print_success "Created .env file (edit to configure your API keys)"
|
|
141
|
+
else
|
|
142
|
+
print_warning ".env file already exists, skipping"
|
|
143
|
+
fi
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Create symlink for global access
|
|
147
|
+
create_symlink() {
|
|
148
|
+
print_info "Setting up global command..."
|
|
149
|
+
|
|
150
|
+
# Determine bin directory
|
|
151
|
+
if [ -d "$HOME/.local/bin" ]; then
|
|
152
|
+
BIN_DIR="$HOME/.local/bin"
|
|
153
|
+
elif [ -d "/usr/local/bin" ] && [ -w "/usr/local/bin" ]; then
|
|
154
|
+
BIN_DIR="/usr/local/bin"
|
|
155
|
+
else
|
|
156
|
+
mkdir -p "$HOME/.local/bin"
|
|
157
|
+
BIN_DIR="$HOME/.local/bin"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Create symlink
|
|
161
|
+
ln -sf "$INSTALL_DIR/bin/cli.js" "$BIN_DIR/lynkr"
|
|
162
|
+
chmod +x "$INSTALL_DIR/bin/cli.js"
|
|
163
|
+
|
|
164
|
+
# Check if BIN_DIR is in PATH
|
|
165
|
+
if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then
|
|
166
|
+
print_warning "$BIN_DIR is not in your PATH"
|
|
167
|
+
echo ""
|
|
168
|
+
echo "Add this to your ~/.bashrc or ~/.zshrc:"
|
|
169
|
+
echo " export PATH=\"$BIN_DIR:\$PATH\""
|
|
170
|
+
echo ""
|
|
171
|
+
else
|
|
172
|
+
print_success "lynkr command available globally"
|
|
173
|
+
fi
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
# Print next steps
|
|
177
|
+
print_next_steps() {
|
|
178
|
+
echo ""
|
|
179
|
+
echo "=============================="
|
|
180
|
+
print_success "Lynkr installed successfully!"
|
|
181
|
+
echo "=============================="
|
|
182
|
+
echo ""
|
|
183
|
+
echo "Next steps:"
|
|
184
|
+
echo ""
|
|
185
|
+
echo " 1. Configure your API keys:"
|
|
186
|
+
echo " ${BLUE}nano $INSTALL_DIR/.env${NC}"
|
|
187
|
+
echo ""
|
|
188
|
+
echo " 2. Start Lynkr:"
|
|
189
|
+
echo " ${BLUE}cd $INSTALL_DIR && npm start${NC}"
|
|
190
|
+
echo " or"
|
|
191
|
+
echo " ${BLUE}lynkr${NC} (if in PATH)"
|
|
192
|
+
echo ""
|
|
193
|
+
echo " 3. Configure Claude CLI to use Lynkr:"
|
|
194
|
+
echo " ${BLUE}export ANTHROPIC_BASE_URL=http://localhost:8080${NC}"
|
|
195
|
+
echo ""
|
|
196
|
+
echo " 4. Run Claude Code:"
|
|
197
|
+
echo " ${BLUE}claude${NC}"
|
|
198
|
+
echo ""
|
|
199
|
+
echo "Documentation: https://github.com/vishalveerareddy123/Lynkr"
|
|
200
|
+
echo ""
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Alternative: npm global install
|
|
204
|
+
npm_install_instructions() {
|
|
205
|
+
echo ""
|
|
206
|
+
echo "Alternative: Install via npm"
|
|
207
|
+
echo "=============================="
|
|
208
|
+
echo ""
|
|
209
|
+
echo " ${BLUE}npm install -g lynkr${NC}"
|
|
210
|
+
echo " ${BLUE}lynkr-setup${NC}"
|
|
211
|
+
echo " ${BLUE}lynkr${NC}"
|
|
212
|
+
echo ""
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Main installation flow
|
|
216
|
+
main() {
|
|
217
|
+
print_banner
|
|
218
|
+
|
|
219
|
+
# Parse arguments
|
|
220
|
+
while [[ $# -gt 0 ]]; do
|
|
221
|
+
case $1 in
|
|
222
|
+
--dir)
|
|
223
|
+
INSTALL_DIR="$2"
|
|
224
|
+
shift 2
|
|
225
|
+
;;
|
|
226
|
+
--branch)
|
|
227
|
+
BRANCH="$2"
|
|
228
|
+
shift 2
|
|
229
|
+
;;
|
|
230
|
+
--help|-h)
|
|
231
|
+
echo "Usage: install.sh [OPTIONS]"
|
|
232
|
+
echo ""
|
|
233
|
+
echo "Options:"
|
|
234
|
+
echo " --dir DIR Installation directory (default: ~/.lynkr)"
|
|
235
|
+
echo " --branch NAME Git branch to install (default: main)"
|
|
236
|
+
echo " --help Show this help message"
|
|
237
|
+
echo ""
|
|
238
|
+
echo "Environment variables:"
|
|
239
|
+
echo " LYNKR_INSTALL_DIR Installation directory"
|
|
240
|
+
echo " LYNKR_BRANCH Git branch to install"
|
|
241
|
+
exit 0
|
|
242
|
+
;;
|
|
243
|
+
*)
|
|
244
|
+
print_error "Unknown option: $1"
|
|
245
|
+
exit 1
|
|
246
|
+
;;
|
|
247
|
+
esac
|
|
248
|
+
done
|
|
249
|
+
|
|
250
|
+
check_requirements
|
|
251
|
+
clone_or_update
|
|
252
|
+
install_dependencies
|
|
253
|
+
create_env_file
|
|
254
|
+
create_symlink
|
|
255
|
+
print_next_steps
|
|
256
|
+
npm_install_instructions
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
# Run main function
|
|
260
|
+
main "$@"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lynkr",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Self-hosted Claude Code proxy with Databricks,Azure adapters, workspace tooling, and MCP integration.",
|
|
3
|
+
"version": "3.0.0",
|
|
4
|
+
"description": "Self-hosted Claude Code proxy with Databricks,Azure adapters, openrouter, Ollama,llamacpp, workspace tooling, and MCP integration.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"lynkr": "./bin/cli.js",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"dev": "nodemon index.js",
|
|
13
13
|
"lint": "eslint src index.js",
|
|
14
14
|
"test": "npm run test:unit && npm run test:performance",
|
|
15
|
-
"test:unit": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/routing.test.js test/hybrid-routing-integration.test.js test/web-tools.test.js test/passthrough-mode.test.js test/openrouter-error-resilience.test.js test/format-conversion.test.js test/azure-openai-config.test.js test/azure-openai-format-conversion.test.js test/azure-openai-routing.test.js test/azure-openai-streaming.test.js test/azure-openai-error-resilience.test.js test/azure-openai-integration.test.js",
|
|
15
|
+
"test:unit": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/routing.test.js test/hybrid-routing-integration.test.js test/web-tools.test.js test/passthrough-mode.test.js test/openrouter-error-resilience.test.js test/format-conversion.test.js test/azure-openai-config.test.js test/azure-openai-format-conversion.test.js test/azure-openai-routing.test.js test/azure-openai-streaming.test.js test/azure-openai-error-resilience.test.js test/azure-openai-integration.test.js test/openai-integration.test.js test/llamacpp-integration.test.js test/memory/store.test.js test/memory/surprise.test.js test/memory/extractor.test.js test/memory/search.test.js test/memory/retriever.test.js",
|
|
16
|
+
"test:memory": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/memory/store.test.js test/memory/surprise.test.js test/memory/extractor.test.js test/memory/search.test.js test/memory/retriever.test.js",
|
|
16
17
|
"test:new-features": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node --test test/passthrough-mode.test.js test/openrouter-error-resilience.test.js test/format-conversion.test.js",
|
|
17
18
|
"test:performance": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/hybrid-routing-performance.test.js && DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-tests.js",
|
|
18
19
|
"test:benchmark": "DATABRICKS_API_KEY=test-key DATABRICKS_API_BASE=http://test.com node test/performance-benchmark.js",
|