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.
Files changed (76) hide show
  1. package/README.md +206 -84
  2. package/dist/ai-sdk.cjs +219 -15
  3. package/dist/ai-sdk.cjs.map +1 -1
  4. package/dist/ai-sdk.d.ts +17 -7
  5. package/dist/ai-sdk.mjs +222 -16
  6. package/dist/ai-sdk.mjs.map +1 -1
  7. package/dist/anthropic.cjs +917 -80
  8. package/dist/anthropic.cjs.map +1 -1
  9. package/dist/anthropic.mjs +921 -81
  10. package/dist/anthropic.mjs.map +1 -1
  11. package/dist/azure-openai.cjs +1166 -96
  12. package/dist/azure-openai.cjs.map +1 -1
  13. package/dist/azure-openai.mjs +1170 -97
  14. package/dist/azure-openai.mjs.map +1 -1
  15. package/dist/bedrock.cjs +928 -67
  16. package/dist/bedrock.cjs.map +1 -1
  17. package/dist/bedrock.mjs +932 -68
  18. package/dist/bedrock.mjs.map +1 -1
  19. package/dist/browser.cjs +29 -3
  20. package/dist/browser.cjs.map +1 -1
  21. package/dist/browser.d.ts +1 -1
  22. package/dist/browser.mjs +27 -3
  23. package/dist/browser.mjs.map +1 -1
  24. package/dist/claude-agent-sdk.cjs +27 -7
  25. package/dist/claude-agent-sdk.cjs.map +1 -1
  26. package/dist/claude-agent-sdk.mjs +27 -7
  27. package/dist/claude-agent-sdk.mjs.map +1 -1
  28. package/dist/cli.cjs +13061 -0
  29. package/dist/cli.cjs.map +1 -0
  30. package/dist/cli.d.ts +1 -0
  31. package/dist/cli.mjs +13060 -0
  32. package/dist/cli.mjs.map +1 -0
  33. package/dist/google-genai.cjs +867 -46
  34. package/dist/google-genai.cjs.map +1 -1
  35. package/dist/google-genai.d.ts +2 -2
  36. package/dist/google-genai.mjs +871 -47
  37. package/dist/google-genai.mjs.map +1 -1
  38. package/dist/index.cjs +11465 -3944
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.ts +1667 -68
  41. package/dist/index.mjs +11563 -4052
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/langchain.cjs +69 -7
  44. package/dist/langchain.cjs.map +1 -1
  45. package/dist/langchain.mjs +73 -8
  46. package/dist/langchain.mjs.map +1 -1
  47. package/dist/mastra-wrap.cjs +21 -6
  48. package/dist/mastra-wrap.cjs.map +1 -1
  49. package/dist/mastra-wrap.mjs +21 -6
  50. package/dist/mastra-wrap.mjs.map +1 -1
  51. package/dist/openai-agents.cjs +19 -4
  52. package/dist/openai-agents.cjs.map +1 -1
  53. package/dist/openai-agents.mjs +19 -4
  54. package/dist/openai-agents.mjs.map +1 -1
  55. package/dist/openai.cjs +1406 -210
  56. package/dist/openai.cjs.map +1 -1
  57. package/dist/openai.mjs +1410 -211
  58. package/dist/openai.mjs.map +1 -1
  59. package/dist/opencode-plugin.cjs +8 -7
  60. package/dist/opencode-plugin.cjs.map +1 -1
  61. package/dist/opencode-plugin.d.ts +0 -2
  62. package/dist/opencode-plugin.mjs +8 -7
  63. package/dist/opencode-plugin.mjs.map +1 -1
  64. package/dist/openrouter-agent.cjs +106 -19
  65. package/dist/openrouter-agent.cjs.map +1 -1
  66. package/dist/openrouter-agent.mjs +110 -20
  67. package/dist/openrouter-agent.mjs.map +1 -1
  68. package/dist/pi-agent.cjs +21 -6
  69. package/dist/pi-agent.cjs.map +1 -1
  70. package/dist/pi-agent.mjs +21 -6
  71. package/dist/pi-agent.mjs.map +1 -1
  72. package/dist/vertex-ai.cjs +867 -46
  73. package/dist/vertex-ai.cjs.map +1 -1
  74. package/dist/vertex-ai.mjs +871 -47
  75. package/dist/vertex-ai.mjs.map +1 -1
  76. 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. Create your LLM client AFTER init()
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
- For auto-instrumentation of specific LLM providers, install the corresponding peer dependency:
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, exporters, and instrumentation |
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
- ### Important: Initialization Order
57
+ ## Doctor v2
86
58
 
87
- `init()` is **async** and must be called **before** creating any LLM client instances. This is because instrumentation works by monkey-patching libraries at init time.
59
+ Run the local SDK pipeline check without credentials or network access:
88
60
 
89
- ```typescript
90
- // Correct
91
- await init({ instrumentations: ['openai'] });
92
- const client = new OpenAI(); // patched
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
- // Wrong client created before patching
95
- const client = new OpenAI(); // NOT patched
96
- await init({ instrumentations: ['openai'] });
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' &#124; 'hash' &#124; 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` | `SpanKind` | `'CHAIN'` | Span 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://app.neatlogs.com',
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
- // Update prompt content
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', { label: 'v2' });
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
- // Delete a prompt
382
- await client.deletePrompt('qa-system');
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 Instrumentations
439
-
440
- ### Isolation policy
441
-
442
- Neatlogs always runs on a private provider and private async context. Third-party
443
- auto-instrumentors that call the global OpenTelemetry context API cannot provide
444
- bidirectional isolation, so the manager rejects them at initialization before
445
- creating any provider state. Use the explicit provider/framework wrappers
446
- instead.
447
-
448
- ### Registry Entries (not yet instrumented in TypeScript)
449
-
450
- The following libraries are registered in the instrumentation registry for future support. Passing them to `instrumentations` will log a debug message and skip gracefully:
451
-
452
- `cohere`, `groq`, `together`, `vertexai`, `google_generativeai`, `mistralai`, `ollama`, `watsonx`, `alephalpha`, `replicate`, `sagemaker`, `huggingface_hub`, `litellm`, `langgraph`, `llamaindex`, `autogen`, `haystack`, `dspy`, `chromadb`, `pinecone`, `weaviate`, `qdrant`, `milvus`, `opensearch`, `elasticsearch`, `redis`, `marqo`, `instructor`, `guardrails`, `google_adk`, `agno`, `openai_agents`, `pydantic_ai`, `smolagents`, `strands`, `pipecat`, `portkey`, `promptflow`
453
-
454
- ## Framework Integrations
455
-
456
- For frameworks that don't fit the auto-instrument-on-init pattern, use the SDK's explicit wrappers. These wrappers use Neatlogs' private context and remain isolated from other tracing SDKs:
457
-
458
- | Framework | Helper |
459
- |-----------|--------|
460
- | Mastra (`@mastra/core`) | `wrapMastra()` from `neatlogs/mastra` |
461
- | Vercel AI SDK (`ai`) | `wrapAISDK()` from `neatlogs/ai` |
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 auto-instrumentation |
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 |