@tracehatch/sdk 0.3.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/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0
4
+
5
+ - Use only the Tracehatch client, environment variables and request headers.
6
+ - Remove retired class aliases and configuration fallbacks.
7
+ - Use Tracehatch names for process state, identifier hashes, conversation
8
+ fingerprints, capture metadata and product-specific span attributes.
9
+ - Keep server-only capture, ESM/CommonJS shared context and the hosted API default.
package/GUIDE.md ADDED
@@ -0,0 +1,387 @@
1
+ # Tracehatch SDK guide
2
+
3
+ Record agent runs, model calls, tool steps and sessions in Tracehatch from Node.js
4
+ 18 or newer. The package supports ESM and CommonJS and has no runtime
5
+ dependencies.
6
+
7
+ ## Install and configure
8
+
9
+ Install the SDK in the **server package that makes model calls**:
10
+
11
+ ```sh
12
+ npm install @tracehatch/sdk@0.3.0
13
+ # Or: pnpm add @tracehatch/sdk@0.3.0
14
+ # Or: yarn add @tracehatch/sdk@0.3.0
15
+ ```
16
+
17
+ The package is MIT licensed. Your dashboard at [tracehatch.com](https://tracehatch.com)
18
+ also provides the same SDK as a versioned archive when you need that installation path:
19
+
20
+ ```sh
21
+ npm install https://tracehatch.com/downloads/tracehatch-sdk-0.3.0.tgz
22
+ ```
23
+
24
+ Create a project API key in Tracehatch. The key selects the project and environment.
25
+ Configuration comes from the environment:
26
+
27
+ | Variable | Purpose |
28
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
29
+ | `TRACEHATCH_API_KEY` | Required. Without it the SDK stays disabled and sends nothing. |
30
+ | `TRACEHATCH_BASE_URL` | Optional. Your API origin for a self-hosted or local Tracehatch; `/api/v1` bases work too. Defaults to `https://api.tracehatch.com`. |
31
+ | `TRACEHATCH_AGENT` | Optional. Agent name; defaults to the nearest `package.json` name. |
32
+ | `TRACEHATCH_RELEASE` | Optional. Release; defaults to `VERCEL_GIT_COMMIT_SHA`, `GITHUB_SHA` and similar, then git `HEAD`. |
33
+
34
+ Keep the key in the server environment and never expose it in browser code.
35
+
36
+ Load the SDK before anything else so provider clients are created after it:
37
+
38
+ ```sh
39
+ node --import @tracehatch/sdk/auto server.js
40
+ ```
41
+
42
+ ```ts
43
+ // or, as the first line of the entry file
44
+ import "@tracehatch/sdk/auto"
45
+ ```
46
+
47
+ CommonJS: `require("@tracehatch/sdk/auto")`. Next.js: create
48
+ `instrumentation.ts` beside `app` or `pages`, inside `src` when the application
49
+ uses `src/app` or `src/pages`:
50
+
51
+ ```ts
52
+ export async function register() {
53
+ if (process.env.NEXT_RUNTIME === "nodejs")
54
+ await import("@tracehatch/sdk/auto")
55
+ }
56
+ ```
57
+
58
+ The auto entry calls `init()` with the environment. Call `init()` yourself
59
+ instead when you want options:
60
+
61
+ ```ts
62
+ import { init } from "@tracehatch/sdk"
63
+
64
+ init({
65
+ agent: "support-agent",
66
+ captureBodies: false,
67
+ redact: { rules: [{ name: "customer", pattern: /CUSTOMER-\d+/g }] },
68
+ sampling: { rate: 0.25 },
69
+ })
70
+ ```
71
+
72
+ `init` options: `apiKey`, `baseUrl`, `agent`, `release`, `captureBodies`
73
+ (default `true`), `redact` (`false` or `{ builtIns?, rules? }`), `sampling`
74
+ (`{ rate }`, head sampling per run), `debug`, `flushOnExit` (default `true`).
75
+ Unknown options are rejected. `init()` replaces an earlier client and installs
76
+ the capture hooks; `shutdown()` removes them.
77
+
78
+ ## Check the connection
79
+
80
+ Save this as `tracehatch-check.mjs` in the consuming package, load
81
+ `TRACEHATCH_API_KEY` (and `TRACEHATCH_BASE_URL` for a local API) into the process
82
+ with your existing configuration, then run `node tracehatch-check.mjs`. On Node 22
83
+ or newer `node --env-file=.env tracehatch-check.mjs` also works.
84
+
85
+ ```js
86
+ import "@tracehatch/sdk/auto"
87
+ import { trace, flushWithResult, shutdown } from "@tracehatch/sdk"
88
+
89
+ try {
90
+ const traceId = await trace("tracehatch-setup-check", (run) => run.id)
91
+ const result = await flushWithResult()
92
+ if (result.status !== "accepted")
93
+ throw new Error(`Delivery was not confirmed: ${JSON.stringify(result)}`)
94
+ console.log({ traceId, delivery: result.status })
95
+ } finally {
96
+ await shutdown()
97
+ }
98
+ ```
99
+
100
+ `accepted` requires the API's `202` receipt with a matching span count. It
101
+ proves ingestion acceptance; the project's trace view confirms processing. A
102
+ web page at the wrong URL, a rejected key, a timeout and disabled tracing cannot
103
+ be mistaken for a successful check.
104
+
105
+ ## What is captured
106
+
107
+ Capture happens at the HTTP boundary: the SDK observes the runtime's global
108
+ `fetch`, so any client or framework that uses it is recorded without wrapping.
109
+ The request body names the model call; the response is read from a clone while
110
+ your code consumes the original. A capture failure never changes the response
111
+ or the error your application receives.
112
+
113
+ | Request | Recorded as |
114
+ | ------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
115
+ | `POST …/chat/completions` | `generation` span, `chat.completions` |
116
+ | `POST …/responses`, `GET …/responses/{id}`, `POST …/responses/{id}/cancel` | `generation` span, `responses`; polls complete a background response |
117
+ | `POST …/embeddings` | `embedding` span |
118
+ | `POST …/messages` on `api.anthropic.com`, or with an `anthropic-version` header | `generation` span, `messages` |
119
+
120
+ `gen_ai.system` is `openai` or `anthropic` on the official hosts, a known name
121
+ for Azure OpenAI, Groq, Mistral, Together, OpenRouter, DeepSeek, xAI,
122
+ Perplexity, Fireworks, Cerebras, Gemini's OpenAI-compatible endpoint and
123
+ Ollama, and the hostname otherwise. Pricing follows the model name when the
124
+ system is unknown.
125
+
126
+ Recorded per call: model, request settings, reported token usage (including
127
+ cached and cache-creation input and reasoning tokens), finish reasons, tool
128
+ call counts, time to first token and tokens per second for streams, the HTTP
129
+ status, provider error types (`rate_limit`, `timeout`, `auth`,
130
+ `invalid_request`, `provider_error`, `incomplete_stream`,
131
+ `incomplete_response`) and, with body capture on, the request, messages and
132
+ assembled output. A provider client's retry of the same request within a minute
133
+ of a failure is recorded as attempt 2, 3 and so on.
134
+
135
+ Streams: the SDK reads its own copy while your code reads the response, so a
136
+ stream returned out of a `trace()` callback and consumed later is still
137
+ recorded; the run's end waits for it, bounded by two minutes, and `flush()`
138
+ waits for such ends too. A stream your code neither reads nor cancels is
139
+ recorded as cancelled when that bound passes. Cancelling through an `AbortSignal` records a
140
+ cancelled span. For OpenAI chat streams `stream_options.include_usage: true` is
141
+ added when you have not set the option, so usage is reported; an explicit
142
+ `false` stays false.
143
+
144
+ Not captured: clients constructed before the SDK loaded (they keep the original
145
+ `fetch`), clients given their own `fetch` option, non-JSON request bodies such
146
+ as audio uploads, and endpoints outside the table.
147
+
148
+ ## Runs, sessions and tools without code
149
+
150
+ **Runs.** Inside an inbound HTTP request handled by `http.Server` or
151
+ `https.Server` (Express, Fastify, NestJS, Next.js) every model call belongs to
152
+ one run named `METHOD /path`; the run is sent only when a model call or an
153
+ explicit span happened, ends when the response finishes, and is marked failed
154
+ on a 5xx status. Outside a request (scripts, queues, workers) a model call
155
+ starts a run. If the response asks for tools, the run stays open for the tool
156
+ step and the follow-up call that carries the tool results; a response without
157
+ tool calls, a failure, a new user message, ten idle minutes or process exit
158
+ ends it. Explicit `trace()` runs take precedence over both.
159
+
160
+ Automatic runs also populate their transcript with the current user message
161
+ from the first provider call and the latest textual model answer. Tool
162
+ arguments and reasoning remain on the generation span. Explicit traces keep
163
+ application-supplied input and output. Inferred transcripts use the same
164
+ redaction, truncation, and `captureBodies: false` policy as other bodies.
165
+
166
+ **Sessions and users.** In order: the `x-tracehatch-session-id` and
167
+ `x-tracehatch-user-id` request headers, `setSession()` / `setUser()`, the OpenAI
168
+ Responses `conversation` id or `previous_response_id`, then a fingerprint of
169
+ the conversation's system prompt and first user message, which every later
170
+ turn resends. Derived session ids look like `auto-` followed by 32 hex
171
+ characters and are identical across processes, restarts and the gateway. The
172
+ OpenAI `user` field and Anthropic `metadata.user_id` name the end user.
173
+
174
+ **Tools.** Tool calls in a response are paired with the tool results in the
175
+ next request (chat `tool` messages, Responses `function_call_output` items,
176
+ Anthropic `tool_result` blocks) and recorded as `tool` spans with the call id,
177
+ name, arguments, output, error flag and the time between the two calls.
178
+
179
+ When timing that same provider-requested tool with `tool()`, include
180
+ `attributes: { "tool.call_id": call.id }` in its options. The explicit span then
181
+ takes precedence over the inferred span, retaining its real timing and retry
182
+ events. A matching name alone cannot identify one tool execution reliably.
183
+
184
+ **Identity.** The run's `agent` is the nearest `package.json` name and the
185
+ `release` is the deployment's commit unless `init` or the environment says
186
+ otherwise. Automatic runs carry `metadata["tracehatch.capture"] = "auto"`.
187
+
188
+ ## Precision when you want it
189
+
190
+ The explicit API works alongside automatic capture; model calls made inside a
191
+ `trace()` become children of it.
192
+
193
+ ```ts
194
+ import OpenAI from "openai"
195
+ import { trace, tool, setSession, setUser, flush } from "@tracehatch/sdk"
196
+
197
+ const openai = new OpenAI()
198
+
199
+ await trace("answer question", async (run) => {
200
+ setSession("conversation-42")
201
+ setUser({ id: "user-7" })
202
+ const context = await tool("search docs", async () => "Refunds take 5 days")
203
+ const answer = await openai.chat.completions.create({
204
+ model: "YOUR_EXISTING_MODEL_ID",
205
+ messages: [{ role: "user", content: `Explain: ${context}` }],
206
+ })
207
+ run.addTags("support")
208
+ return answer
209
+ })
210
+ await flush()
211
+ ```
212
+
213
+ Both `trace` and `span` return promises; await them even for synchronous
214
+ callbacks. For an explicit lifetime:
215
+
216
+ ```ts
217
+ import { startTrace, span, shutdown } from "@tracehatch/sdk"
218
+
219
+ const run = startTrace("import documents", { tags: ["batch"] })
220
+ try {
221
+ await run.run(() => span("parse", "custom", async () => "parsed"))
222
+ run.end({ output: { imported: 1 } })
223
+ } catch (error) {
224
+ run.end({ outcome: "error", error })
225
+ throw error
226
+ } finally {
227
+ await shutdown()
228
+ }
229
+ ```
230
+
231
+ Trace handles support `setInput`, `setOutput`, `setUser`, `setSession`,
232
+ `addTags`, `setMetadata` and `score`. Span handles support `setOutput`,
233
+ `setAttributes` and `addEvent(name, attributes?, level?)`. Top-level context
234
+ helpers update the active run. Concurrent spans keep their own parents. Nested
235
+ traces receive `metadata.parent_trace_id`. A `span()` or `tool()` recorded
236
+ outside any run becomes a run of its own.
237
+
238
+ `tool(name, fn, { retries: 2, backoffMs: 100 })` makes up to three attempts in
239
+ one span, with an event per attempt. Retries default to zero. Only opt into
240
+ retries when the tool operation can safely be repeated. Provider client
241
+ retries are recorded as separate attempts of the generation.
242
+
243
+ For a provider the SDK does not recognise, record the call yourself:
244
+
245
+ ```ts
246
+ import { trace, span } from "@tracehatch/sdk"
247
+
248
+ await trace("answer question", () =>
249
+ span("model call", "generation", async (step) => {
250
+ const result = await existingModelCall()
251
+ step.setAttributes({
252
+ "gen_ai.system": existingProviderName,
253
+ "gen_ai.request.model": existingModelId,
254
+ })
255
+ return result
256
+ })
257
+ )
258
+ ```
259
+
260
+ ## Scores
261
+
262
+ Record numeric or categorical scores while the run is open:
263
+
264
+ ```ts
265
+ import { trace, span, score } from "@tracehatch/sdk"
266
+
267
+ await trace("answer question", async (run) => {
268
+ await span("check answer", "custom", async (step) => {
269
+ score({ name: "correctness", value: "pass", spanId: step.id })
270
+ })
271
+ run.score({ name: "confidence", value: 0.95, comment: "Evidence matched" })
272
+ })
273
+ ```
274
+
275
+ `score({ name, value, comment?, spanId? })` uses the current run;
276
+ `run.score(...)` works with a manual `startTrace` handle too. Without `spanId`,
277
+ the score belongs to the run. Call before `run.end()` or before the trace
278
+ callback returns. Calls outside a recording run, after end, or with invalid
279
+ values are ignored. There are at most 100 SDK scores per run; each gets a
280
+ stable `scr_` id so retries cannot create duplicates. Numeric values must be
281
+ finite; categorical values must be nonempty. Names, categories and comments
282
+ are redacted and bounded to 128, 256 and 2,048 characters respectively.
283
+
284
+ Scores travel with subsequent completed spans, including the final root. Flush
285
+ after the run ends to send its final scores. The worker keeps a span-targeted
286
+ score pending until that span arrives and its project, environment and run
287
+ match. Scores are private project data available in the trace scores API;
288
+ public share links omit them.
289
+
290
+ ## Data and delivery
291
+
292
+ Body capture defaults to on. Built-in redaction masks email addresses, phone
293
+ numbers, valid card-shaped strings, IBANs, and common API key/secret patterns.
294
+ Credential fields are masked too. It runs on bodies, attributes, metadata,
295
+ errors, score text, and user details before they enter the queue. Detection is
296
+ heuristic; choose `captureBodies: false` when prompts and outputs must be
297
+ excluded entirely.
298
+
299
+ Session and user ids need stable grouping. If redaction would change an id, or
300
+ the id exceeds the wire's 128-character limit, the SDK sends a deterministic
301
+ SHA-256 pseudonym of the complete original id instead of a shared marker or
302
+ truncated prefix. Session and user pseudonyms use separate hash domains; safe,
303
+ bounded ids remain unchanged. These are pseudonyms, not anonymous values: the
304
+ hashes are unkeyed, so guessed low-entropy identifiers can be checked against
305
+ them. Prefer opaque identifiers.
306
+
307
+ With body capture off, span byte counts remain available; input, output and
308
+ messages are omitted, including trace-level bodies. `redact: false` explicitly
309
+ disables masking. Large bodies are truncated to a bounded head and tail.
310
+ Cycles, unsupported values and throwing getters cannot break your code.
311
+ Streamed output is assembled up to a bound; beyond it the span is marked
312
+ truncated and keeps the full byte count.
313
+
314
+ The queue holds at most 10 MB, including trace envelopes. It sends up to 100
315
+ spans per batch after two seconds, retries transient failures, honours
316
+ `Retry-After`, and splits oversized batches. Oldest queued spans are dropped
317
+ when full. `init()` returns a client with `stats()` to inspect queued and
318
+ dropped spans.
319
+
320
+ `await flushWithResult(timeoutMs?)` returns `status`, `acceptedSpans`,
321
+ `droppedSpans`, `pendingSpans` and optional `lastError: { code, httpStatus? }`.
322
+ The status is `disabled` without an initialised client, `empty` before any
323
+ recorded delivery, `accepted` only when all queued work has been acknowledged
324
+ without loss, `timeout` while work is pending, or `failed` after any loss.
325
+
326
+ `sampling.rate` is head sampling: the decision is made per run when it starts,
327
+ so spans of an unsampled run are never sent. While a workspace is over its
328
+ monthly trace allowance the API answers each batch with a lower advisory rate;
329
+ the SDK applies it to new runs, logs a warning once, and returns to the
330
+ configured rate as soon as the hint stops. At three times the allowance the API
331
+ rejects batches with `quota_exceeded` and a `Retry-After`; the SDK retries with
332
+ backoff and eventually drops those spans.
333
+
334
+ Exit: the queue is flushed on `beforeExit` and, with a two-second bound, on
335
+ `SIGTERM` and `SIGINT`; when nothing else handles the signal the SDK re-raises
336
+ it afterwards so the process still exits. Open automatic runs are ended first.
337
+ Vercel functions receive the final flush through `waitUntil`. On AWS Lambda,
338
+ Netlify and similar hosts `await flush()` before the handler returns. `flush()`
339
+ never rejects and waits up to five seconds by default. Call `shutdown()` only
340
+ when the process is finished: it flushes, stops timers and removes the capture
341
+ hooks.
342
+
343
+ ## Prompt for your coding assistant
344
+
345
+ Copy this prompt into the AI working in your application repository. Do not
346
+ paste an API key into a prompt; give it only the package version and, for a
347
+ self-hosted API, the API origin.
348
+
349
+ ```text
350
+ Integrate Tracehatch observability into this application. First inspect the
351
+ runtime, server entry point and package manager/lockfile. Preserve our current
352
+ provider, model, credentials, retries and behavior.
353
+
354
+ Install @tracehatch/sdk@0.3.0 from npm and verify the exact package name and
355
+ version. If the application uses the dashboard-hosted archive instead, preserve
356
+ that installation method and use its versioned SDK URL.
357
+
358
+ For Node.js, install it in the server package that makes model calls. Read
359
+ TRACEHATCH_API_KEY (and TRACEHATCH_BASE_URL only for a self-hosted API) through our
360
+ existing secret configuration; never print or commit a key or put it in
361
+ client-side/public environment variables. Load the SDK before provider clients
362
+ are created: `node --import @tracehatch/sdk/auto` or
363
+ `import "@tracehatch/sdk/auto"` as the first import of the entry
364
+ file; in Next.js use instrumentation.ts with the nodejs runtime check.
365
+ Model calls, inbound requests, sessions and tool steps are recorded without
366
+ further changes; add trace()/tool()/setSession() only where we want explicit
367
+ naming. Await flush() before short-lived processes and Lambda handlers return.
368
+
369
+ Start with the connection check from the SDK guide, require status "accepted",
370
+ print the trace id and verify that exact trace in the selected Tracehatch project.
371
+ Keep body capture on unless our data policy says otherwise; init({ captureBodies:
372
+ false }) turns it off. Run focused checks, show the changed files and report
373
+ receipt evidence and anything you could not verify.
374
+ ```
375
+
376
+ ## Maintainers
377
+
378
+ `pnpm --filter @tracehatch/sdk test:package:isolated` rebuilds,
379
+ packs, installs the archive into a clean offline consumer with install scripts
380
+ disabled, and verifies the ESM, CommonJS and auto entries share one client. It
381
+ does not publish anything or call a model or API deployment.
382
+
383
+ From this repository, `pnpm --filter @tracehatch/sdk sample` runs a
384
+ small agent without any external model dependency. With an API key configured
385
+ (and `TRACEHATCH_BASE_URL` for a local API), it sends a root, a tool and a
386
+ retrieval span to your API. `pnpm --filter @tracehatch/sdk fixture`
387
+ regenerates the API's e2e fixture from the public surface.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Unravel contributors
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,134 @@
1
+ # Tracehatch SDK
2
+
3
+ Record supported model calls, tool steps and sessions from your Node.js agent.
4
+ See each run in Tracehatch: what called what, where it failed, how long it
5
+ took and what it cost.
6
+
7
+ ## Setup
8
+
9
+ For guided installation, open your project in Tracehatch and copy its setup command.
10
+ Run it in your existing server application. The installer detects the framework
11
+ and package manager, connects through your browser, and previews its file changes.
12
+ It starts with prompt/output capture disabled and lets you choose what to record.
13
+
14
+ For manual installation, install in the **server package that makes model calls**:
15
+
16
+ ```sh
17
+ npm install @tracehatch/sdk@0.3.0
18
+ ```
19
+
20
+ The hosted API default is `https://api.tracehatch.com`. Open your project at
21
+ [tracehatch.com](https://tracehatch.com) to view its runs.
22
+
23
+ For an installation that uses the dashboard-hosted archive:
24
+
25
+ ```sh
26
+ npm install https://tracehatch.com/downloads/tracehatch-sdk-0.3.0.tgz
27
+ ```
28
+
29
+ Create a project API key in Tracehatch and set it in your server's environment:
30
+
31
+ ```dotenv
32
+ TRACEHATCH_API_KEY=your-project-api-key
33
+ ```
34
+
35
+ Use `.env.local` for Next.js. Other Node apps need their existing environment
36
+ loader or Node.js 22+ `--env-file` option; writing an `.env` file alone does not
37
+ load it. Keep the file ignored by Git and restart the server after changing it.
38
+
39
+ Start a plain Node app with the SDK loaded first:
40
+
41
+ ```sh
42
+ node --import @tracehatch/sdk/auto server.js
43
+ ```
44
+
45
+ or make `import "@tracehatch/sdk/auto"` the first line of your entry
46
+ file (`require("@tracehatch/sdk/auto")` in CommonJS). For a
47
+ self-hosted or local Tracehatch API, also set `TRACEHATCH_BASE_URL`. Hosted Tracehatch
48
+ uses the default API address.
49
+
50
+ Next.js initializes the SDK in `instrumentation.ts`, beside `app` or `pages`
51
+ (inside `src` when applicable). See `GUIDE.md` for the Node-runtime recipe.
52
+ The automatic import captures bodies by default; use explicit
53
+ `init({ captureBodies: false })` to omit prompts and outputs.
54
+
55
+ Restart your app, trigger one of its existing AI actions, and open the matching
56
+ run in **Traces**. A successful connection check confirms delivery separately;
57
+ it does not prove that your application initialized the SDK or captured a model.
58
+
59
+ ## What is recorded
60
+
61
+ - **Model calls** made by any client or framework through `fetch`: OpenAI
62
+ chat, Responses and embeddings; Anthropic messages; OpenAI-compatible hosts
63
+ such as Azure OpenAI, Groq, Mistral, Together, OpenRouter, DeepSeek, xAI,
64
+ Fireworks, Cerebras, Gemini's compatible endpoint and Ollama. Streams are
65
+ assembled; tokens, time to first token, finish reasons, provider errors and
66
+ client retries are captured.
67
+ - **Runs**: one per inbound HTTP request that made a model call, or one per
68
+ agent loop for calls outside a request. A response that asks for tools and
69
+ the follow-up call with the tool results belong to the same run.
70
+ - **Sessions and users**: the `x-tracehatch-session-id` and `x-tracehatch-user-id`
71
+ request headers, OpenAI `conversation` / `previous_response_id`, the `user`
72
+ field or Anthropic `metadata.user_id`, otherwise a fingerprint of the system
73
+ prompt and first user message, so every turn of a conversation lands in one
74
+ session.
75
+ - **Tool steps**: tool calls in a response paired with the tool results in the
76
+ next request become tool spans with arguments, output and duration.
77
+ - **Agent and release**: the nearest `package.json` name (or `TRACEHATCH_AGENT`)
78
+ and the deployment's commit (platform variables, git `HEAD`, or
79
+ `TRACEHATCH_RELEASE`).
80
+
81
+ ## Add precision where you want it
82
+
83
+ ```ts
84
+ import { trace, tool, setSession, flush } from "@tracehatch/sdk"
85
+
86
+ await trace("answer question", async (run) => {
87
+ setSession("conversation-42")
88
+ const docs = await tool("search docs", () => search(question))
89
+ // Model calls made in here are children of this run.
90
+ const answer = await answerWith(docs)
91
+ run.score({ name: "confidence", value: 0.9 })
92
+ return answer
93
+ })
94
+ await flush() // before a short-lived process or Lambda invocation returns
95
+ ```
96
+
97
+ ## Check the connection
98
+
99
+ ```js
100
+ import "@tracehatch/sdk/auto"
101
+ import { trace, flushWithResult, shutdown } from "@tracehatch/sdk"
102
+
103
+ const traceId = await trace("tracehatch-setup-check", (run) => run.id)
104
+ console.log(await flushWithResult(), traceId)
105
+ await shutdown()
106
+ ```
107
+
108
+ `status: "accepted"` means the API stored the batch; open the trace id in your
109
+ project to confirm processing.
110
+
111
+ ## Deploy after local verification
112
+
113
+ Commit the reviewed initialization, package manifest and lockfile. Create a
114
+ production environment key in Tracehatch and add it to your hosting provider's
115
+ private server settings. Local environment files are not deployed by the
116
+ installer. Redeploy, trigger a real AI action and inspect it in Tracehatch with
117
+ the production environment selected.
118
+
119
+ ## Things to know
120
+
121
+ - Load the SDK before provider clients are created; they take `fetch` when
122
+ constructed. A client given its own `fetch` option is not captured.
123
+ - Node.js 18+, ESM, CommonJS and TypeScript, no runtime dependencies. Server
124
+ code only; never ship the key or the SDK to a browser.
125
+ - Serverless: Vercel functions hand the final flush to `waitUntil`; on AWS
126
+ Lambda `await flush()` before returning.
127
+ - `init({ captureBodies: false })` records sizes and usage without prompts or
128
+ outputs. Built-in redaction masks common secrets and personal data before
129
+ send, but it can miss values.
130
+
131
+ Full configuration, capture rules and provider details are in `GUIDE.md`,
132
+ included in the installed package.
133
+
134
+ MIT licensed.
package/dist/auto.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var chunkU5REKR34_cjs=require('./chunk-U5REKR34.cjs');chunkU5REKR34_cjs.a.client||chunkU5REKR34_cjs.m();//# sourceMappingURL=auto.cjs.map
2
+ //# sourceMappingURL=auto.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auto.ts"],"names":["state","init"],"mappings":"mEASKA,mBAAAA,CAAM,QAAQC,mBAAAA,EAAK","file":"auto.cjs","sourcesContent":["/**\n * `@tracehatch/sdk/auto`: import first (or `node --import`) and\n * every model call, inbound request and tool step is recorded with the\n * settings in `TRACEHATCH_API_KEY`, `TRACEHATCH_BASE_URL`, `TRACEHATCH_AGENT` and\n * `TRACEHATCH_RELEASE`. An explicit `init()` made earlier is kept.\n */\nimport { state } from \"./context.js\"\nimport { init } from \"./init.js\"\n\nif (!state.client) init()\n"]}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/auto.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/auto.js ADDED
@@ -0,0 +1,2 @@
1
+ import {a,m}from'./chunk-KHVJY566.js';a.client||m();//# sourceMappingURL=auto.js.map
2
+ //# sourceMappingURL=auto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auto.ts"],"names":["state","init"],"mappings":"sCASKA,CAAAA,CAAM,QAAQC,CAAAA,EAAK","file":"auto.js","sourcesContent":["/**\n * `@tracehatch/sdk/auto`: import first (or `node --import`) and\n * every model call, inbound request and tool step is recorded with the\n * settings in `TRACEHATCH_API_KEY`, `TRACEHATCH_BASE_URL`, `TRACEHATCH_AGENT` and\n * `TRACEHATCH_RELEASE`. An explicit `init()` made earlier is kept.\n */\nimport { state } from \"./context.js\"\nimport { init } from \"./init.js\"\n\nif (!state.client) init()\n"]}