neatlogs 1.1.18 → 1.1.20
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 +206 -84
- package/dist/ai-sdk.cjs +219 -15
- package/dist/ai-sdk.cjs.map +1 -1
- package/dist/ai-sdk.d.ts +17 -7
- package/dist/ai-sdk.mjs +222 -16
- package/dist/ai-sdk.mjs.map +1 -1
- package/dist/anthropic.cjs +917 -80
- package/dist/anthropic.cjs.map +1 -1
- package/dist/anthropic.mjs +921 -81
- package/dist/anthropic.mjs.map +1 -1
- package/dist/azure-openai.cjs +1166 -96
- package/dist/azure-openai.cjs.map +1 -1
- package/dist/azure-openai.mjs +1170 -97
- package/dist/azure-openai.mjs.map +1 -1
- package/dist/bedrock.cjs +928 -67
- package/dist/bedrock.cjs.map +1 -1
- package/dist/bedrock.mjs +932 -68
- package/dist/bedrock.mjs.map +1 -1
- package/dist/browser.cjs +29 -3
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.mjs +27 -3
- package/dist/browser.mjs.map +1 -1
- package/dist/claude-agent-sdk.cjs +27 -7
- package/dist/claude-agent-sdk.cjs.map +1 -1
- package/dist/claude-agent-sdk.mjs +27 -7
- package/dist/claude-agent-sdk.mjs.map +1 -1
- package/dist/cli.cjs +13061 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +13060 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/google-genai.cjs +867 -46
- package/dist/google-genai.cjs.map +1 -1
- package/dist/google-genai.d.ts +2 -2
- package/dist/google-genai.mjs +871 -47
- package/dist/google-genai.mjs.map +1 -1
- package/dist/index.cjs +11465 -3944
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1667 -68
- package/dist/index.mjs +11563 -4052
- package/dist/index.mjs.map +1 -1
- package/dist/langchain.cjs +69 -7
- package/dist/langchain.cjs.map +1 -1
- package/dist/langchain.mjs +73 -8
- package/dist/langchain.mjs.map +1 -1
- package/dist/mastra-wrap.cjs +21 -6
- package/dist/mastra-wrap.cjs.map +1 -1
- package/dist/mastra-wrap.mjs +21 -6
- package/dist/mastra-wrap.mjs.map +1 -1
- package/dist/openai-agents.cjs +19 -4
- package/dist/openai-agents.cjs.map +1 -1
- package/dist/openai-agents.mjs +19 -4
- package/dist/openai-agents.mjs.map +1 -1
- package/dist/openai.cjs +1406 -210
- package/dist/openai.cjs.map +1 -1
- package/dist/openai.mjs +1410 -211
- package/dist/openai.mjs.map +1 -1
- package/dist/opencode-plugin.cjs +8 -7
- package/dist/opencode-plugin.cjs.map +1 -1
- package/dist/opencode-plugin.d.ts +0 -2
- package/dist/opencode-plugin.mjs +8 -7
- package/dist/opencode-plugin.mjs.map +1 -1
- package/dist/openrouter-agent.cjs +106 -19
- package/dist/openrouter-agent.cjs.map +1 -1
- package/dist/openrouter-agent.mjs +110 -20
- package/dist/openrouter-agent.mjs.map +1 -1
- package/dist/pi-agent.cjs +21 -6
- package/dist/pi-agent.cjs.map +1 -1
- package/dist/pi-agent.mjs +21 -6
- package/dist/pi-agent.mjs.map +1 -1
- package/dist/vertex-ai.cjs +867 -46
- package/dist/vertex-ai.cjs.map +1 -1
- package/dist/vertex-ai.mjs +871 -47
- package/dist/vertex-ai.mjs.map +1 -1
- package/package.json +10 -43
package/README.md
CHANGED
|
@@ -7,18 +7,15 @@ Automatically trace LLM calls, agent workflows, tool invocations, and retrieval
|
|
|
7
7
|
## Quick Start
|
|
8
8
|
|
|
9
9
|
```typescript
|
|
10
|
-
import { init, span, shutdown } from 'neatlogs';
|
|
10
|
+
import { init, span, shutdown, wrapOpenAI } from 'neatlogs';
|
|
11
11
|
import OpenAI from 'openai';
|
|
12
12
|
|
|
13
13
|
async function main() {
|
|
14
14
|
// 1. Initialize the SDK
|
|
15
|
-
await init({
|
|
16
|
-
apiKey: process.env.NEATLOGS_API_KEY,
|
|
17
|
-
instrumentations: ['openai'],
|
|
18
|
-
});
|
|
15
|
+
await init({ apiKey: process.env.NEATLOGS_API_KEY });
|
|
19
16
|
|
|
20
|
-
// 2.
|
|
21
|
-
const client = new OpenAI();
|
|
17
|
+
// 2. Explicitly wrap the provider client
|
|
18
|
+
const client = wrapOpenAI(new OpenAI());
|
|
22
19
|
|
|
23
20
|
// 3. Wrap functions with span() for observability
|
|
24
21
|
const myWorkflow = span({ kind: 'WORKFLOW', name: 'qa-bot' }, async (query: string) => {
|
|
@@ -44,56 +41,49 @@ main().catch(console.error);
|
|
|
44
41
|
npm install neatlogs
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# OpenAI
|
|
51
|
-
npm install @arizeai/openinference-instrumentation-openai
|
|
52
|
-
|
|
53
|
-
# Anthropic
|
|
54
|
-
npm install @arizeai/openinference-instrumentation-anthropic
|
|
55
|
-
|
|
56
|
-
# AWS Bedrock
|
|
57
|
-
npm install @arizeai/openinference-instrumentation-bedrock
|
|
58
|
-
|
|
59
|
-
# LangChain
|
|
60
|
-
npm install @arizeai/openinference-instrumentation-langchain
|
|
61
|
-
|
|
62
|
-
# MCP (Model Context Protocol)
|
|
63
|
-
npm install @arizeai/openinference-instrumentation-mcp
|
|
64
|
-
|
|
65
|
-
# BeeAI
|
|
66
|
-
npm install @arizeai/openinference-instrumentation-beeai
|
|
67
|
-
|
|
68
|
-
# Claude Agent SDK
|
|
69
|
-
npm install @arizeai/openinference-instrumentation-claude-agent-sdk
|
|
70
|
-
|
|
71
|
-
# Google GenAI (@google/genai)
|
|
72
|
-
npm install @google/genai
|
|
73
|
-
```
|
|
44
|
+
Install the provider or framework package you already use, then apply its
|
|
45
|
+
documented Neatlogs wrapper, hook, processor, or telemetry helper.
|
|
74
46
|
|
|
75
47
|
## Core Concepts
|
|
76
48
|
|
|
77
49
|
| Function | Purpose |
|
|
78
50
|
|----------|---------|
|
|
79
|
-
| `init()` | Initialize the SDK — sets up OTel providers
|
|
51
|
+
| `init()` | Initialize the SDK — sets up private OTel providers and exporters |
|
|
80
52
|
| `span()` | Wrap a function with observability — captures inputs, outputs, timing, and errors |
|
|
81
53
|
| `trace()` | Create a manual span with prompt template tracking and multi-turn session support |
|
|
82
54
|
| `log()` | Capture timestamped log steps within the active trace |
|
|
83
55
|
| `shutdown()` | Flush all pending data and shut down the SDK gracefully |
|
|
84
56
|
|
|
85
|
-
|
|
57
|
+
## Doctor v2
|
|
86
58
|
|
|
87
|
-
|
|
59
|
+
Run the local SDK pipeline check without credentials or network access:
|
|
88
60
|
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
61
|
+
```bash
|
|
62
|
+
npx neatlogs doctor --local --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run the controlled end-to-end probe explicitly:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
NEATLOGS_API_KEY=<project-key> \
|
|
69
|
+
NEATLOGS_ENDPOINT=https://ingest.neatlogs.com \
|
|
70
|
+
npx neatlogs doctor --probe --json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Probe mode exports four generated spans through the normal `/v1/traces` route
|
|
74
|
+
with `x-neatlogs-doctor: v1`, flushes, and polls
|
|
75
|
+
`/api/traces/v3/:traceId` for that exact trace. It passes only after persisted
|
|
76
|
+
hierarchy, span semantics, input/output, versioned metadata, and numeric token
|
|
77
|
+
totals validate. It does not call an LLM or inspect user data.
|
|
78
|
+
|
|
79
|
+
### Important: Explicit integration
|
|
93
80
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
81
|
+
`init()` does not monkey-patch provider libraries. Use the documented explicit
|
|
82
|
+
wrapper, hook, processor, or telemetry helper for each integration.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
await init({ apiKey: process.env.NEATLOGS_API_KEY });
|
|
86
|
+
const client = wrapOpenAI(new OpenAI());
|
|
97
87
|
```
|
|
98
88
|
|
|
99
89
|
### Important: No Top-Level Await
|
|
@@ -119,7 +109,6 @@ Initialize the Neatlogs SDK. Returns `Promise<void>`.
|
|
|
119
109
|
```typescript
|
|
120
110
|
await init({
|
|
121
111
|
apiKey: process.env.NEATLOGS_API_KEY,
|
|
122
|
-
instrumentations: ['openai', 'anthropic'],
|
|
123
112
|
debug: true,
|
|
124
113
|
});
|
|
125
114
|
```
|
|
@@ -129,7 +118,6 @@ await init({
|
|
|
129
118
|
| Option | Type | Default | Description |
|
|
130
119
|
|--------|------|---------|-------------|
|
|
131
120
|
| `apiKey` | `string` | `process.env.NEATLOGS_API_KEY` | Neatlogs API key. Export disabled if not set. |
|
|
132
|
-
| `baseUrl` | `string` | `'https://app.neatlogs.com'` | Base URL for the Neatlogs API. |
|
|
133
121
|
| `workflowName` | `string` | Derived from `process.argv[1]` | Name of the workflow being traced. |
|
|
134
122
|
| `sessionId` | `string` | — | Explicit session ID for grouping traces. |
|
|
135
123
|
| `autoSession` | `boolean` | `false` | Auto-generate a session ID if none provided. |
|
|
@@ -138,19 +126,49 @@ await init({
|
|
|
138
126
|
| `metadata` | `Record<string, any>` | — | Custom metadata attached to all spans. |
|
|
139
127
|
| `debug` | `boolean` | `false` | Enable debug logging. |
|
|
140
128
|
| `disableExport` | `boolean` | `false` | Disable export to Neatlogs backend. |
|
|
141
|
-
| `instrumentations` | `string[]` | — | Legacy manager path. Instrumentors that depend on global OTel context are rejected; use explicit wrappers below. |
|
|
142
129
|
| `tracerProvider` | `BasicTracerProvider` | Private SDK provider | Optional caller-owned private provider. It is never registered globally or shut down by Neatlogs. |
|
|
143
130
|
| `registerShutdownHandlers` | `boolean` | `true` for SDK-owned provider | Register process exit/signal handlers. Set `false` when the host application owns shutdown. |
|
|
144
131
|
| `mask` | `MaskFunction` | — | Global mask function applied to all spans. |
|
|
145
132
|
| `sampleRate` | `number` | `1.0` | Sampling rate (0.0 to 1.0). |
|
|
146
133
|
| `captureLogs` | `boolean` | `false` | Capture log records via OTel LoggerProvider. |
|
|
147
|
-
| `traceContent` | `boolean` | `true` | Capture input/output content on spans. |
|
|
148
134
|
| `pii` | `'redact' | 'hash' | false` | — | PII detection mode. |
|
|
149
135
|
| `endpoint` | `string` | `'https://ingest.neatlogs.com'` | Base ingest endpoint. The SDK sends traces to `/v1/traces` and logs to `/v1/logs`. |
|
|
150
136
|
| `batchSize` | `number` | `100` | Maximum spans per export batch. |
|
|
151
137
|
| `flushInterval` | `number` | `5` | Seconds between batch flushes. |
|
|
152
138
|
| `piiEnabled` | `boolean` | — | Override team-level PII redaction toggle. |
|
|
153
139
|
| `piiSpanTypes` | `string[]` | — | Override which span types have server-side PII redaction. |
|
|
140
|
+
| `uploadAuthority` | `boolean \| UploadAuthority` | `false` | Enable the authenticated typed-media/oversized-OTLP upload contract, or inject an implementation. Keep disabled until the backend contract is deployed. |
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### Independent `Client` pipelines
|
|
145
|
+
|
|
146
|
+
Use `Client` when one process must send different executions to different
|
|
147
|
+
Neatlogs projects. Each Client owns an isolated provider/export queue; the
|
|
148
|
+
active Client is scoped to its synchronous or asynchronous `activate()` call.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { Client, trace, wrapOpenAI } from 'neatlogs';
|
|
152
|
+
|
|
153
|
+
const project = new Client({
|
|
154
|
+
apiKey: process.env.NEATLOGS_API_KEY!,
|
|
155
|
+
workflowName: 'support-agent',
|
|
156
|
+
captureLogs: true,
|
|
157
|
+
});
|
|
158
|
+
const openai = wrapOpenAI(rawOpenAI); // reusable; routing occurs at invocation
|
|
159
|
+
|
|
160
|
+
await project.activate(async () => {
|
|
161
|
+
await trace({ name: 'answer', kind: 'WORKFLOW' }, async () => {
|
|
162
|
+
return openai.responses.create({ model: 'gpt-5', input: 'Hello' });
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
await project.shutdown();
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Do not share one activation across unrelated concurrent jobs. Create one Client
|
|
170
|
+
per destination, use `activate()` around each execution, and always await
|
|
171
|
+
`shutdown()` when that Client is no longer needed.
|
|
154
172
|
|
|
155
173
|
---
|
|
156
174
|
|
|
@@ -249,7 +267,7 @@ const result = await trace({
|
|
|
249
267
|
| Option | Type | Default | Description |
|
|
250
268
|
|--------|------|---------|-------------|
|
|
251
269
|
| `name` | `string` | — | **Required.** Name for the trace span. |
|
|
252
|
-
| `kind` | `
|
|
270
|
+
| `kind` | `TraceSpanKind` | `'CHAIN'` | Span kind. Base kinds include `GUARDRAIL` and `EVALUATOR`; `trace()` additionally accepts `LLM`, `RERANKER`, and `VECTOR_STORE`. |
|
|
253
271
|
| `sessionId` | `string` | — | Session ID for grouping this root trace. |
|
|
254
272
|
| `parentSessionId` | `string` | — | Immediate parent session ID. |
|
|
255
273
|
| `sessionFeatureName` | `string` | — | Product feature that initiated the session request. |
|
|
@@ -345,8 +363,12 @@ Server-side prompt management for storing, versioning, and retrieving prompts fr
|
|
|
345
363
|
import { PromptClient } from 'neatlogs';
|
|
346
364
|
|
|
347
365
|
const client = new PromptClient({
|
|
348
|
-
baseUrl: 'https://
|
|
366
|
+
baseUrl: 'https://ingest.neatlogs.com',
|
|
349
367
|
apiKey: process.env.NEATLOGS_API_KEY!,
|
|
368
|
+
cacheTtlMs: 60_000, // fresh lifetime for latest/label lookups
|
|
369
|
+
staleWhileRevalidateMs: 300_000, // bounded stale fallback during refresh
|
|
370
|
+
requestTimeoutMs: 10_000, // deadline for each prompt API request
|
|
371
|
+
maxCacheEntries: 100, // LRU bound for process memory
|
|
350
372
|
});
|
|
351
373
|
|
|
352
374
|
// Create a prompt
|
|
@@ -359,9 +381,17 @@ const prompt = await client.createPrompt({
|
|
|
359
381
|
// Fetch by name (returns latest version)
|
|
360
382
|
const handle = await client.getPrompt('qa-system');
|
|
361
383
|
|
|
384
|
+
// Per-key cache policy is retained across refreshes. During the stale window,
|
|
385
|
+
// getPrompt returns the last known value and starts one coalesced refresh.
|
|
386
|
+
const fastRefresh = await client.getPrompt('qa-system', {
|
|
387
|
+
cacheTtlMs: 5_000,
|
|
388
|
+
staleWhileRevalidateMs: 60_000,
|
|
389
|
+
});
|
|
390
|
+
|
|
362
391
|
// Fetch by label or version
|
|
363
392
|
const prod = await client.getPrompt('qa-system', { label: 'production' });
|
|
364
393
|
const v2 = await client.getPrompt('qa-system', { version: 2 });
|
|
394
|
+
const v3 = await client.getPrompt('qa-system', { version: 3 });
|
|
365
395
|
|
|
366
396
|
// Compile with variables
|
|
367
397
|
const rendered = handle.compile({ role: 'helpful', company: 'Acme' });
|
|
@@ -372,20 +402,62 @@ const messages = handle.compileMessages({ role: 'helpful', company: 'Acme' });
|
|
|
372
402
|
// List all prompts
|
|
373
403
|
const all = await client.listPrompts();
|
|
374
404
|
|
|
375
|
-
//
|
|
405
|
+
// Backward-compatible alias: managed prompts are immutable, so this creates a version
|
|
376
406
|
await client.updatePrompt('qa-system', { content: 'Updated: {{role}} for {{company}}.' });
|
|
377
407
|
|
|
378
|
-
// Save a new version
|
|
379
|
-
await client.saveAsVersion('qa-system', {
|
|
408
|
+
// Save a new version. Content or messages is required by the backend contract.
|
|
409
|
+
await client.saveAsVersion('qa-system', {
|
|
410
|
+
content: 'Version 2: {{role}} for {{company}}.',
|
|
411
|
+
labels: ['staging'],
|
|
412
|
+
commitMessage: 'Try the revised system prompt',
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Mutations target immutable version UUIDs. Name + version/label is resolved first.
|
|
416
|
+
await client.setLabel('qa-system', 'production', { version: 2 });
|
|
417
|
+
await client.addTag('qa-system', 'release-candidate', { version: 2 });
|
|
418
|
+
await client.removeTag('qa-system', 'release-candidate', { version: 2 });
|
|
419
|
+
await client.deletePrompt('qa-system', { version: 1 });
|
|
380
420
|
|
|
381
|
-
//
|
|
382
|
-
|
|
421
|
+
// Explicit PromptClient instances own their cache and prompt requests.
|
|
422
|
+
client.close();
|
|
383
423
|
```
|
|
384
424
|
|
|
425
|
+
Each prompt version may have zero or one active label. Accordingly, `labels`
|
|
426
|
+
accepts at most one value on create/save, and `setLabel()` replaces or moves
|
|
427
|
+
that label rather than adding a second simultaneous label.
|
|
428
|
+
|
|
429
|
+
Latest and label selectors are fresh for `cacheTtlMs`. After that, they may be
|
|
430
|
+
served only for the bounded `staleWhileRevalidateMs` window while one shared
|
|
431
|
+
same-key refresh runs. Refresh failure leaves the last known value available
|
|
432
|
+
until that stale window ends; after it ends, the next lookup waits for the
|
|
433
|
+
backend and reports a typed error. A version selector is immutable in-process:
|
|
434
|
+
`{ version: 2 }` never changes into another version. Request a different
|
|
435
|
+
version explicitly, call `clearCache()`, or create a new client.
|
|
436
|
+
|
|
437
|
+
Every request has a finite `requestTimeoutMs`. `close()` aborts in-flight prompt
|
|
438
|
+
requests and releases the cache; calls after close raise
|
|
439
|
+
`PromptClientClosedError`. The shared prompt client created by `init()` is
|
|
440
|
+
closed by `shutdown()`, without making prompt failures part of telemetry flush
|
|
441
|
+
success. An explicitly constructed `PromptClient` must be closed by its owner.
|
|
442
|
+
|
|
443
|
+
#### Prompt privacy and ownership
|
|
444
|
+
|
|
445
|
+
Prompt CRUD is intentional product-data transfer, separate from trace
|
|
446
|
+
telemetry. The API key selects the Neatlogs project and authenticates prompt
|
|
447
|
+
requests to `baseUrl`; the in-memory cache retains prompt content only until
|
|
448
|
+
eviction, `clearCache()`, or `close()`. Server retention follows the managed
|
|
449
|
+
prompt service policy for that project.
|
|
450
|
+
|
|
451
|
+
Telemetry `mask=`, `pii`, and `piiSpanTypes` settings do **not** transform prompt
|
|
452
|
+
content sent to the prompt-management API. If prompt content must be redacted,
|
|
453
|
+
transform it explicitly before calling prompt CRUD. The SDK does not currently
|
|
454
|
+
provide a prompt transform and does not claim that telemetry masking protects
|
|
455
|
+
managed prompt payloads.
|
|
456
|
+
|
|
385
457
|
Module-level convenience functions are also available after `init()`:
|
|
386
458
|
|
|
387
459
|
```typescript
|
|
388
|
-
import { init, getPrompt, fetchPrompt, listPrompts, createPrompt, updatePrompt, saveAsVersion, deletePrompt, removeTag } from 'neatlogs';
|
|
460
|
+
import { init, getPrompt, fetchPrompt, listPrompts, createPrompt, updatePrompt, saveAsVersion, deletePrompt, setLabel, addTag, removeTag } from 'neatlogs';
|
|
389
461
|
|
|
390
462
|
await init({ apiKey: process.env.NEATLOGS_API_KEY });
|
|
391
463
|
|
|
@@ -395,16 +467,28 @@ const rendered = handle.compile({ name: 'world' });
|
|
|
395
467
|
|
|
396
468
|
---
|
|
397
469
|
|
|
398
|
-
### `flush()` / `shutdown()`
|
|
470
|
+
### `flush()` / `flushAll()` / `flushAllDetailed()` / `shutdown()`
|
|
399
471
|
|
|
400
472
|
```typescript
|
|
401
473
|
// Flush pending spans without shutting down
|
|
402
474
|
await flush();
|
|
403
475
|
|
|
476
|
+
// Flush the default pipeline and every live Neatlogs Client under one deadline
|
|
477
|
+
const flushed = await flushAll(30_000);
|
|
478
|
+
if (!flushed) console.error('One or more Neatlogs pipelines failed to flush');
|
|
479
|
+
|
|
480
|
+
// Inspect per-pipeline timeout and failure details when needed
|
|
481
|
+
const result = await flushAllDetailed(30_000);
|
|
482
|
+
if (!result.success) console.error(result.outcomes);
|
|
483
|
+
|
|
404
484
|
// Flush and shut down — call before process exit
|
|
405
485
|
await shutdown();
|
|
406
486
|
```
|
|
407
487
|
|
|
488
|
+
`flushAll()` and `flushAllDetailed()` only know about Neatlogs-owned pipelines.
|
|
489
|
+
They do not discover or flush Datadog, Langfuse, Braintrust, or a global
|
|
490
|
+
OpenTelemetry provider.
|
|
491
|
+
|
|
408
492
|
`shutdown()` resets all SDK state so `init()` can be called again if needed.
|
|
409
493
|
|
|
410
494
|
---
|
|
@@ -435,30 +519,36 @@ import { registerCrewaiTask } from 'neatlogs';
|
|
|
435
519
|
registerCrewaiTask('research-task', 'Research the latest AI developments');
|
|
436
520
|
```
|
|
437
521
|
|
|
438
|
-
## Supported
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
|
459
|
-
|
|
460
|
-
|
|
|
461
|
-
|
|
|
522
|
+
## Supported TypeScript Integrations
|
|
523
|
+
|
|
524
|
+
For `neatlogs >=1.1.19 <2.0.0`, use only the explicit helper shown below. The
|
|
525
|
+
SDK has no `instrumentations: [...]` loader. These helpers attach to the object,
|
|
526
|
+
callback surface, processor, or plugin you pass and use Neatlogs' private
|
|
527
|
+
context. Versioned rows below name the dependencies installed by this repository's test
|
|
528
|
+
matrix; API-shaped rows deliberately make no blanket semver claim.
|
|
529
|
+
|
|
530
|
+
| Library | Repository test/API baseline | Explicit helper | Import path |
|
|
531
|
+
|---|---|---|---|
|
|
532
|
+
| OpenAI | `openai` 6.34.x | `wrapOpenAI(client)` | `neatlogs` or `neatlogs/openai` |
|
|
533
|
+
| Anthropic | `@anthropic-ai/sdk` 0.68.x | `wrapAnthropic(client)` | `neatlogs` or `neatlogs/anthropic` |
|
|
534
|
+
| Azure OpenAI | `openai` 6.34.x | `wrapAzureOpenAI(client)` | `neatlogs/azure-openai` |
|
|
535
|
+
| AWS Bedrock Runtime | AWS SDK v3 command API | `wrapBedrock(client)` | `neatlogs/bedrock` |
|
|
536
|
+
| Google GenAI | `@google/genai` 1.34.x | `wrapGoogleGenAI(client)` / `wrapGoogleGenAIChat(chat)` | `neatlogs/google-genai` |
|
|
537
|
+
| Vertex AI through `@google/genai` | `@google/genai` 1.34.x | `wrapVertexAI(client)` / `wrapVertexAIChat(chat)` | `neatlogs/vertex-ai` |
|
|
538
|
+
| OpenRouter Agent | `@openrouter/agent` 0.7.x | `wrapOpenRouterAgent(client)` / `wrapCallModel(fn)` | `neatlogs/openrouter-agent` |
|
|
539
|
+
| Vercel AI SDK | `ai` 6.x | `wrapAISDK(ai)` | `neatlogs/ai` |
|
|
540
|
+
| Mastra | `@mastra/core` 1.32.x | `wrapMastra(entity)` / `wrapMastraRerank(fn)` | `neatlogs/mastra` |
|
|
541
|
+
| Claude Agent SDK | documented `query()` API | `wrapClaudeAgentSDK(sdk)` | `neatlogs/claude-agent-sdk` |
|
|
542
|
+
| LangChain / LangGraph | `@langchain/core` 0.3.x | `langchainHandler()` callback | `neatlogs` or `neatlogs/langchain` |
|
|
543
|
+
| OpenAI Agents SDK | documented `addTraceProcessor()` API | `openaiAgentsProcessor()` | `neatlogs` or `neatlogs/openai-agents` |
|
|
544
|
+
| Pi Agent | `agent-core` 0.73.x and 0.83.x | `piAgentHooks(agent)` / `tracePiAgentEvents(...)` / `tracePiStream(...)` | `neatlogs` or `neatlogs/pi-agent` |
|
|
545
|
+
| OpenCode | current plugin API | `NeatlogsOpencodePlugin` | `neatlogs/opencode` |
|
|
546
|
+
| Browser client | browser SDK API in this release | `Neatlogs` | `neatlogs/browser` |
|
|
547
|
+
|
|
548
|
+
Edge runtime packaging, the removed `instrumentations` init option, and Strands
|
|
549
|
+
global-context hooks are not supported. `strandsHooks()` remains an explicit
|
|
550
|
+
runtime rejection so an application cannot silently believe it is isolated or
|
|
551
|
+
instrumented.
|
|
462
552
|
|
|
463
553
|
```typescript
|
|
464
554
|
// Vercel AI SDK
|
|
@@ -468,16 +558,48 @@ import * as ai from 'ai';
|
|
|
468
558
|
import { openai } from '@ai-sdk/openai';
|
|
469
559
|
|
|
470
560
|
await init({ apiKey: process.env.NEATLOGS_API_KEY });
|
|
471
|
-
const { generateText } = wrapAISDK(ai);
|
|
561
|
+
const { generateText, ToolLoopAgent } = wrapAISDK(ai);
|
|
472
562
|
|
|
473
563
|
const { text } = await generateText({
|
|
474
564
|
model: openai('gpt-4o-mini'),
|
|
475
565
|
prompt: 'What is TypeScript?',
|
|
476
566
|
});
|
|
477
567
|
|
|
568
|
+
// AI SDK v6 agents are supported too. The wrapper injects telemetry into the
|
|
569
|
+
// constructor settings, including calls returned from a custom prepareCall.
|
|
570
|
+
const agent = new ToolLoopAgent({
|
|
571
|
+
id: 'support-agent',
|
|
572
|
+
model: openai('gpt-4o-mini'),
|
|
573
|
+
experimental_telemetry: { functionId: 'support-agent' },
|
|
574
|
+
});
|
|
575
|
+
await agent.generate({ prompt: 'Help me debug my order' });
|
|
576
|
+
|
|
478
577
|
await shutdown();
|
|
479
578
|
```
|
|
480
579
|
|
|
580
|
+
If a call already supplies an `experimental_telemetry.tracer` (for example,
|
|
581
|
+
Laminar), the wrapper mirrors the AI SDK's native spans to both that tracer and
|
|
582
|
+
Neatlogs. The caller-owned tracer remains the global context owner; Neatlogs
|
|
583
|
+
keeps separate parent context and export state in its private provider.
|
|
584
|
+
|
|
585
|
+
The same coexistence is available without the wrapper by passing the existing
|
|
586
|
+
tracer to `createAITelemetry`:
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
import { getTracer } from '@lmnr-ai/lmnr';
|
|
590
|
+
import { streamText } from 'ai';
|
|
591
|
+
import { createAITelemetry } from 'neatlogs/ai';
|
|
592
|
+
|
|
593
|
+
await streamText({
|
|
594
|
+
model,
|
|
595
|
+
prompt,
|
|
596
|
+
experimental_telemetry: createAITelemetry({
|
|
597
|
+
tracer: getTracer(),
|
|
598
|
+
functionId: 'progress-narration',
|
|
599
|
+
}),
|
|
600
|
+
});
|
|
601
|
+
```
|
|
602
|
+
|
|
481
603
|
## Configuration
|
|
482
604
|
|
|
483
605
|
### Environment Variables
|
|
@@ -486,6 +608,7 @@ await shutdown();
|
|
|
486
608
|
|----------|-------------|
|
|
487
609
|
| `NEATLOGS_API_KEY` | API key (fallback when `apiKey` option is not provided) |
|
|
488
610
|
| `NEATLOGS_DISABLE_EXPORT` | Set to `true`, `1`, or `yes` to disable export |
|
|
611
|
+
| `NEATLOGS_UPLOADS_ENABLED` | Set to `true`, `1`, or `yes` to enable authenticated typed-media and oversized-OTLP uploads |
|
|
489
612
|
|
|
490
613
|
### Programmatic Configuration
|
|
491
614
|
|
|
@@ -499,7 +622,6 @@ await init({
|
|
|
499
622
|
userId: 'user-456',
|
|
500
623
|
tags: ['production', 'v2'],
|
|
501
624
|
metadata: { environment: 'prod' },
|
|
502
|
-
instrumentations: ['openai', 'anthropic'],
|
|
503
625
|
sampleRate: 0.5,
|
|
504
626
|
captureLogs: true,
|
|
505
627
|
debug: true,
|
|
@@ -575,7 +697,7 @@ See the [`examples/`](./examples/) directory for complete, runnable examples:
|
|
|
575
697
|
|
|
576
698
|
| File | Description |
|
|
577
699
|
|------|-------------|
|
|
578
|
-
| [`basic-openai.ts`](./examples/basic-openai.ts) | Basic OpenAI usage with
|
|
700
|
+
| [`basic-openai.ts`](./examples/basic-openai.ts) | Basic OpenAI usage with an explicit wrapper |
|
|
579
701
|
| [`prompt-management.ts`](./examples/prompt-management.ts) | PromptTemplate + trace() for prompt versioning |
|
|
580
702
|
| [`multi-agent-workflow.ts`](./examples/multi-agent-workflow.ts) | Nested spans: WORKFLOW → AGENT → TOOL |
|
|
581
703
|
| [`custom-spans.ts`](./examples/custom-spans.ts) | All span kinds: WORKFLOW, CHAIN, AGENT, TOOL, RETRIEVER, EMBEDDING, GUARDRAIL |
|