@lynxops/sdk 1.0.2 → 1.0.4

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,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@lynxops/sdk` will be documented in this file.
4
+
5
+ ## 1.0.2
6
+
7
+ - Added production-safe background delivery defaults.
8
+ - Added delivery timeout, queue overflow, retry, and circuit breaker controls.
9
+ - Added `flush()`, `shutdown()`, and `getStatus()` lifecycle APIs.
10
+ - Added semantic event helpers for user input, decisions, context, memory, and
11
+ outcomes.
12
+ - Added local-first `guardTool()` policy evaluation.
13
+ - Added `full`, `metadata-only`, and `smart` capture modes.
14
+ - Added sensitive payload masking before delivery.
15
+ - Added OpenAI, Anthropic, Google, Vercel AI SDK, LangChain, Ollama, and Cohere
16
+ instrumentation helpers.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Haven / Lynx
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
11
+ FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,470 +1,496 @@
1
- # Lynx SDK
2
-
3
- TypeScript SDK for tracing, debugging, and governing AI agent runs with Lynx.
4
-
5
- Lynx records what happened during an agent run: user input, agent decisions,
6
- LLM calls, tool calls, context loading, policy decisions, retries, errors, and
7
- the final outcome. The SDK is designed for production services, so event
8
- delivery failures do not stop your application by default.
9
-
10
- ## Installation
11
-
12
- ```bash
13
- pnpm add @lynxops/sdk
14
- ```
15
-
16
- ```bash
17
- npm install @lynxops/sdk
18
- ```
19
-
20
- ```bash
21
- yarn add @lynxops/sdk
22
- ```
23
-
24
- ## Quick Start
25
-
26
- ```ts
27
- import { LynxTracer } from "@lynxops/sdk";
28
-
29
- const lynx = new LynxTracer({
30
- clientId: "support-api",
31
- apiKey: process.env.LYNX_API_KEY,
32
- workspaceId: process.env.LYNX_WORKSPACE_ID,
33
- environment: "production",
34
- });
35
-
36
- await lynx.run("SupportAgent", async () => {
37
- lynx.userInput("I want a refund", { userId: "usr_123" });
38
- lynx.setAttributes({ orderId: "order_123" });
39
-
40
- lynx.context("refund-policy", {
41
- refundWindowDays: 30,
42
- });
43
-
44
- lynx.decision({
45
- name: "select_refund_workflow",
46
- selected: "refund",
47
- confidence: 0.82,
48
- reason: "Order is inside the refund window",
49
- });
50
-
51
- lynx.outcome({
52
- status: "COMPLETED",
53
- businessStatus: "SUCCEEDED",
54
- reason: "Refund request was accepted",
55
- });
56
- });
57
- ```
58
-
59
- By default, events are sent to:
60
-
61
- ```text
62
- https://api.lynxops.co
63
- ```
64
-
65
- Use `endpoint` or `LYNX_ENDPOINT` for local development or self-hosted
66
- deployments.
67
-
68
- ## Default Instance
69
-
70
- The SDK exports a default `lynx` instance configured from environment
71
- variables.
72
-
73
- ```ts
74
- import { lynx } from "@lynxops/sdk";
75
-
76
- await lynx.run("ResearchAgent", async () => {
77
- lynx.userInput("Find the latest invoice policy");
78
- lynx.decision("search internal docs first");
79
- });
80
- ```
81
-
82
- ```bash
83
- LYNX_CLIENT_ID=support-api
84
- LYNX_API_KEY=lynx_sk_...
85
- LYNX_WORKSPACE_ID=...
86
- LYNX_ENVIRONMENT=production
87
- ```
88
-
89
- ## Production Delivery Model
90
-
91
- The SDK prioritizes your application over event delivery.
92
-
93
- Production-oriented defaults:
94
-
95
- | Option | Default |
96
- | --- | --- |
97
- | `endpoint` | `https://api.lynxops.co` |
98
- | `delivery.mode` | `BACKGROUND` |
99
- | `delivery.timeoutMs` | `1000` |
100
- | `delivery.flushOnRunEnd` | `false` |
101
- | `delivery.flushIntervalMs` | `3000` |
102
- | `delivery.batchSize` | `50` |
103
- | `delivery.maxQueueSize` | `1000` |
104
- | `delivery.overflowStrategy` | `DROP_OLDEST` |
105
- | `circuitBreaker.enabled` | `true` |
106
- | `circuitBreaker.failureThreshold` | `3` |
107
- | `circuitBreaker.cooldownMs` | `30000` |
108
-
109
- Recommended production configuration:
110
-
111
- ```ts
112
- const lynx = new LynxTracer({
113
- clientId: "support-api",
114
- apiKey: process.env.LYNX_API_KEY,
115
- workspaceId: process.env.LYNX_WORKSPACE_ID,
116
-
117
- delivery: {
118
- mode: "BACKGROUND",
119
- timeoutMs: 1000,
120
- flushOnRunEnd: false,
121
- flushIntervalMs: 5000,
122
- batchSize: 50,
123
- maxQueueSize: 10_000,
124
- overflowStrategy: "DROP_OLDEST",
125
- },
126
-
127
- circuitBreaker: {
128
- enabled: true,
129
- failureThreshold: 3,
130
- cooldownMs: 30_000,
131
- },
132
- });
133
- ```
134
-
135
- If the Lynx API is unavailable, the SDK:
136
-
137
- - catches network, timeout, and non-2xx delivery errors
138
- - queues events in memory
139
- - retries with backoff
140
- - opens a circuit breaker after repeated failures
141
- - drops events according to the configured overflow strategy when the queue is
142
- full
143
-
144
- With the default background delivery mode, `run()` does not wait for event
145
- HTTP requests.
146
-
147
- ## Capturing Agent Runs
148
-
149
- Use `run()` as the unit of work for one agent execution.
150
-
151
- ```ts
152
- await lynx.run(
153
- "InvoiceAgent",
154
- async () => {
155
- lynx.userInput("Can this invoice be paid?");
156
- lynx.decision("verify vendor and payment policy");
157
- },
158
- {
159
- workspaceId: "workspace_123",
160
- agentId: "agent_invoice",
161
- sessionId: "session_456",
162
- },
163
- );
164
- ```
165
-
166
- Useful identifiers:
167
-
168
- | Field | Purpose |
169
- | --- | --- |
170
- | `runId` | Unique execution id for one agent run. Generated automatically unless provided. |
171
- | `sessionId` | Groups multiple runs or events into a user-visible session. |
172
- | `workspaceId` | Tenant boundary for Lynx ingestion and dashboards. |
173
- | `agentId` | Stable agent identifier. |
174
- | `agentName` | Human-readable agent name shown in debugging views. |
175
- | `environment` | Runtime environment such as `production`, `staging`, or `local`. |
176
- | `appVersion` | Application release metadata. |
177
- | `deploymentId` | Deployment metadata for incident correlation. |
178
- | `promptVersion` | Prompt version metadata attached to LLM and reasoning events. |
179
- | `policyVersion` | Guardrail or policy version metadata. |
180
-
181
- ## Semantic Events
182
-
183
- Prefer semantic helpers over raw event logging. They make Lynx debugging views
184
- more useful.
185
-
186
- ```ts
187
- lynx.userInput("Book a flight to Seoul", { userId: "usr_123" });
188
-
189
- lynx.context("calendar-availability", {
190
- daysLoaded: 14,
191
- source: "calendar-api",
192
- });
193
-
194
- lynx.decision({
195
- name: "choose_booking_tool",
196
- selected: "flight_search",
197
- alternatives: ["email_assistant", "manual_handoff"],
198
- confidence: 0.76,
199
- reason: "The user requested a travel booking action",
200
- });
201
-
202
- lynx.log("tool.timeout", {
203
- error: "Travel API timed out",
204
- toolName: "travel.search",
205
- });
206
-
207
- lynx.outcome({
208
- status: "FAILED",
209
- businessStatus: "FAILED",
210
- reason: "The external travel API timed out",
211
- userImpact: "MEDIUM",
212
- });
213
- ```
214
-
215
- ## Record LLM calls
216
-
217
- Use `instrumentLLM()` to wrap a model client. The returned proxy preserves the
218
- original client shape while recording supported model calls.
219
-
220
- ```ts
221
- const instrumentedClient = lynx.instrumentLLM(client, {
222
- modelLabel: "openai.gpt-4.1-mini",
223
- });
224
-
225
- await lynx.run("SupportAgent", async () => {
226
- await instrumentedClient.responses.create({
227
- model: "gpt-4.1-mini",
228
- input: "Summarize this support ticket",
229
- metadata: {
230
- promptVersion: "support-summary-v3",
231
- },
232
- });
233
- });
234
- ```
235
-
236
- ## Record tool calls
237
-
238
- Use `instrumentTool()` to wrap a reusable tool function.
239
-
240
- ```ts
241
- const postSlackMessage = lynx.instrumentTool(
242
- "slack.postMessage",
243
- async (input: { channel: string; text: string }) => {
244
- return await slack.chat.postMessage(input);
245
- },
246
- {
247
- sideEffect: true,
248
- riskLevel: "MEDIUM",
249
- externalTarget: "slack",
250
- },
251
- );
252
-
253
- await postSlackMessage({
254
- channel: "C123",
255
- text: "Refund approved",
256
- });
257
- ```
258
-
259
- ## Local Guardrails
260
-
261
- `guardTool()` evaluates your policy locally before a tool runs. Lynx server
262
- availability does not decide whether the tool is blocked.
263
-
264
- ```ts
265
- import { LynxPolicyError } from "@lynxops/sdk";
266
-
267
- const refund = lynx.guardTool(
268
- "refund.create",
269
- async ({ amount }: { amount: number }) => {
270
- return { refunded: amount };
271
- },
272
- {
273
- sideEffect: true,
274
- riskLevel: "HIGH",
275
- failureMode: "FAIL_CLOSED",
276
- beforeCall: ({ input }) => {
277
- if (input.amount > 100) {
278
- return {
279
- action: "BLOCK",
280
- policyId: "refund-limit",
281
- reason: "Refund amount is over the approved limit",
282
- severity: "HIGH",
283
- };
284
- }
285
-
286
- return {
287
- action: "ALLOW",
288
- policyId: "refund-limit",
289
- };
290
- },
291
- },
292
- );
293
-
294
- try {
295
- await lynx.run("SupportAgent", () => refund({ amount: 500 }));
296
- } catch (error) {
297
- if (error instanceof LynxPolicyError) {
298
- console.log(error.action, error.policyId, error.reason);
299
- }
300
- }
301
- ```
302
-
303
- Policy behavior:
304
-
305
- | Policy result | Behavior |
306
- | --- | --- |
307
- | `ALLOW` | Runs the tool and records policy evaluation metadata. |
308
- | `WARN` | Runs the tool and records a warning. |
309
- | `BLOCK` | Blocks the tool and throws `LynxPolicyError`. |
310
- | `REQUIRE_APPROVAL` | Blocks the tool and throws `LynxPolicyError`. |
311
-
312
- If policy evaluation itself throws, `failureMode` decides the fallback:
313
-
314
- | Failure mode | Behavior |
315
- | --- | --- |
316
- | `FAIL_OPEN` | Allows the tool call and records the policy error. |
317
- | `FAIL_CLOSED` | Blocks the tool call. |
318
- | `REQUIRE_APPROVAL` | Blocks with `action: "REQUIRE_APPROVAL"`. |
319
-
320
- ## Capture Modes
321
-
322
- Lynx does not require you to store full payloads.
323
-
324
- | Mode | Behavior |
325
- | --- | --- |
326
- | `full` | Captures input and output payloads according to `captureInput` and `captureOutput`. |
327
- | `metadata-only` | Keeps structure, timing, token usage, cost, status, errors, tool names, and trace metadata without raw content. |
328
- | `smart` | Captures metadata for normal events and preserves richer detail for failures, policy violations, and abnormal latency. |
329
-
330
- ```ts
331
- const lynx = new LynxTracer({
332
- clientId: "support-api",
333
- apiKey: process.env.LYNX_API_KEY,
334
- captureMode: "smart",
335
- maxPayloadLength: 16_000,
336
- });
337
- ```
338
-
339
- ## Flush, Shutdown, and Health
340
-
341
- Use `flush()` to send the current queue while keeping the SDK active.
342
-
343
- ```ts
344
- await lynx.flush();
345
- ```
346
-
347
- Use `shutdown()` when the process is about to exit, in serverless handlers, or
348
- in tests.
349
-
350
- ```ts
351
- await lynx.shutdown({ timeoutMs: 1000 });
352
- ```
353
-
354
- Use `getStatus()` for local diagnostics.
355
-
356
- ```ts
357
- const status = lynx.getStatus();
358
-
359
- console.log({
360
- queueSize: status.queueSize,
361
- droppedEvents: status.droppedEvents,
362
- circuitState: status.circuitState,
363
- pendingTransmissions: status.pendingTransmissions,
364
- });
365
- ```
366
-
367
- ## Configuration Reference
368
-
369
- ```ts
370
- const lynx = new LynxTracer({
371
- clientId: "support-api",
372
- endpoint: "https://api.lynxops.co",
373
- workspaceId: "workspace_123",
374
- agentId: "agent_support",
375
- apiKey: process.env.LYNX_API_KEY,
376
- appVersion: "2026.06.29",
377
- deploymentId: "deploy_123",
378
- environment: "production",
379
- policyVersion: "policy_2026_06",
380
- sampleRate: 1,
381
- captureInput: true,
382
- captureOutput: true,
383
- captureMode: "smart",
384
- maxPayloadLength: 16_000,
385
- delivery: {
386
- mode: "BACKGROUND",
387
- timeoutMs: 1000,
388
- flushOnRunEnd: false,
389
- flushIntervalMs: 3000,
390
- batchSize: 50,
391
- maxQueueSize: 1000,
392
- overflowStrategy: "DROP_OLDEST",
393
- },
394
- circuitBreaker: {
395
- enabled: true,
396
- failureThreshold: 3,
397
- cooldownMs: 30_000,
398
- },
399
- });
400
- ```
401
-
402
- | Option | Description |
403
- | --- | --- |
404
- | `clientId` | Required service or client identifier. |
405
- | `endpoint` | Lynx API endpoint. Defaults to `https://api.lynxops.co`. |
406
- | `workspaceId` | Default workspace id attached to events. |
407
- | `agentId` | Default agent id attached to events. |
408
- | `apiKey` | Lynx ingestion API key. Sent as a bearer token. |
409
- | `appVersion` | Application version metadata. |
410
- | `deploymentId` | Deployment id metadata. |
411
- | `environment` | Runtime environment metadata. |
412
- | `policyVersion` | Default policy version metadata. |
413
- | `sampleRate` | Trace sampling ratio from `0` to `1`. |
414
- | `captureInput` | Whether input payloads can be captured. |
415
- | `captureOutput` | Whether output payloads can be captured. |
416
- | `captureMode` | `full`, `metadata-only`, or `smart`. |
417
- | `maxPayloadLength` | Maximum serialized payload length per event. |
418
- | `delivery.mode` | `BACKGROUND` or `BLOCKING`. |
419
- | `delivery.timeoutMs` | Timeout for one event delivery request. |
420
- | `delivery.flushOnRunEnd` | Whether `run()` tries to flush after the wrapped work finishes. |
421
- | `delivery.flushIntervalMs` | Background flush interval. |
422
- | `delivery.batchSize` | Batch size for delivery. |
423
- | `delivery.maxQueueSize` | Maximum queued events in memory. |
424
- | `delivery.overflowStrategy` | `DROP_OLDEST` or `DROP_NEWEST`. |
425
- | `circuitBreaker.enabled` | Enables delivery circuit breaker protection. |
426
- | `circuitBreaker.failureThreshold` | Consecutive delivery failures before opening the breaker. |
427
- | `circuitBreaker.cooldownMs` | Cooldown before retrying after the breaker opens. |
428
-
429
- ## Environment Variables
430
-
431
- The default `lynx` export reads these variables:
432
-
433
- | Variable | Description |
434
- | --- | --- |
435
- | `LYNX_CLIENT_ID` | Client or service identifier. Defaults to `local_dev_env`. |
436
- | `LYNX_ENDPOINT` | Optional Lynx API endpoint override. |
437
- | `LYNX_API_KEY` | Lynx ingestion API key. |
438
- | `LYNX_WORKSPACE_ID` | Default workspace id. |
439
- | `LYNX_AGENT_ID` | Default agent id. |
440
- | `LYNX_SESSION_ID` | Default session id when `run()` does not receive one. |
441
- | `LYNX_SAMPLE_RATE` | Sampling rate from `0` to `1`. |
442
- | `LYNX_CAPTURE_INPUT` | `true` or `false`. |
443
- | `LYNX_CAPTURE_OUTPUT` | `true` or `false`. |
444
- | `LYNX_CAPTURE_MODE` | `full`, `metadata-only`, or `smart`. |
445
- | `LYNX_MAX_PAYLOAD_LENGTH` | Maximum payload string length. |
446
- | `LYNX_APP_VERSION` | Application version metadata. |
447
- | `LYNX_DEPLOYMENT_ID` | Deployment id metadata. |
448
- | `LYNX_ENVIRONMENT` | Runtime environment metadata. Falls back to `NODE_ENV`. |
449
- | `LYNX_POLICY_VERSION` | Default policy version metadata. |
450
- | `LYNX_DELIVERY_MODE` | `BACKGROUND` or `BLOCKING`. |
451
- | `LYNX_DELIVERY_TIMEOUT_MS` | Delivery timeout in milliseconds. |
452
- | `LYNX_DELIVERY_FLUSH_ON_RUN_END` | `true` or `false`. |
453
- | `LYNX_DELIVERY_FLUSH_INTERVAL_MS` | Flush interval in milliseconds. |
454
- | `LYNX_DELIVERY_BATCH_SIZE` | Batch size. |
455
- | `LYNX_DELIVERY_MAX_QUEUE_SIZE` | Maximum queued event count. |
456
- | `LYNX_DELIVERY_OVERFLOW_STRATEGY` | `DROP_OLDEST` or `DROP_NEWEST`. |
457
- | `LYNX_CIRCUIT_BREAKER_ENABLED` | `true` or `false`. |
458
- | `LYNX_CIRCUIT_BREAKER_FAILURE_THRESHOLD` | Consecutive failure count before opening the breaker. |
459
- | `LYNX_CIRCUIT_BREAKER_COOLDOWN_MS` | Circuit breaker cooldown in milliseconds. |
460
-
461
- ## Development
462
-
463
- ```bash
464
- pnpm install
465
- pnpm build
466
- pnpm test
467
- ```
468
-
469
- The SDK is ESM-first and also publishes a CommonJS build through package
470
- exports.
1
+ # Lynx SDK
2
+
3
+ TypeScript SDK for tracing, debugging, and governing AI agent runs with Lynx.
4
+
5
+ Lynx records what happened during an agent run: user input, agent decisions,
6
+ LLM calls, tool calls, context loading, policy decisions, retries, errors, and
7
+ the final outcome. The SDK is designed for production services, so event
8
+ delivery failures do not stop your application by default.
9
+
10
+ This SDK is designed for Node.js server-side runtimes. Browser and edge runtime
11
+ support are not guaranteed yet.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pnpm add @lynxops/sdk
17
+ ```
18
+
19
+ ```bash
20
+ npm install @lynxops/sdk
21
+ ```
22
+
23
+ ```bash
24
+ yarn add @lynxops/sdk
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```ts
30
+ import { LynxTracer } from "@lynxops/sdk";
31
+
32
+ const lynx = new LynxTracer({
33
+ clientId: "support-api",
34
+ apiKey: process.env.LYNX_API_KEY,
35
+ workspaceId: process.env.LYNX_WORKSPACE_ID,
36
+ environment: "production",
37
+ });
38
+
39
+ await lynx.run("SupportAgent", async () => {
40
+ lynx.userInput("I want a refund", { userId: "usr_123" });
41
+ lynx.setAttributes({ orderId: "order_123" });
42
+
43
+ lynx.context("refund-policy", {
44
+ refundWindowDays: 30,
45
+ });
46
+
47
+ lynx.decision({
48
+ name: "select_refund_workflow",
49
+ selected: "refund",
50
+ confidence: 0.82,
51
+ reason: "Order is inside the refund window",
52
+ });
53
+
54
+ lynx.outcome({
55
+ status: "COMPLETED",
56
+ businessStatus: "SUCCEEDED",
57
+ reason: "Refund request was accepted",
58
+ });
59
+ });
60
+ ```
61
+
62
+ In serverless functions, CLI scripts, tests, or other short-lived processes,
63
+ call `shutdown()` before the process exits so queued background events can be
64
+ flushed.
65
+
66
+ ```ts
67
+ await lynx.shutdown({ timeoutMs: 1000 });
68
+ ```
69
+
70
+ By default, events are sent to:
71
+
72
+ ```text
73
+ https://api.lynxops.co
74
+ ```
75
+
76
+ Use `endpoint` or `LYNX_ENDPOINT` for local development or self-hosted
77
+ deployments.
78
+
79
+ ## Default Instance
80
+
81
+ The SDK exports a default `lynx` instance configured from environment
82
+ variables.
83
+
84
+ ```ts
85
+ import { lynx } from "@lynxops/sdk";
86
+
87
+ await lynx.run("ResearchAgent", async () => {
88
+ lynx.userInput("Find the latest invoice policy");
89
+ lynx.decision("search internal docs first");
90
+ });
91
+ ```
92
+
93
+ ```bash
94
+ LYNX_CLIENT_ID=support-api
95
+ LYNX_API_KEY=lynx_sk_...
96
+ LYNX_WORKSPACE_ID=...
97
+ LYNX_ENVIRONMENT=production
98
+ ```
99
+
100
+ ## Production Delivery Model
101
+
102
+ The SDK prioritizes your application over event delivery.
103
+
104
+ Production-oriented defaults:
105
+
106
+ | Option | Default |
107
+ | --- | --- |
108
+ | `endpoint` | `https://api.lynxops.co` |
109
+ | `delivery.mode` | `BACKGROUND` |
110
+ | `delivery.timeoutMs` | `1000` |
111
+ | `delivery.flushOnRunEnd` | `false` |
112
+ | `delivery.flushIntervalMs` | `3000` |
113
+ | `delivery.batchSize` | `50` |
114
+ | `delivery.maxQueueSize` | `1000` |
115
+ | `delivery.overflowStrategy` | `DROP_OLDEST` |
116
+ | `circuitBreaker.enabled` | `true` |
117
+ | `circuitBreaker.failureThreshold` | `3` |
118
+ | `circuitBreaker.cooldownMs` | `30000` |
119
+
120
+ Recommended production configuration:
121
+
122
+ ```ts
123
+ const lynx = new LynxTracer({
124
+ clientId: "support-api",
125
+ apiKey: process.env.LYNX_API_KEY,
126
+ workspaceId: process.env.LYNX_WORKSPACE_ID,
127
+
128
+ delivery: {
129
+ mode: "BACKGROUND",
130
+ timeoutMs: 1000,
131
+ flushOnRunEnd: false,
132
+ flushIntervalMs: 5000,
133
+ batchSize: 50,
134
+ maxQueueSize: 10_000,
135
+ overflowStrategy: "DROP_OLDEST",
136
+ },
137
+
138
+ circuitBreaker: {
139
+ enabled: true,
140
+ failureThreshold: 3,
141
+ cooldownMs: 30_000,
142
+ },
143
+ });
144
+ ```
145
+
146
+ If the Lynx API is unavailable, the SDK:
147
+
148
+ - catches network, timeout, and non-2xx delivery errors
149
+ - queues events in memory
150
+ - retries with backoff
151
+ - opens a circuit breaker after repeated failures
152
+ - drops events according to the configured overflow strategy when the queue is
153
+ full
154
+
155
+ With the default background delivery mode, `run()` does not wait for event
156
+ HTTP requests.
157
+
158
+ ## Capturing Agent Runs
159
+
160
+ Use `run()` as the unit of work for one agent execution.
161
+
162
+ ```ts
163
+ await lynx.run(
164
+ {
165
+ agentName: "InvoiceAgent",
166
+ workspaceId: "workspace_123",
167
+ agentId: "agent_invoice",
168
+ sessionId: "session_456",
169
+ },
170
+ async () => {
171
+ lynx.userInput("Can this invoice be paid?");
172
+ lynx.decision("verify vendor and payment policy");
173
+ },
174
+ );
175
+ ```
176
+
177
+ Useful identifiers:
178
+
179
+ | Field | Purpose |
180
+ | --- | --- |
181
+ | `runId` | Unique execution id for one agent run. Generated automatically unless provided. |
182
+ | `sessionId` | Groups multiple runs or events into a user-visible session. |
183
+ | `workspaceId` | Tenant boundary for Lynx ingestion and dashboards. |
184
+ | `agentId` | Stable agent identifier. |
185
+ | `agentName` | Human-readable agent name shown in debugging views. |
186
+ | `environment` | Runtime environment such as `production`, `staging`, or `local`. |
187
+ | `appVersion` | Application release metadata. |
188
+ | `deploymentId` | Deployment metadata for incident correlation. |
189
+ | `promptVersion` | Prompt version metadata attached to LLM and reasoning events. |
190
+ | `policyVersion` | Guardrail or policy version metadata. |
191
+
192
+ ## Semantic Events
193
+
194
+ Prefer semantic helpers over raw event logging. They make Lynx debugging views
195
+ more useful.
196
+
197
+ ```ts
198
+ lynx.userInput("Book a flight to Seoul", { userId: "usr_123" });
199
+
200
+ lynx.context("calendar-availability", {
201
+ daysLoaded: 14,
202
+ source: "calendar-api",
203
+ });
204
+
205
+ lynx.decision({
206
+ name: "choose_booking_tool",
207
+ selected: "flight_search",
208
+ alternatives: ["email_assistant", "manual_handoff"],
209
+ confidence: 0.76,
210
+ reason: "The user requested a travel booking action",
211
+ });
212
+
213
+ lynx.log("tool.timeout", {
214
+ error: "Travel API timed out",
215
+ toolName: "travel.search",
216
+ });
217
+
218
+ lynx.outcome({
219
+ status: "FAILED",
220
+ businessStatus: "FAILED",
221
+ reason: "The external travel API timed out",
222
+ userImpact: "MEDIUM",
223
+ });
224
+ ```
225
+
226
+ ## Record LLM calls
227
+
228
+ Use `instrumentLLM()` to wrap a model client. The returned proxy preserves the
229
+ original client shape while recording supported model calls.
230
+
231
+ ```ts
232
+ const instrumentedClient = lynx.instrumentLLM(client, {
233
+ modelLabel: "openai.gpt-4.1-mini",
234
+ });
235
+
236
+ await lynx.run("SupportAgent", async () => {
237
+ await instrumentedClient.responses.create({
238
+ model: "gpt-4.1-mini",
239
+ input: "Summarize this support ticket",
240
+ metadata: {
241
+ promptVersion: "support-summary-v3",
242
+ },
243
+ });
244
+ });
245
+ ```
246
+
247
+ ## Record tool calls
248
+
249
+ Use `instrumentTool()` to wrap a reusable tool function.
250
+
251
+ ```ts
252
+ const postSlackMessage = lynx.instrumentTool(
253
+ "slack.postMessage",
254
+ async (input: { channel: string; text: string }) => {
255
+ return await slack.chat.postMessage(input);
256
+ },
257
+ {
258
+ sideEffect: true,
259
+ riskLevel: "MEDIUM",
260
+ externalTarget: "slack",
261
+ },
262
+ );
263
+
264
+ await postSlackMessage({
265
+ channel: "C123",
266
+ text: "Refund approved",
267
+ });
268
+ ```
269
+
270
+ ## Local Guardrails
271
+
272
+ `guardTool()` evaluates your policy locally before a tool runs. Lynx server
273
+ availability does not decide whether the tool is blocked.
274
+
275
+ ```ts
276
+ import { LynxPolicyError } from "@lynxops/sdk";
277
+
278
+ const refund = lynx.guardTool(
279
+ "refund.create",
280
+ async ({ amount }: { amount: number }) => {
281
+ return { refunded: amount };
282
+ },
283
+ {
284
+ sideEffect: true,
285
+ riskLevel: "HIGH",
286
+ failureMode: "FAIL_CLOSED",
287
+ beforeCall: ({ input }) => {
288
+ if (input.amount > 100) {
289
+ return {
290
+ action: "BLOCK",
291
+ policyId: "refund-limit",
292
+ reason: "Refund amount is over the approved limit",
293
+ severity: "HIGH",
294
+ };
295
+ }
296
+
297
+ return {
298
+ action: "ALLOW",
299
+ policyId: "refund-limit",
300
+ };
301
+ },
302
+ },
303
+ );
304
+
305
+ try {
306
+ await lynx.run("SupportAgent", () => refund({ amount: 500 }));
307
+ } catch (error) {
308
+ if (error instanceof LynxPolicyError) {
309
+ console.log(error.action, error.policyId, error.reason);
310
+ }
311
+ }
312
+ ```
313
+
314
+ Policy behavior:
315
+
316
+ | Policy result | Behavior |
317
+ | --- | --- |
318
+ | `ALLOW` | Runs the tool and records policy evaluation metadata. |
319
+ | `WARN` | Runs the tool and records a warning. |
320
+ | `BLOCK` | Blocks the tool and throws `LynxPolicyError`. |
321
+ | `REQUIRE_APPROVAL` | Blocks the tool and throws `LynxPolicyError`. |
322
+
323
+ If policy evaluation itself throws, `failureMode` decides the fallback:
324
+
325
+ | Failure mode | Behavior |
326
+ | --- | --- |
327
+ | `FAIL_OPEN` | Allows the tool call and records the policy error. |
328
+ | `FAIL_CLOSED` | Blocks the tool call. |
329
+ | `REQUIRE_APPROVAL` | Blocks with `action: "REQUIRE_APPROVAL"`. |
330
+
331
+ ## Capture Modes
332
+
333
+ Lynx does not require you to store full payloads.
334
+
335
+ | Mode | Behavior |
336
+ | --- | --- |
337
+ | `full` | Captures input and output payloads according to `captureInput` and `captureOutput`. |
338
+ | `metadata-only` | Keeps structure, timing, token usage, cost, status, errors, tool names, and trace metadata without raw content. |
339
+ | `smart` | Captures metadata for normal events and preserves richer detail for failures, policy violations, and abnormal latency. |
340
+
341
+ ```ts
342
+ const lynx = new LynxTracer({
343
+ clientId: "support-api",
344
+ apiKey: process.env.LYNX_API_KEY,
345
+ captureMode: "smart",
346
+ maxPayloadLength: 16_000,
347
+ });
348
+ ```
349
+
350
+ ## Flush, Shutdown, and Health
351
+
352
+ Use `flush()` to send the current queue while keeping the SDK active.
353
+
354
+ ```ts
355
+ await lynx.flush();
356
+ ```
357
+
358
+ Use `shutdown()` when the process is about to exit, in serverless handlers, or
359
+ in tests.
360
+
361
+ ```ts
362
+ await lynx.shutdown({ timeoutMs: 1000 });
363
+ ```
364
+
365
+ Use `getStatus()` for local diagnostics.
366
+
367
+ ```ts
368
+ const status = lynx.getStatus();
369
+
370
+ console.log({
371
+ queueSize: status.queueSize,
372
+ droppedEvents: status.droppedEvents,
373
+ circuitState: status.circuitState,
374
+ pendingTransmissions: status.pendingTransmissions,
375
+ });
376
+ ```
377
+
378
+ ## Configuration Reference
379
+
380
+ ```ts
381
+ const lynx = new LynxTracer({
382
+ clientId: "support-api",
383
+ endpoint: "https://api.lynxops.co",
384
+ workspaceId: "workspace_123",
385
+ agentId: "agent_support",
386
+ apiKey: process.env.LYNX_API_KEY,
387
+ appVersion: "2026.06.29",
388
+ deploymentId: "deploy_123",
389
+ environment: "production",
390
+ policyVersion: "policy_2026_06",
391
+ sampleRate: 1,
392
+ captureInput: true,
393
+ captureOutput: true,
394
+ captureMode: "smart",
395
+ maxPayloadLength: 16_000,
396
+ delivery: {
397
+ mode: "BACKGROUND",
398
+ timeoutMs: 1000,
399
+ flushOnRunEnd: false,
400
+ flushIntervalMs: 3000,
401
+ batchSize: 50,
402
+ maxQueueSize: 1000,
403
+ overflowStrategy: "DROP_OLDEST",
404
+ },
405
+ circuitBreaker: {
406
+ enabled: true,
407
+ failureThreshold: 3,
408
+ cooldownMs: 30_000,
409
+ },
410
+ });
411
+ ```
412
+
413
+ | Option | Description |
414
+ | --- | --- |
415
+ | `clientId` | Required service or client identifier. |
416
+ | `endpoint` | Lynx API endpoint. Defaults to `https://api.lynxops.co`. |
417
+ | `workspaceId` | Default workspace id attached to events. |
418
+ | `agentId` | Default agent id attached to events. |
419
+ | `apiKey` | Lynx ingestion API key. Sent as a bearer token. |
420
+ | `appVersion` | Application version metadata. |
421
+ | `deploymentId` | Deployment id metadata. |
422
+ | `environment` | Runtime environment metadata. |
423
+ | `policyVersion` | Default policy version metadata. |
424
+ | `sampleRate` | Trace sampling ratio from `0` to `1`. |
425
+ | `captureInput` | Whether input payloads can be captured. |
426
+ | `captureOutput` | Whether output payloads can be captured. |
427
+ | `captureMode` | `full`, `metadata-only`, or `smart`. |
428
+ | `maxPayloadLength` | Maximum serialized payload length per event. |
429
+ | `delivery.mode` | `BACKGROUND` or `BLOCKING`. |
430
+ | `delivery.timeoutMs` | Timeout for one event delivery request. |
431
+ | `delivery.flushOnRunEnd` | Whether `run()` tries to flush after the wrapped work finishes. |
432
+ | `delivery.flushIntervalMs` | Background flush interval. |
433
+ | `delivery.batchSize` | Batch size for delivery. |
434
+ | `delivery.maxQueueSize` | Maximum queued events in memory. |
435
+ | `delivery.overflowStrategy` | `DROP_OLDEST` or `DROP_NEWEST`. |
436
+ | `circuitBreaker.enabled` | Enables delivery circuit breaker protection. |
437
+ | `circuitBreaker.failureThreshold` | Consecutive delivery failures before opening the breaker. |
438
+ | `circuitBreaker.cooldownMs` | Cooldown before retrying after the breaker opens. |
439
+
440
+ ## Environment Variables
441
+
442
+ The default `lynx` export reads these variables:
443
+
444
+ | Variable | Description |
445
+ | --- | --- |
446
+ | `LYNX_CLIENT_ID` | Client or service identifier. Defaults to `local_dev_env`. |
447
+ | `LYNX_ENDPOINT` | Optional Lynx API endpoint override. |
448
+ | `LYNX_API_KEY` | Lynx ingestion API key. |
449
+ | `LYNX_WORKSPACE_ID` | Default workspace id. |
450
+ | `LYNX_AGENT_ID` | Default agent id. |
451
+ | `LYNX_SESSION_ID` | Default session id when `run()` does not receive one. |
452
+ | `LYNX_SAMPLE_RATE` | Sampling rate from `0` to `1`. |
453
+ | `LYNX_CAPTURE_INPUT` | `true` or `false`. |
454
+ | `LYNX_CAPTURE_OUTPUT` | `true` or `false`. |
455
+ | `LYNX_CAPTURE_MODE` | `full`, `metadata-only`, or `smart`. |
456
+ | `LYNX_MAX_PAYLOAD_LENGTH` | Maximum payload string length. |
457
+ | `LYNX_APP_VERSION` | Application version metadata. |
458
+ | `LYNX_DEPLOYMENT_ID` | Deployment id metadata. |
459
+ | `LYNX_ENVIRONMENT` | Runtime environment metadata. Falls back to `NODE_ENV`. |
460
+ | `LYNX_POLICY_VERSION` | Default policy version metadata. |
461
+ | `LYNX_DELIVERY_MODE` | `BACKGROUND` or `BLOCKING`. |
462
+ | `LYNX_DELIVERY_TIMEOUT_MS` | Delivery timeout in milliseconds. |
463
+ | `LYNX_DELIVERY_FLUSH_ON_RUN_END` | `true` or `false`. |
464
+ | `LYNX_DELIVERY_FLUSH_INTERVAL_MS` | Flush interval in milliseconds. |
465
+ | `LYNX_DELIVERY_BATCH_SIZE` | Batch size. |
466
+ | `LYNX_DELIVERY_MAX_QUEUE_SIZE` | Maximum queued event count. |
467
+ | `LYNX_DELIVERY_OVERFLOW_STRATEGY` | `DROP_OLDEST` or `DROP_NEWEST`. |
468
+ | `LYNX_CIRCUIT_BREAKER_ENABLED` | `true` or `false`. |
469
+ | `LYNX_CIRCUIT_BREAKER_FAILURE_THRESHOLD` | Consecutive failure count before opening the breaker. |
470
+ | `LYNX_CIRCUIT_BREAKER_COOLDOWN_MS` | Circuit breaker cooldown in milliseconds. |
471
+
472
+ ## Development
473
+
474
+ ```bash
475
+ pnpm install
476
+ pnpm build
477
+ pnpm test
478
+ ```
479
+
480
+ The SDK is ESM-first and also publishes a CommonJS build through package
481
+ exports.
482
+
483
+ ## Runtime Support
484
+
485
+ `@lynxops/sdk` supports Node.js 18 and newer. It uses Node runtime APIs such as
486
+ `AsyncLocalStorage`, global `fetch`, `AbortSignal.timeout`, and process
487
+ lifecycle hooks.
488
+
489
+ ## Security
490
+
491
+ Please report security issues privately to `security@lynxops.co`. See
492
+ `SECURITY.md` for details.
493
+
494
+ ## License
495
+
496
+ ISC
package/SECURITY.md ADDED
@@ -0,0 +1,29 @@
1
+ # Security Policy
2
+
3
+ Lynx SDK runs inside customer applications, so we treat security reports with
4
+ high priority.
5
+
6
+ ## Supported Versions
7
+
8
+ Security fixes are provided for the latest published version of `@lynxops/sdk`.
9
+
10
+ ## Reporting a Vulnerability
11
+
12
+ Please do not open a public GitHub issue for sensitive security reports.
13
+
14
+ Send vulnerability details to:
15
+
16
+ ```text
17
+ security@lynxops.co
18
+ ```
19
+
20
+ Include:
21
+
22
+ - affected package version
23
+ - runtime and framework details
24
+ - reproduction steps or proof of concept
25
+ - potential impact
26
+ - any relevant logs or traces with secrets removed
27
+
28
+ We will acknowledge reports as soon as possible and coordinate remediation
29
+ before public disclosure.
package/dist/index.cjs CHANGED
@@ -123,6 +123,35 @@ var PII_RULES = patterns_default.piiRules.map((rule) => ({
123
123
  replacement: rule.replacement
124
124
  }));
125
125
  var SENSITIVE_KEY_PATTERN = /(?:api[-_]?key|authorization|auth[-_]?token|bearer|client[-_]?secret|cookie|credential|jwt|password|private[-_]?key|refresh[-_]?token|secret|session[-_]?token|token)/i;
126
+ var SAFE_TOKEN_METRIC_KEYS = /* @__PURE__ */ new Set([
127
+ "completiontokens",
128
+ "completiontokencount",
129
+ "completion_tokens",
130
+ "inputtokens",
131
+ "inputtokencount",
132
+ "input_tokens",
133
+ "maxtokens",
134
+ "maxoutputtokens",
135
+ "max_tokens",
136
+ "outputtokens",
137
+ "outputtokencount",
138
+ "output_tokens",
139
+ "prompttokens",
140
+ "prompttokencount",
141
+ "prompt_tokens",
142
+ "totaltokens",
143
+ "totaltokencount",
144
+ "total_tokens"
145
+ ]);
146
+ function normalizeKey(key) {
147
+ return key.replace(/[-_]/g, "").toLowerCase();
148
+ }
149
+ function isSensitiveKey(key) {
150
+ if (SAFE_TOKEN_METRIC_KEYS.has(normalizeKey(key))) {
151
+ return false;
152
+ }
153
+ return SENSITIVE_KEY_PATTERN.test(key);
154
+ }
126
155
  function maskPIIString(text) {
127
156
  let masked = text;
128
157
  for (const rule of PII_RULES) {
@@ -141,7 +170,7 @@ function recursiveMaskPII(obj) {
141
170
  if (typeof obj === "object") {
142
171
  const res = {};
143
172
  for (const key of Object.keys(obj)) {
144
- if (SENSITIVE_KEY_PATTERN.test(key)) {
173
+ if (isSensitiveKey(key)) {
145
174
  res[key] = "[MASKED_SECRET]";
146
175
  } else {
147
176
  res[key] = recursiveMaskPII(obj[key]);
@@ -354,6 +383,7 @@ function instrumentLLM(tracer, instance, optionsOrLabel = "llm.inference") {
354
383
  }
355
384
  const pathStr = path.join(".");
356
385
  return pathStr === "chat.completions.create" || // OpenAI
386
+ pathStr === "responses.create" || // OpenAI Responses API
357
387
  pathStr === "messages.create" || // Anthropic (Claude)
358
388
  pathStr === "models.generateContent" || // Google Gen AI 신규
359
389
  pathStr === "generateContent" || // Google Generative AI 기존
@@ -498,8 +528,10 @@ function instrumentTool(tracer, toolName, fn, metadata = {}) {
498
528
  });
499
529
  }
500
530
 
531
+ // src/version.ts
532
+ var SDK_VERSION = "1.0.4";
533
+
501
534
  // src/core/tracer.ts
502
- var SDK_VERSION = "1.0.0";
503
535
  var DEFAULT_ENDPOINT = "https://api.lynxops.co";
504
536
  var DEFAULT_MAX_QUEUE_SIZE = 1e3;
505
537
  var DEFAULT_BATCH_SIZE = 50;
package/dist/index.js CHANGED
@@ -92,6 +92,35 @@ var PII_RULES = patterns_default.piiRules.map((rule) => ({
92
92
  replacement: rule.replacement
93
93
  }));
94
94
  var SENSITIVE_KEY_PATTERN = /(?:api[-_]?key|authorization|auth[-_]?token|bearer|client[-_]?secret|cookie|credential|jwt|password|private[-_]?key|refresh[-_]?token|secret|session[-_]?token|token)/i;
95
+ var SAFE_TOKEN_METRIC_KEYS = /* @__PURE__ */ new Set([
96
+ "completiontokens",
97
+ "completiontokencount",
98
+ "completion_tokens",
99
+ "inputtokens",
100
+ "inputtokencount",
101
+ "input_tokens",
102
+ "maxtokens",
103
+ "maxoutputtokens",
104
+ "max_tokens",
105
+ "outputtokens",
106
+ "outputtokencount",
107
+ "output_tokens",
108
+ "prompttokens",
109
+ "prompttokencount",
110
+ "prompt_tokens",
111
+ "totaltokens",
112
+ "totaltokencount",
113
+ "total_tokens"
114
+ ]);
115
+ function normalizeKey(key) {
116
+ return key.replace(/[-_]/g, "").toLowerCase();
117
+ }
118
+ function isSensitiveKey(key) {
119
+ if (SAFE_TOKEN_METRIC_KEYS.has(normalizeKey(key))) {
120
+ return false;
121
+ }
122
+ return SENSITIVE_KEY_PATTERN.test(key);
123
+ }
95
124
  function maskPIIString(text) {
96
125
  let masked = text;
97
126
  for (const rule of PII_RULES) {
@@ -110,7 +139,7 @@ function recursiveMaskPII(obj) {
110
139
  if (typeof obj === "object") {
111
140
  const res = {};
112
141
  for (const key of Object.keys(obj)) {
113
- if (SENSITIVE_KEY_PATTERN.test(key)) {
142
+ if (isSensitiveKey(key)) {
114
143
  res[key] = "[MASKED_SECRET]";
115
144
  } else {
116
145
  res[key] = recursiveMaskPII(obj[key]);
@@ -323,6 +352,7 @@ function instrumentLLM(tracer, instance, optionsOrLabel = "llm.inference") {
323
352
  }
324
353
  const pathStr = path.join(".");
325
354
  return pathStr === "chat.completions.create" || // OpenAI
355
+ pathStr === "responses.create" || // OpenAI Responses API
326
356
  pathStr === "messages.create" || // Anthropic (Claude)
327
357
  pathStr === "models.generateContent" || // Google Gen AI 신규
328
358
  pathStr === "generateContent" || // Google Generative AI 기존
@@ -467,8 +497,10 @@ function instrumentTool(tracer, toolName, fn, metadata = {}) {
467
497
  });
468
498
  }
469
499
 
500
+ // src/version.ts
501
+ var SDK_VERSION = "1.0.4";
502
+
470
503
  // src/core/tracer.ts
471
- var SDK_VERSION = "1.0.0";
472
504
  var DEFAULT_ENDPOINT = "https://api.lynxops.co";
473
505
  var DEFAULT_MAX_QUEUE_SIZE = 1e3;
474
506
  var DEFAULT_BATCH_SIZE = 50;
package/package.json CHANGED
@@ -1,56 +1,58 @@
1
- {
2
- "name": "@lynxops/sdk",
3
- "version": "1.0.2",
4
- "description": "TypeScript SDK for tracing, debugging, and governing AI agent runs with Lynx.",
5
- "type": "module",
6
- "main": "./dist/index.cjs",
7
- "module": "./dist/index.js",
8
- "types": "./dist/index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
14
- }
15
- },
16
- "files": [
17
- "dist"
18
- ],
19
- "scripts": {
20
- "build": "tsup src/index.ts --format cjs,esm --clean --dts",
21
- "obfuscate": "javascript-obfuscator ./dist/index.js --output ./dist/index.js --config obfuscator.config.json && javascript-obfuscator ./dist/index.cjs --output ./dist/index.cjs --config obfuscator.config.json",
22
- "build:prod": "pnpm build && pnpm obfuscate",
23
- "check-types": "tsc --noEmit",
24
- "test": "pnpm build && node --test test/*.mjs"
25
- },
26
- "keywords": [
27
- "ai",
28
- "agent",
29
- "observability",
30
- "tracing",
31
- "debugging",
32
- "guardrails",
33
- "lynx"
34
- ],
35
- "author": "Lynx",
36
- "license": "ISC",
37
- "devDependencies": {
38
- "@types/node": "^25.9.1",
39
- "javascript-obfuscator": "^4.1.1",
40
- "tsup": "^8.3.5",
41
- "typescript": "^5.0.0"
42
- },
43
- "dependencies": {},
44
- "repository": {
45
- "type": "git",
46
- "url": "git+https://github.com/hvnn-oss/lynx-sdk.git"
47
- },
48
- "bugs": {
49
- "url": "https://github.com/hvnn-oss/lynx-sdk/issues"
50
- },
51
- "homepage": "https://github.com/hvnn-oss/lynx-sdk#readme",
52
- "publishConfig": {
53
- "access": "public",
54
- "provenance": true
55
- }
56
- }
1
+ {
2
+ "name": "@lynxops/sdk",
3
+ "version": "1.0.4",
4
+ "description": "TypeScript SDK for tracing, debugging, and governing AI agent runs with Lynx.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "CHANGELOG.md",
22
+ "SECURITY.md"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup src/index.ts --format cjs,esm --clean --dts",
26
+ "check-types": "tsc --noEmit",
27
+ "test": "pnpm build && node --test test/*.mjs"
28
+ },
29
+ "keywords": [
30
+ "ai",
31
+ "agent",
32
+ "observability",
33
+ "tracing",
34
+ "debugging",
35
+ "guardrails",
36
+ "lynx"
37
+ ],
38
+ "author": "Lynx",
39
+ "license": "ISC",
40
+ "homepage": "https://docs.lynxops.co",
41
+ "devDependencies": {
42
+ "@types/node": "^25.9.1",
43
+ "tsup": "^8.3.5",
44
+ "typescript": "^5.0.0"
45
+ },
46
+ "dependencies": {},
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/hvnn-oss/lynx-sdk.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/hvnn-oss/lynx-sdk/issues"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public",
56
+ "provenance": true
57
+ }
58
+ }