llmtap 0.1.0 → 0.1.1
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 +292 -0
- package/package.json +4 -4
package/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">LLMTap</h1>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h3 align="center">DevTools for AI Agents</h3>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
See every LLM call. Trace agent workflows. Track costs.<br/>
|
|
9
|
+
Local-first. Zero-config. Two lines of code.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="#quick-start">Quick Start</a> ·
|
|
14
|
+
<a href="#features">Features</a> ·
|
|
15
|
+
<a href="#supported-providers">Providers</a> ·
|
|
16
|
+
<a href="#api-reference">API</a> ·
|
|
17
|
+
<a href="#architecture">Architecture</a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
Most LLM observability tools require cloud accounts, proxy configurations, or framework-specific callbacks. LLMTap takes a different approach: it runs entirely on your machine, instruments any LLM client with a single function call, and gives you a real-time dashboard at `localhost`.
|
|
23
|
+
|
|
24
|
+
No sign-ups. No API keys to manage the tool itself. Your prompts and responses never leave your machine.
|
|
25
|
+
|
|
26
|
+
<!-- hero-screenshot -->
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
**1. Start LLMTap**
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx llmtap
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The collector starts on `http://localhost:4781` and opens the dashboard.
|
|
39
|
+
|
|
40
|
+
**2. Instrument your code**
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import OpenAI from "openai";
|
|
44
|
+
import { wrap } from "@llmtap/sdk";
|
|
45
|
+
|
|
46
|
+
const client = wrap(new OpenAI());
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**3. Use your client as normal**
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const res = await client.chat.completions.create({
|
|
53
|
+
model: "gpt-4o",
|
|
54
|
+
messages: [{ role: "user", content: "Hello, world" }],
|
|
55
|
+
});
|
|
56
|
+
// Traced automatically -- tokens, cost, latency, full request/response
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Open `http://localhost:4781`. Traces appear in real time.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Features
|
|
64
|
+
|
|
65
|
+
**Transparent instrumentation** -- `wrap()` returns an ES Proxy. Your client behaves identically. No code changes beyond the wrap call. Streaming, tool calls, and multi-turn conversations all work.
|
|
66
|
+
|
|
67
|
+
**Real-time dashboard** -- Traces stream to the browser via SSE. See every LLM call as it happens with token counts, costs, latency, and full message content.
|
|
68
|
+
|
|
69
|
+
<!-- dashboard-screenshot -->
|
|
70
|
+
|
|
71
|
+
**Cost tracking** -- Built-in pricing for 50+ models across all major providers. Input and output costs calculated per-call. Override pricing for custom or fine-tuned models at runtime.
|
|
72
|
+
|
|
73
|
+
**Trace grouping** -- Group multiple LLM calls into a single trace with `startTrace()`. See total cost and token usage for multi-step agent pipelines.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
import { wrap, startTrace } from "@llmtap/sdk";
|
|
77
|
+
|
|
78
|
+
await startTrace("research-agent", async () => {
|
|
79
|
+
const plan = await client.chat.completions.create({ model: "gpt-4o", messages: [...] });
|
|
80
|
+
const draft = await client.chat.completions.create({ model: "gpt-4o-mini", messages: [...] });
|
|
81
|
+
});
|
|
82
|
+
// Both calls grouped under "research-agent" in the dashboard
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Streaming support** -- Full support for streaming responses across all providers. Token counts and costs are captured after the stream completes. Your application sees the exact same stream.
|
|
86
|
+
|
|
87
|
+
**OpenTelemetry export** -- Export traces in OTLP format following GenAI Semantic Conventions. Forward to Datadog, Grafana, Jaeger, or any OTLP-compatible backend.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 npx llmtap
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Privacy by default** -- Everything runs locally. No data is sent anywhere unless you explicitly configure OTLP forwarding. Content capture can be disabled entirely.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Supported Providers
|
|
98
|
+
|
|
99
|
+
LLMTap works with any provider that uses the OpenAI, Anthropic, or Google Gemini SDK format.
|
|
100
|
+
|
|
101
|
+
| Provider | SDK | Detection |
|
|
102
|
+
|----------|-----|-----------|
|
|
103
|
+
| **OpenAI** | `openai` | Automatic |
|
|
104
|
+
| **Anthropic** | `@anthropic-ai/sdk` | Automatic |
|
|
105
|
+
| **Google Gemini** | `@google/generative-ai` | Automatic |
|
|
106
|
+
| **DeepSeek** | `openai` (compatible) | Auto via base URL |
|
|
107
|
+
| **Groq** | `openai` (compatible) | Auto via base URL |
|
|
108
|
+
| **Together** | `openai` (compatible) | Auto via base URL |
|
|
109
|
+
| **Fireworks** | `openai` (compatible) | Auto via base URL |
|
|
110
|
+
| **OpenRouter** | `openai` (compatible) | Auto via base URL |
|
|
111
|
+
| **xAI (Grok)** | `openai` (compatible) | Auto via base URL |
|
|
112
|
+
| **Ollama** | `openai` (compatible) | Auto via base URL |
|
|
113
|
+
| **Vercel AI SDK** | `ai` | Via `wrapVercelAI()` |
|
|
114
|
+
| **Any OpenAI-compatible** | `openai` | Manual or auto |
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// OpenAI
|
|
118
|
+
const openai = wrap(new OpenAI());
|
|
119
|
+
|
|
120
|
+
// Anthropic
|
|
121
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
122
|
+
const claude = wrap(new Anthropic());
|
|
123
|
+
|
|
124
|
+
// Google Gemini
|
|
125
|
+
import { GoogleGenerativeAI } from "@google/generative-ai";
|
|
126
|
+
const gemini = wrap(new GoogleGenerativeAI(process.env.GOOGLE_API_KEY));
|
|
127
|
+
|
|
128
|
+
// DeepSeek, Groq, or any OpenAI-compatible provider
|
|
129
|
+
const deepseek = wrap(new OpenAI({
|
|
130
|
+
baseURL: "https://api.deepseek.com",
|
|
131
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
132
|
+
}));
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## API Reference
|
|
138
|
+
|
|
139
|
+
### `wrap(client, options?)`
|
|
140
|
+
|
|
141
|
+
Wraps an LLM client to trace all API calls. Returns a proxy -- the client works identically.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const client = wrap(new OpenAI());
|
|
145
|
+
const client = wrap(new OpenAI(), { provider: "deepseek", tags: { env: "staging" } });
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
| Option | Type | Description |
|
|
149
|
+
|--------|------|-------------|
|
|
150
|
+
| `provider` | `string` | Override auto-detected provider name |
|
|
151
|
+
| `tags` | `Record<string, string>` | Custom tags attached to every span |
|
|
152
|
+
|
|
153
|
+
### `startTrace(name, fn, options?)`
|
|
154
|
+
|
|
155
|
+
Groups multiple LLM calls under a single trace.
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
const result = await startTrace("my-pipeline", async () => {
|
|
159
|
+
const step1 = await client.chat.completions.create({ ... });
|
|
160
|
+
const step2 = await client.chat.completions.create({ ... });
|
|
161
|
+
return step2;
|
|
162
|
+
}, { sessionId: "user-123", tags: { workflow: "summarize" } });
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| Option | Type | Description |
|
|
166
|
+
|--------|------|-------------|
|
|
167
|
+
| `sessionId` | `string` | Group traces into a session |
|
|
168
|
+
| `tags` | `Record<string, string>` | Custom tags on the trace |
|
|
169
|
+
|
|
170
|
+
### `init(config)`
|
|
171
|
+
|
|
172
|
+
Configure the SDK globally. All options can also be set via environment variables.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { init } from "@llmtap/sdk";
|
|
176
|
+
|
|
177
|
+
init({
|
|
178
|
+
collectorUrl: "http://localhost:4781",
|
|
179
|
+
captureContent: true,
|
|
180
|
+
enabled: true,
|
|
181
|
+
debug: false,
|
|
182
|
+
sessionId: "my-session",
|
|
183
|
+
onError: (err, ctx) => console.warn("LLMTap:", err.message),
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
| Config | Env Var | Default | Description |
|
|
188
|
+
|--------|---------|---------|-------------|
|
|
189
|
+
| `collectorUrl` | `LLMTAP_COLLECTOR_URL` | `http://localhost:4781` | Collector endpoint |
|
|
190
|
+
| `captureContent` | `LLMTAP_CAPTURE_CONTENT` | `true` | Capture message content |
|
|
191
|
+
| `enabled` | `LLMTAP_ENABLED` | `true` | Enable/disable tracing |
|
|
192
|
+
| `debug` | `LLMTAP_DEBUG` | `false` | Debug logging |
|
|
193
|
+
| `sessionId` | `LLMTAP_SESSION_ID` | -- | Session grouping |
|
|
194
|
+
|
|
195
|
+
### `wrapVercelAI(ai)`
|
|
196
|
+
|
|
197
|
+
Wraps the Vercel AI SDK for framework-level tracing across any underlying provider.
|
|
198
|
+
|
|
199
|
+
### `shutdown()`
|
|
200
|
+
|
|
201
|
+
Flushes all buffered spans and shuts down the SDK. Call before process exit in serverless environments.
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { shutdown } from "@llmtap/sdk";
|
|
205
|
+
await shutdown();
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Architecture
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
Your Application
|
|
214
|
+
|
|
|
215
|
+
| wrap(client) -- ES Proxy intercepts LLM calls
|
|
216
|
+
|
|
|
217
|
+
v
|
|
218
|
+
@llmtap/sdk ───────────> @llmtap/collector ───────────> @llmtap/dashboard
|
|
219
|
+
Proxy-based Fastify + SQLite React + Vite
|
|
220
|
+
instrumentation REST API + SSE Real-time UI
|
|
221
|
+
| |
|
|
222
|
+
| Batched HTTP POST | SSE push on new spans Connects via SSE
|
|
223
|
+
| to /v1/spans | GET /v1/traces, /v1/stats and REST API
|
|
224
|
+
v v
|
|
225
|
+
┌─────────────┐
|
|
226
|
+
│ SQLite DB │ Optional: OTLP export to
|
|
227
|
+
│ (WAL mode) │ ───> Datadog, Grafana, Jaeger
|
|
228
|
+
└─────────────┘
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| Package | Description |
|
|
232
|
+
|---------|-------------|
|
|
233
|
+
| `llmtap` | CLI entry point -- `npx llmtap` starts collector + dashboard |
|
|
234
|
+
| `@llmtap/sdk` | ES Proxy-based instrumentation for LLM clients |
|
|
235
|
+
| `@llmtap/collector` | Fastify server, SQLite storage, SSE, REST API |
|
|
236
|
+
| `@llmtap/dashboard` | React + Vite + Tailwind SPA with real-time updates |
|
|
237
|
+
| `@llmtap/shared` | Types, constants, pricing data, OTLP converter |
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## CLI
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npx llmtap # Start collector + dashboard
|
|
245
|
+
npx llmtap --demo # Start with sample data
|
|
246
|
+
npx llmtap --port 8080 # Custom port
|
|
247
|
+
npx llmtap --retention 7d # Auto-delete old data
|
|
248
|
+
npx llmtap --host 0.0.0.0 # Expose to network
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Comparison
|
|
254
|
+
|
|
255
|
+
| | LLMTap | LangSmith | Helicone | Langfuse |
|
|
256
|
+
|---|---|---|---|---|
|
|
257
|
+
| **Setup** | `npx` + 2 lines | SDK + cloud account | Proxy + cloud | SDK + self-host or cloud |
|
|
258
|
+
| **Data location** | Your machine | Their cloud | Their cloud | Your infra or theirs |
|
|
259
|
+
| **Pricing** | Free, no limits | $39/seat/mo | $79/mo | Free (self-host) |
|
|
260
|
+
| **Instrumentation** | `wrap(client)` | Framework-specific | Proxy gateway | SDK callbacks |
|
|
261
|
+
|
|
262
|
+
LLMTap is a developer tool -- fast to start, private by default, zero friction. Use it during development and prototyping. When you need production infrastructure, export your traces via OTLP to the platform of your choice.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Development
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
git clone https://github.com/DivyaanshuXD/LLMTap.git
|
|
270
|
+
cd llmtap
|
|
271
|
+
pnpm install
|
|
272
|
+
pnpm build # Build all packages
|
|
273
|
+
pnpm test # Run all tests (Vitest)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
TypeScript monorepo with pnpm workspaces and Turborepo. Packages build with tsup, the dashboard builds with Vite.
|
|
277
|
+
|
|
278
|
+
## Contributing
|
|
279
|
+
|
|
280
|
+
Contributions are welcome.
|
|
281
|
+
|
|
282
|
+
1. Fork the repository
|
|
283
|
+
2. Create a feature branch: `git checkout -b feature/my-feature`
|
|
284
|
+
3. Make your changes and add tests
|
|
285
|
+
4. Run `pnpm build && pnpm test` to verify
|
|
286
|
+
5. Open a pull request
|
|
287
|
+
|
|
288
|
+
Please open an issue first for large changes so we can discuss the approach.
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llmtap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "DevTools for AI Agents - See every LLM call, trace agent workflows, track costs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"chalk": "^5.4.0",
|
|
14
14
|
"commander": "^13.0.0",
|
|
15
15
|
"open": "^10.1.0",
|
|
16
|
-
"@llmtap/collector": "0.1.
|
|
17
|
-
"@llmtap/shared": "0.1.
|
|
16
|
+
"@llmtap/collector": "0.1.1",
|
|
17
|
+
"@llmtap/shared": "0.1.1"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/node": "^25.4.0",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"repository": {
|
|
40
40
|
"type": "git",
|
|
41
|
-
"url": "https://github.com/
|
|
41
|
+
"url": "https://github.com/DivyaanshuXD/LLMTap",
|
|
42
42
|
"directory": "packages/cli"
|
|
43
43
|
},
|
|
44
44
|
"scripts": {
|