@patravishek/memex 0.2.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/LICENSE +21 -0
- package/README.md +399 -0
- package/dist/ai/provider.d.ts +6 -0
- package/dist/ai/provider.js +134 -0
- package/dist/ai/provider.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +475 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/pty-wrapper.d.ts +14 -0
- package/dist/core/pty-wrapper.js +233 -0
- package/dist/core/pty-wrapper.js.map +1 -0
- package/dist/core/session-logger.d.ts +31 -0
- package/dist/core/session-logger.js +124 -0
- package/dist/core/session-logger.js.map +1 -0
- package/dist/memory/compressor.d.ts +4 -0
- package/dist/memory/compressor.js +167 -0
- package/dist/memory/compressor.js.map +1 -0
- package/dist/memory/store.d.ts +42 -0
- package/dist/memory/store.js +145 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/storage/db.d.ts +7 -0
- package/dist/storage/db.js +148 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/queries.d.ts +38 -0
- package/dist/storage/queries.js +271 -0
- package/dist/storage/queries.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Avishek Patra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# Memex
|
|
2
|
+
|
|
3
|
+
> Persistent memory for any AI terminal agent.
|
|
4
|
+
|
|
5
|
+
When you close a terminal session with Claude, GPT, or any AI coding agent — all context is lost. The next session starts from zero. You end up re-explaining the project, re-establishing decisions, re-describing what you were working on.
|
|
6
|
+
|
|
7
|
+
Memex fixes this. It wraps your AI agent session, records the conversation, and uses AI to compress it into a structured memory file. The next time you start a session, Memex automatically injects that context so your agent picks up exactly where it left off.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## How it works
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
memex start claude
|
|
15
|
+
↓
|
|
16
|
+
macOS `script` command records all terminal I/O
|
|
17
|
+
↓
|
|
18
|
+
Session logged to .memex/sessions/
|
|
19
|
+
↓
|
|
20
|
+
On exit: AI compresses transcript → .memex/memex.db (SQLite)
|
|
21
|
+
↓
|
|
22
|
+
memex resume claude
|
|
23
|
+
↓
|
|
24
|
+
Memory injected as first message → agent has full context
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Memory is **project-scoped** — tied to the directory you run Memex from. Each project has its own independent SQLite database at `.memex/memex.db`. Session recording uses the macOS built-in `script` command — no native dependencies or compilation required.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
### Prerequisites
|
|
34
|
+
|
|
35
|
+
- macOS
|
|
36
|
+
- Node.js 18+
|
|
37
|
+
- An API key from Anthropic, OpenAI, or a LiteLLM enterprise proxy
|
|
38
|
+
- Any AI terminal agent (e.g. [Claude CLI](https://docs.anthropic.com/en/docs/claude-code))
|
|
39
|
+
|
|
40
|
+
### Via Homebrew (recommended)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
brew install patravishek/memex/memex
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The `patravishek/memex/memex` format is Homebrew's shorthand for a third-party tap — it registers the tap and installs the formula in a single command, no separate `brew tap` step needed.
|
|
47
|
+
|
|
48
|
+
To upgrade later:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
brew upgrade memex
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Via npm / manual
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/patravishek/memex.git
|
|
58
|
+
cd memex
|
|
59
|
+
npm install && npm run build && npm link
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`npm link` makes the `memex` command available globally from any directory.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
Memex reads API keys from your **shell environment** — no config file required. Add your key to `~/.zshrc` (or `~/.bashrc`) and reload:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
source ~/.zshrc
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Anthropic (default)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
78
|
+
export ANTHROPIC_MODEL=claude-3-haiku-20240307 # optional
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### OpenAI
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
export OPENAI_API_KEY=sk-...
|
|
85
|
+
export OPENAI_MODEL=gpt-4o-mini # optional
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### LiteLLM (enterprise proxy)
|
|
89
|
+
|
|
90
|
+
Many enterprises route AI traffic through a [LiteLLM](https://docs.litellm.ai) proxy to centralise key management, cost tracking, and model governance. Memex supports this natively.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
export LITELLM_API_KEY=your_litellm_key
|
|
94
|
+
export LITELLM_BASE_URL=https://litellm.your-company.com
|
|
95
|
+
export LITELLM_MODEL=claude-3-haiku # must match your proxy's model name
|
|
96
|
+
export LITELLM_TEAM_ID=your_team_id # optional — for team-based routing
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Memex uses the OpenAI SDK pointed at your LiteLLM proxy URL, so it works with **any model your enterprise has configured** — Claude, GPT-4, Mistral, Llama, and more. The `LITELLM_MODEL` value must match exactly what your proxy exposes (check with your LiteLLM admin).
|
|
100
|
+
|
|
101
|
+
### Provider auto-detection order
|
|
102
|
+
|
|
103
|
+
Memex auto-detects the provider from whichever keys are present in the environment:
|
|
104
|
+
|
|
105
|
+
1. **LiteLLM** — if both `LITELLM_API_KEY` and `LITELLM_BASE_URL` are set
|
|
106
|
+
2. **Anthropic** — if `ANTHROPIC_API_KEY` is set
|
|
107
|
+
3. **OpenAI** — if `OPENAI_API_KEY` is set
|
|
108
|
+
|
|
109
|
+
Override explicitly with `export AI_PROVIDER=anthropic|openai|litellm` if needed.
|
|
110
|
+
|
|
111
|
+
### Optional: `.env` file
|
|
112
|
+
|
|
113
|
+
If you prefer not to set shell variables globally, Memex also accepts a `.env` file inside the cloned repo directory. Shell environment variables always take precedence over `.env`.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cp .env.example .env
|
|
117
|
+
# edit .env with your keys
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Quickstart
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Install
|
|
126
|
+
brew install patravishek/memex/memex
|
|
127
|
+
|
|
128
|
+
# Add your API key to ~/.zshrc
|
|
129
|
+
echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.zshrc && source ~/.zshrc
|
|
130
|
+
|
|
131
|
+
# Go to any project and start a tracked session
|
|
132
|
+
cd ~/your-project
|
|
133
|
+
memex start claude
|
|
134
|
+
|
|
135
|
+
# Next day — resume with full context restored
|
|
136
|
+
memex resume claude
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Usage
|
|
142
|
+
|
|
143
|
+
### `memex start [command]`
|
|
144
|
+
|
|
145
|
+
Start a tracked session. Memex wraps your agent, records all I/O, and compresses it into memory when you exit.
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Wrap Claude CLI (default)
|
|
149
|
+
memex start claude
|
|
150
|
+
|
|
151
|
+
# Wrap any other agent
|
|
152
|
+
memex start aider
|
|
153
|
+
memex start sgpt
|
|
154
|
+
|
|
155
|
+
# Run against a specific project directory
|
|
156
|
+
memex start claude --project /path/to/project
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
On exit, you'll see:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
✔ Memory updated — focus: Implementing the checkout flow
|
|
163
|
+
Pending tasks: 3, gotchas: 1
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
### `memex resume [command]`
|
|
169
|
+
|
|
170
|
+
Start a new session with full context automatically restored. Memex injects your project memory as the first message so the agent immediately understands where things stand.
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
memex resume claude
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The agent receives a structured context block covering:
|
|
177
|
+
|
|
178
|
+
- What the project does and its tech stack
|
|
179
|
+
- What you were working on last session
|
|
180
|
+
- Pending tasks and key decisions
|
|
181
|
+
- Gotchas — mistakes and dead ends to avoid repeating
|
|
182
|
+
|
|
183
|
+
No more re-explaining. No more lost momentum.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
### `memex status`
|
|
188
|
+
|
|
189
|
+
See what Memex currently knows about your project.
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
memex status
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Example output:
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
memex — project memory
|
|
199
|
+
|
|
200
|
+
Project: my-app
|
|
201
|
+
What this project does:
|
|
202
|
+
E-commerce platform built with Next.js and Stripe...
|
|
203
|
+
|
|
204
|
+
Tech stack: Next.js, TypeScript, Prisma, PostgreSQL
|
|
205
|
+
|
|
206
|
+
Current focus: Implementing the checkout flow
|
|
207
|
+
|
|
208
|
+
Pending tasks:
|
|
209
|
+
- Add payment failure test cases
|
|
210
|
+
- Fix flaky login selector on Safari
|
|
211
|
+
|
|
212
|
+
Gotchas:
|
|
213
|
+
- chalk v5 is ESM-only, use v4 in CommonJS projects
|
|
214
|
+
|
|
215
|
+
Sessions recorded: 4
|
|
216
|
+
Database: /your-project/.memex/memex.db
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### `memex history`
|
|
222
|
+
|
|
223
|
+
List all past sessions for the current project with dates, durations, and summaries.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
memex history
|
|
227
|
+
|
|
228
|
+
# Show more results
|
|
229
|
+
memex history -n 50
|
|
230
|
+
|
|
231
|
+
# Show sessions across all projects
|
|
232
|
+
memex history --all
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Example output:
|
|
236
|
+
|
|
237
|
+
```
|
|
238
|
+
memex — session history
|
|
239
|
+
|
|
240
|
+
#12 Feb 18, 2026, 10:30 AM [claude] 42m 18s
|
|
241
|
+
Implemented cart persistence, fixed guest cart bug on page refresh.
|
|
242
|
+
|
|
243
|
+
#11 Feb 17, 2026, 3:12 PM [claude] 1h 5m
|
|
244
|
+
Set up Stripe webhook handler and wrote integration tests.
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### `memex show <id>`
|
|
250
|
+
|
|
251
|
+
View full details of any past session, including every recorded conversation turn.
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
memex show 12
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
### `memex search <query>`
|
|
260
|
+
|
|
261
|
+
Full-text search across all session summaries. Fast — backed by SQLite FTS5.
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
memex search "stripe webhook"
|
|
265
|
+
memex search "authentication bug"
|
|
266
|
+
|
|
267
|
+
# Search across all projects
|
|
268
|
+
memex search "prisma migration" --all
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Example output:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
memex — search: "stripe webhook"
|
|
275
|
+
|
|
276
|
+
#11 Feb 17, 2026 [claude]
|
|
277
|
+
Set up [stripe webhook] handler and wrote integration tests for...
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
### `memex prune [days]`
|
|
283
|
+
|
|
284
|
+
Delete session records older than N days (default: 30). Raw JSONL log files in `.memex/sessions/` are not touched — remove those separately if needed.
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# Remove sessions older than 30 days (default)
|
|
288
|
+
memex prune
|
|
289
|
+
|
|
290
|
+
# Remove sessions older than 7 days
|
|
291
|
+
memex prune 7
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
### `memex forget`
|
|
297
|
+
|
|
298
|
+
Clear all memory for the current project and start fresh.
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Clear memory fields but keep session history
|
|
302
|
+
memex forget --keep-sessions
|
|
303
|
+
|
|
304
|
+
# Clear everything
|
|
305
|
+
memex forget
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### `memex compress`
|
|
311
|
+
|
|
312
|
+
Manually re-run compression on the latest session log. Useful if compression failed at the end of a session or you want to force a memory refresh.
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
memex compress
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Project structure
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
.memex/ # Created in your project root
|
|
324
|
+
├── memex.db # SQLite database (memory + full session history)
|
|
325
|
+
├── memory.json.bak # Auto-created if upgrading from v0.1 (safe to delete)
|
|
326
|
+
└── sessions/
|
|
327
|
+
├── 2026-02-18T10-00.jsonl # Structured session log (raw I/O entries)
|
|
328
|
+
└── 2026-02-18T10-00-raw.txt # Raw terminal recording (from `script` command)
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Add this to your project's `.gitignore` to keep raw session logs out of version control:
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
.memex/sessions/
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
The `memex.db` file is small (typically a few KB per session). You can commit it so your whole team shares the same project memory — useful for onboarding or handoffs. Use `memex history` to inspect it without opening a SQL client.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## What gets captured
|
|
342
|
+
|
|
343
|
+
| Field | Description |
|
|
344
|
+
|---|---|
|
|
345
|
+
| `description` | What the project does |
|
|
346
|
+
| `stack` | Tech stack detected from conversation |
|
|
347
|
+
| `currentFocus` | What was being worked on |
|
|
348
|
+
| `pendingTasks` | Tasks mentioned but not completed |
|
|
349
|
+
| `keyDecisions` | Architectural and design decisions made |
|
|
350
|
+
| `importantFiles` | Files referenced during the session |
|
|
351
|
+
| `gotchas` | Problems hit, mistakes made, things to avoid |
|
|
352
|
+
| `recentSessions` | Summaries of the last 5 sessions |
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Supported providers
|
|
357
|
+
|
|
358
|
+
| Provider | Key variable | Default model |
|
|
359
|
+
|---|---|---|
|
|
360
|
+
| Anthropic | `ANTHROPIC_API_KEY` | `claude-3-haiku-20240307` |
|
|
361
|
+
| OpenAI | `OPENAI_API_KEY` | `gpt-4o-mini` |
|
|
362
|
+
| LiteLLM | `LITELLM_API_KEY` + `LITELLM_BASE_URL` | Set via `LITELLM_MODEL` |
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Works with any agent
|
|
367
|
+
|
|
368
|
+
| Agent | Command |
|
|
369
|
+
|---|---|
|
|
370
|
+
| Claude CLI | `memex start claude` |
|
|
371
|
+
| Aider | `memex start aider` |
|
|
372
|
+
| Shell-GPT | `memex start sgpt` |
|
|
373
|
+
| Any custom agent | `memex start your-agent` |
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Notes
|
|
378
|
+
|
|
379
|
+
### Claude CLI users
|
|
380
|
+
|
|
381
|
+
Memex automatically strips its own API keys from the environment before passing it to the wrapped agent. This prevents the auth conflict warning that Claude CLI shows when `ANTHROPIC_API_KEY` is set in the environment but you are logged in via claude.ai.
|
|
382
|
+
|
|
383
|
+
### Key isolation
|
|
384
|
+
|
|
385
|
+
Your project's own `.env` files are never read or modified by Memex. Memex only reads from your shell environment and its own optional `.env` inside the repo directory.
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Roadmap
|
|
390
|
+
|
|
391
|
+
See [ROADMAP.md](ROADMAP.md) for planned features across upcoming versions — including MCP server support, a local web UI, semantic vector search, and more.
|
|
392
|
+
|
|
393
|
+
Contributions welcome. If a feature matters to you, open an issue.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
MIT
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.chat = chat;
|
|
40
|
+
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
41
|
+
const openai_1 = __importDefault(require("openai"));
|
|
42
|
+
const dotenv = __importStar(require("dotenv"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const fs = __importStar(require("fs"));
|
|
45
|
+
// .env is optional — environment variables set in ~/.zshrc or ~/.bashrc take
|
|
46
|
+
// precedence. The .env file (if present) only fills in what's missing.
|
|
47
|
+
const envPath = path.join(__dirname, "../../.env");
|
|
48
|
+
if (fs.existsSync(envPath)) {
|
|
49
|
+
dotenv.config({ path: envPath, override: false });
|
|
50
|
+
}
|
|
51
|
+
const DEFAULTS = {
|
|
52
|
+
anthropic: "claude-3-haiku-20240307",
|
|
53
|
+
openai: "gpt-4o-mini",
|
|
54
|
+
// LiteLLM model names depend on what's configured in the enterprise proxy.
|
|
55
|
+
// Override with LITELLM_MODEL in .env to match your deployment.
|
|
56
|
+
litellm: "gpt-4o-mini",
|
|
57
|
+
};
|
|
58
|
+
function resolveProvider() {
|
|
59
|
+
const provider = process.env.AI_PROVIDER;
|
|
60
|
+
if (provider === "litellm")
|
|
61
|
+
return "litellm";
|
|
62
|
+
if (provider === "openai")
|
|
63
|
+
return "openai";
|
|
64
|
+
if (provider === "anthropic")
|
|
65
|
+
return "anthropic";
|
|
66
|
+
// Auto-detect from available keys
|
|
67
|
+
if (process.env.LITELLM_API_KEY && process.env.LITELLM_BASE_URL)
|
|
68
|
+
return "litellm";
|
|
69
|
+
if (process.env.ANTHROPIC_API_KEY)
|
|
70
|
+
return "anthropic";
|
|
71
|
+
if (process.env.OPENAI_API_KEY)
|
|
72
|
+
return "openai";
|
|
73
|
+
return "anthropic";
|
|
74
|
+
}
|
|
75
|
+
function buildLiteLLMClient() {
|
|
76
|
+
const apiKey = process.env.LITELLM_API_KEY;
|
|
77
|
+
const baseURL = process.env.LITELLM_BASE_URL;
|
|
78
|
+
if (!apiKey)
|
|
79
|
+
throw new Error("LITELLM_API_KEY is not set.");
|
|
80
|
+
if (!baseURL)
|
|
81
|
+
throw new Error("LITELLM_BASE_URL is not set.");
|
|
82
|
+
// LiteLLM exposes an OpenAI-compatible API — we reuse the OpenAI SDK
|
|
83
|
+
// and just point it at the enterprise proxy.
|
|
84
|
+
return new openai_1.default({
|
|
85
|
+
apiKey,
|
|
86
|
+
baseURL: baseURL.replace(/\/$/, "") + "/v1",
|
|
87
|
+
defaultHeaders: {
|
|
88
|
+
// Some LiteLLM deployments require this to identify the caller
|
|
89
|
+
...(process.env.LITELLM_TEAM_ID
|
|
90
|
+
? { "x-litellm-team": process.env.LITELLM_TEAM_ID }
|
|
91
|
+
: {}),
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
async function chat(messages, systemPrompt) {
|
|
96
|
+
const provider = resolveProvider();
|
|
97
|
+
// ── Anthropic direct ────────────────────────────────────────────────────────
|
|
98
|
+
if (provider === "anthropic") {
|
|
99
|
+
const client = new sdk_1.default({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
100
|
+
const model = process.env.ANTHROPIC_MODEL ?? DEFAULTS.anthropic;
|
|
101
|
+
const response = await client.messages.create({
|
|
102
|
+
model,
|
|
103
|
+
max_tokens: 4096,
|
|
104
|
+
system: systemPrompt,
|
|
105
|
+
messages,
|
|
106
|
+
});
|
|
107
|
+
return response.content[0].type === "text" ? response.content[0].text : "";
|
|
108
|
+
}
|
|
109
|
+
// ── LiteLLM proxy ───────────────────────────────────────────────────────────
|
|
110
|
+
if (provider === "litellm") {
|
|
111
|
+
const client = buildLiteLLMClient();
|
|
112
|
+
const model = process.env.LITELLM_MODEL ?? DEFAULTS.litellm;
|
|
113
|
+
const response = await client.chat.completions.create({
|
|
114
|
+
model,
|
|
115
|
+
messages: [
|
|
116
|
+
{ role: "system", content: systemPrompt },
|
|
117
|
+
...messages.map((m) => ({ role: m.role, content: m.content })),
|
|
118
|
+
],
|
|
119
|
+
});
|
|
120
|
+
return response.choices[0]?.message?.content ?? "";
|
|
121
|
+
}
|
|
122
|
+
// ── OpenAI direct ───────────────────────────────────────────────────────────
|
|
123
|
+
const client = new openai_1.default({ apiKey: process.env.OPENAI_API_KEY });
|
|
124
|
+
const model = process.env.OPENAI_MODEL ?? DEFAULTS.openai;
|
|
125
|
+
const response = await client.chat.completions.create({
|
|
126
|
+
model,
|
|
127
|
+
messages: [
|
|
128
|
+
{ role: "system", content: systemPrompt },
|
|
129
|
+
...messages.map((m) => ({ role: m.role, content: m.content })),
|
|
130
|
+
],
|
|
131
|
+
});
|
|
132
|
+
return response.choices[0]?.message?.content ?? "";
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED