@kortyx/telemetry 0.11.1 → 0.12.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 +26 -0
- package/README.md +17 -2
- package/dist/index.d.ts +18 -0
- package/dist/index.js +366 -26
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.0](https://github.com/kortyx-io/kortyx/compare/telemetry-v0.11.2...telemetry-v0.12.0) (2026-10-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **telemetry:** preserve complete private error diagnostics ([#290](https://github.com/kortyx-io/kortyx/issues/290)) ([e1c5a88](https://github.com/kortyx-io/kortyx/commit/e1c5a88c494016fd84a1af40579412fcfde31271))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @kortyx/hooks bumped to 0.31.0
|
|
16
|
+
* @kortyx/telemetry-contracts bumped to 0.15.0
|
|
17
|
+
* @kortyx/core bumped to 0.12.0
|
|
18
|
+
|
|
19
|
+
## [0.11.2](https://github.com/kortyx-io/kortyx/compare/telemetry-v0.11.1...telemetry-v0.11.2) (2026-10-07)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Dependencies
|
|
23
|
+
|
|
24
|
+
* The following workspace dependencies were updated
|
|
25
|
+
* dependencies
|
|
26
|
+
* @kortyx/hooks bumped to 0.30.2
|
|
27
|
+
* @kortyx/telemetry-contracts bumped to 0.14.0
|
|
28
|
+
|
|
3
29
|
## [0.11.1](https://github.com/kortyx-io/kortyx/compare/telemetry-v0.11.0...telemetry-v0.11.1) (2026-10-03)
|
|
4
30
|
|
|
5
31
|
|
package/README.md
CHANGED
|
@@ -48,8 +48,9 @@ available without enabling content capture.
|
|
|
48
48
|
|
|
49
49
|
Delivery is best-effort and at-least-once while the process remains alive. The
|
|
50
50
|
adapter batches events, retries transient failures, and exposes `flush()` for
|
|
51
|
-
controlled shutdown.
|
|
52
|
-
delivery must own that outbox themselves.
|
|
51
|
+
controlled shutdown. Ordinary events have no durable outbox; applications that
|
|
52
|
+
need durable event delivery must own that outbox themselves. Complete diagnostics
|
|
53
|
+
have a separate opt-in upload queue and optional Node spool. Telemetry failures never fail a
|
|
53
54
|
workflow execution.
|
|
54
55
|
|
|
55
56
|
`interrupt.expired` is intentionally API-derived from the durable `expiresAt`
|
|
@@ -67,3 +68,17 @@ values and resume capability tokens are never included in interrupt telemetry.
|
|
|
67
68
|
`run.cancelled` records aborted active executions. Custom HTTP routes must forward
|
|
68
69
|
`request.signal`; `createChatRouteHandler` forwards it automatically. Cancelling a
|
|
69
70
|
`toSSE` response body also cancels its active execution source.
|
|
71
|
+
|
|
72
|
+
## Complete error diagnostics
|
|
73
|
+
|
|
74
|
+
Set `diagnostics: { enabled: true }` on `createKortyxTelemetryAdapter` after
|
|
75
|
+
upgrading the API/Studio and granting `diagnostics:read` to the Studio reader.
|
|
76
|
+
Native capture retains large messages/stacks, causes, aggregate members, custom
|
|
77
|
+
fields, and private provider response evidence with credential redaction. Run
|
|
78
|
+
errors link to one diagnostic; native upload parts do not become timeline events.
|
|
79
|
+
|
|
80
|
+
Studio and `kortyx studio diagnostics get|download` retrieve complete content
|
|
81
|
+
without application chunk reconstruction. Capture and delivery limits are explicit,
|
|
82
|
+
and `flushDiagnostics(timeoutMs)` reports pending and dropped delivery. See the
|
|
83
|
+
[deployment and usage guide](../../docs/complete-error-diagnostics.md) for limits,
|
|
84
|
+
permissions, spool/retention operations, privacy policy, and rollout instructions.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import * as _kortyx_hooks from '@kortyx/hooks';
|
|
2
2
|
import { KortyxTelemetryService, KortyxTelemetryConfig } from '@kortyx/hooks';
|
|
3
3
|
|
|
4
|
+
type DiagnosticDeliveryState = "pending" | "available" | "rejected" | "dropped" | "spool_failed";
|
|
5
|
+
|
|
4
6
|
type CreateKortyxTelemetryAdapterOptions = {
|
|
5
7
|
endpoint: string;
|
|
6
8
|
apiKey: string;
|
|
@@ -8,6 +10,13 @@ type CreateKortyxTelemetryAdapterOptions = {
|
|
|
8
10
|
service: KortyxTelemetryService;
|
|
9
11
|
/** Optional replacement or suppression of captured error diagnostics. */
|
|
10
12
|
error?: _kortyx_hooks.KortyxTraceErrorProjection;
|
|
13
|
+
/** Opt in to complete redacted diagnostics stored by Studio's diagnostic API. */
|
|
14
|
+
diagnostics?: {
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
/** Optional secure persistent queue for Node process-restart recovery. */
|
|
17
|
+
spoolDirectory?: string;
|
|
18
|
+
maxQueueBytes?: number;
|
|
19
|
+
};
|
|
11
20
|
captureContent?: KortyxTelemetryConfig["captureContent"] | undefined;
|
|
12
21
|
metadata?: Record<string, unknown> | undefined;
|
|
13
22
|
tags?: string[] | undefined;
|
|
@@ -17,8 +26,17 @@ type CreateKortyxTelemetryAdapterOptions = {
|
|
|
17
26
|
};
|
|
18
27
|
type KortyxTelemetryAdapter = KortyxTelemetryConfig & {
|
|
19
28
|
flush: () => Promise<void>;
|
|
29
|
+
flushDiagnostics: (timeoutMs?: number) => Promise<{
|
|
30
|
+
timedOut: boolean;
|
|
31
|
+
pending: number;
|
|
32
|
+
pendingBytes: number;
|
|
33
|
+
dropped: number;
|
|
34
|
+
states: Record<string, DiagnosticDeliveryState>;
|
|
35
|
+
}>;
|
|
20
36
|
getDroppedEventCount: () => number;
|
|
21
37
|
getPermanentDeliveryFailureCount: () => number;
|
|
38
|
+
getDiagnosticDeliveryState: (id: string) => DiagnosticDeliveryState | undefined;
|
|
39
|
+
getDroppedDiagnosticCount: () => number;
|
|
22
40
|
};
|
|
23
41
|
|
|
24
42
|
/**
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(index_exports);
|
|
25
25
|
|
|
26
26
|
// src/adapter.ts
|
|
27
|
-
var
|
|
27
|
+
var import_node_crypto2 = require("crypto");
|
|
28
28
|
|
|
29
29
|
// src/delivery.ts
|
|
30
30
|
var TelemetryHttpError = class extends Error {
|
|
@@ -131,30 +131,338 @@ var createDelivery = (args) => {
|
|
|
131
131
|
};
|
|
132
132
|
};
|
|
133
133
|
|
|
134
|
-
// src/
|
|
134
|
+
// src/diagnostics.ts
|
|
135
|
+
var import_node_crypto = require("crypto");
|
|
136
|
+
var import_promises = require("fs/promises");
|
|
137
|
+
var import_node_path = require("path");
|
|
135
138
|
var import_errors = require("@kortyx/core/errors");
|
|
136
139
|
var import_internal = require("@kortyx/hooks/internal");
|
|
140
|
+
var import_telemetry_contracts = require("@kortyx/telemetry-contracts");
|
|
141
|
+
function createDiagnosticDelivery(options) {
|
|
142
|
+
const enabled = options.diagnostics?.enabled === true;
|
|
143
|
+
const queue = /* @__PURE__ */ new Map();
|
|
144
|
+
const states = /* @__PURE__ */ new Map();
|
|
145
|
+
const captured = /* @__PURE__ */ new WeakMap();
|
|
146
|
+
let queuedBytes = 0;
|
|
147
|
+
let dropped = 0;
|
|
148
|
+
let retryAt = 0;
|
|
149
|
+
let timer;
|
|
150
|
+
let inFlight;
|
|
151
|
+
const writes = /* @__PURE__ */ new Set();
|
|
152
|
+
const spool = options.diagnostics?.spoolDirectory ? (0, import_node_path.join)(
|
|
153
|
+
options.diagnostics.spoolDirectory,
|
|
154
|
+
// A stable credential-scoped namespace without storing the API key or
|
|
155
|
+
// a fast credential hash on disk. Only derived when spooling is enabled.
|
|
156
|
+
(0, import_node_crypto.scryptSync)(
|
|
157
|
+
options.apiKey,
|
|
158
|
+
JSON.stringify([options.endpoint, options.environment]),
|
|
159
|
+
24
|
|
160
|
+
).toString("hex")
|
|
161
|
+
) : void 0;
|
|
162
|
+
const state = (id, value) => {
|
|
163
|
+
states.set(id, value);
|
|
164
|
+
if (states.size > 1e3) states.delete(states.keys().next().value);
|
|
165
|
+
};
|
|
166
|
+
const maxBytes = options.diagnostics?.maxQueueBytes ?? 16 * 1024 * 1024;
|
|
167
|
+
const persist = async (entry) => {
|
|
168
|
+
if (!spool) return;
|
|
169
|
+
await (0, import_promises.mkdir)(spool, { recursive: true, mode: 448 });
|
|
170
|
+
const target = (0, import_node_path.join)(spool, `${entry.manifest.diagnosticId}.json`);
|
|
171
|
+
const temporary = `${target}.${(0, import_node_crypto.randomUUID)()}.tmp`;
|
|
172
|
+
await (0, import_promises.writeFile)(temporary, JSON.stringify(entry), { mode: 384 });
|
|
173
|
+
await (0, import_promises.rename)(temporary, target);
|
|
174
|
+
};
|
|
175
|
+
const schedule = () => {
|
|
176
|
+
if (!enabled || timer || inFlight || !queue.size) return;
|
|
177
|
+
timer = setTimeout(() => {
|
|
178
|
+
timer = void 0;
|
|
179
|
+
void flush();
|
|
180
|
+
}, options.flushIntervalMs ?? 250);
|
|
181
|
+
timer.unref?.();
|
|
182
|
+
};
|
|
183
|
+
const restored = (async () => {
|
|
184
|
+
if (!enabled || !spool) return;
|
|
185
|
+
try {
|
|
186
|
+
await (0, import_promises.mkdir)(spool, { recursive: true, mode: 448 });
|
|
187
|
+
for (const filename of (await (0, import_promises.readdir)(spool)).filter(
|
|
188
|
+
(name) => /^[a-f0-9-]{36}\.json$/.test(name)
|
|
189
|
+
)) {
|
|
190
|
+
try {
|
|
191
|
+
if ((await (0, import_promises.stat)((0, import_node_path.join)(spool, filename))).size > import_telemetry_contracts.DIAGNOSTIC_LIMITS.bytes + 64 * 1024)
|
|
192
|
+
throw new Error("Spool file exceeds budget");
|
|
193
|
+
const value = JSON.parse(
|
|
194
|
+
await (0, import_promises.readFile)((0, import_node_path.join)(spool, filename), "utf8")
|
|
195
|
+
);
|
|
196
|
+
const manifest = import_telemetry_contracts.DiagnosticManifestSchema.parse(value.manifest);
|
|
197
|
+
const bytes = Buffer.byteLength(value.content);
|
|
198
|
+
if (bytes !== manifest.byteLength || (0, import_node_crypto.createHash)("sha256").update(value.content).digest("hex") !== manifest.checksum)
|
|
199
|
+
throw new Error("Invalid spool content");
|
|
200
|
+
import_telemetry_contracts.DiagnosticContentSchema.parse(JSON.parse(value.content));
|
|
201
|
+
if (queuedBytes + bytes > maxBytes) {
|
|
202
|
+
state(manifest.diagnosticId, "dropped");
|
|
203
|
+
dropped++;
|
|
204
|
+
await (0, import_promises.unlink)((0, import_node_path.join)(spool, filename));
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
if (!queue.has(manifest.diagnosticId)) {
|
|
208
|
+
queue.set(manifest.diagnosticId, {
|
|
209
|
+
manifest,
|
|
210
|
+
content: value.content
|
|
211
|
+
});
|
|
212
|
+
queuedBytes += bytes;
|
|
213
|
+
state(manifest.diagnosticId, "pending");
|
|
214
|
+
}
|
|
215
|
+
} catch {
|
|
216
|
+
dropped++;
|
|
217
|
+
await (0, import_promises.unlink)((0, import_node_path.join)(spool, filename)).catch(() => void 0);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
schedule();
|
|
221
|
+
} catch {
|
|
222
|
+
dropped++;
|
|
223
|
+
}
|
|
224
|
+
})();
|
|
225
|
+
const send = async (path, body) => {
|
|
226
|
+
const response = await (options.fetch ?? globalThis.fetch)(
|
|
227
|
+
`${options.endpoint.replace(/\/$/, "")}/v1/telemetry/diagnostics${path}?env=${encodeURIComponent(options.environment)}`,
|
|
228
|
+
{
|
|
229
|
+
method: "POST",
|
|
230
|
+
headers: {
|
|
231
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
232
|
+
"content-type": "application/json"
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify(body),
|
|
235
|
+
signal: AbortSignal.timeout(15e3)
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
if (!response.ok) {
|
|
239
|
+
const error = new Error("Diagnostic delivery failed.");
|
|
240
|
+
error.status = response.status;
|
|
241
|
+
if (response.status === 429) {
|
|
242
|
+
const hint = response.headers.get("retry-after");
|
|
243
|
+
const seconds = Number(hint);
|
|
244
|
+
const delay = hint && Number.isFinite(seconds) ? seconds * 1e3 : hint ? Date.parse(hint) - Date.now() : 5e3;
|
|
245
|
+
retryAt = Date.now() + Math.min(
|
|
246
|
+
6e4,
|
|
247
|
+
Math.max(5e3, Number.isFinite(delay) ? delay : 5e3)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
return response;
|
|
253
|
+
};
|
|
254
|
+
const flush = async () => {
|
|
255
|
+
await restored;
|
|
256
|
+
await Promise.all([...writes]);
|
|
257
|
+
if (inFlight) {
|
|
258
|
+
await inFlight;
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
if (timer) {
|
|
262
|
+
clearTimeout(timer);
|
|
263
|
+
timer = void 0;
|
|
264
|
+
}
|
|
265
|
+
const work = async () => {
|
|
266
|
+
if (Date.now() < retryAt) return;
|
|
267
|
+
for (const [id, entry] of [...queue]) {
|
|
268
|
+
try {
|
|
269
|
+
await send("", entry.manifest);
|
|
270
|
+
const bytes = Buffer.from(entry.content);
|
|
271
|
+
for (let index = 0; index < entry.manifest.partCount; index++)
|
|
272
|
+
await send(`/${id}/parts`, {
|
|
273
|
+
index,
|
|
274
|
+
data: bytes.subarray(
|
|
275
|
+
index * import_telemetry_contracts.DIAGNOSTIC_LIMITS.partBytes,
|
|
276
|
+
(index + 1) * import_telemetry_contracts.DIAGNOSTIC_LIMITS.partBytes
|
|
277
|
+
).toString("base64")
|
|
278
|
+
});
|
|
279
|
+
const completed = await send(`/${id}/complete`, {});
|
|
280
|
+
const acknowledgement = await completed.json();
|
|
281
|
+
if (acknowledgement.state !== "available") {
|
|
282
|
+
const error = new Error(
|
|
283
|
+
"Diagnostic integrity verification failed."
|
|
284
|
+
);
|
|
285
|
+
error.status = 422;
|
|
286
|
+
throw error;
|
|
287
|
+
}
|
|
288
|
+
state(id, "available");
|
|
289
|
+
queue.delete(id);
|
|
290
|
+
queuedBytes -= entry.manifest.byteLength;
|
|
291
|
+
if (spool)
|
|
292
|
+
await (0, import_promises.unlink)((0, import_node_path.join)(spool, `${id}.json`)).catch(() => void 0);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
const status = error.status;
|
|
295
|
+
if (status && status < 500 && status !== 429) {
|
|
296
|
+
state(id, "rejected");
|
|
297
|
+
queue.delete(id);
|
|
298
|
+
queuedBytes -= entry.manifest.byteLength;
|
|
299
|
+
dropped++;
|
|
300
|
+
if (spool)
|
|
301
|
+
await (0, import_promises.unlink)((0, import_node_path.join)(spool, `${id}.json`)).catch(() => void 0);
|
|
302
|
+
}
|
|
303
|
+
if (status === 429) break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
inFlight = work();
|
|
308
|
+
try {
|
|
309
|
+
await inFlight;
|
|
310
|
+
} finally {
|
|
311
|
+
inFlight = void 0;
|
|
312
|
+
}
|
|
313
|
+
if (queue.size) {
|
|
314
|
+
timer = setTimeout(
|
|
315
|
+
() => {
|
|
316
|
+
timer = void 0;
|
|
317
|
+
void flush();
|
|
318
|
+
},
|
|
319
|
+
Math.max(5e3, retryAt - Date.now())
|
|
320
|
+
);
|
|
321
|
+
timer.unref?.();
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
const capture = (error, context) => {
|
|
325
|
+
if (!enabled || (0, import_errors.isControlFlowError)(error)) return void 0;
|
|
326
|
+
const scope = JSON.stringify([
|
|
327
|
+
context.correlation?.runId,
|
|
328
|
+
context.correlation?.invocationId,
|
|
329
|
+
context.correlation?.branchId,
|
|
330
|
+
context.correlation?.attemptId
|
|
331
|
+
]);
|
|
332
|
+
const object = error && typeof error === "object" ? error : void 0;
|
|
333
|
+
const existing = object ? captured.get(object)?.get(scope) : void 0;
|
|
334
|
+
if (existing)
|
|
335
|
+
return {
|
|
336
|
+
...existing,
|
|
337
|
+
diagnosticDelivery: existing.diagnosticId ? states.get(existing.diagnosticId) ?? "pending" : void 0
|
|
338
|
+
};
|
|
339
|
+
const content = (0, import_internal.captureDiagnosticContent)(
|
|
340
|
+
error,
|
|
341
|
+
context.project ?? options.error
|
|
342
|
+
);
|
|
343
|
+
if (!content) return { diagnosticCapture: "suppressed", details: null };
|
|
344
|
+
const serialized = JSON.stringify(content);
|
|
345
|
+
const diagnosticId = (0, import_node_crypto.randomUUID)();
|
|
346
|
+
const manifest = import_telemetry_contracts.DiagnosticManifestSchema.parse({
|
|
347
|
+
schemaVersion: 1,
|
|
348
|
+
diagnosticId,
|
|
349
|
+
occurrenceId: (0, import_node_crypto.randomUUID)(),
|
|
350
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
351
|
+
environment: options.environment,
|
|
352
|
+
service: options.service,
|
|
353
|
+
correlation: import_telemetry_contracts.DiagnosticCorrelationSchema.parse(
|
|
354
|
+
Object.fromEntries(
|
|
355
|
+
Object.entries(context.correlation ?? {}).filter(
|
|
356
|
+
([key]) => key !== "topologyHash"
|
|
357
|
+
)
|
|
358
|
+
)
|
|
359
|
+
),
|
|
360
|
+
handled: context.handled,
|
|
361
|
+
severity: context.severity,
|
|
362
|
+
mechanism: context.mechanism,
|
|
363
|
+
summary: {
|
|
364
|
+
type: String(content.data.type ?? "Error").slice(0, 256),
|
|
365
|
+
message: (0, import_telemetry_contracts.summarizeDiagnostic)(content.data).message
|
|
366
|
+
},
|
|
367
|
+
captureStatus: content.capture.status,
|
|
368
|
+
byteLength: Buffer.byteLength(serialized),
|
|
369
|
+
checksum: (0, import_node_crypto.createHash)("sha256").update(serialized).digest("hex"),
|
|
370
|
+
partCount: Math.ceil(
|
|
371
|
+
Buffer.byteLength(serialized) / import_telemetry_contracts.DIAGNOSTIC_LIMITS.partBytes
|
|
372
|
+
)
|
|
373
|
+
});
|
|
374
|
+
if (queuedBytes + manifest.byteLength > maxBytes) {
|
|
375
|
+
state(diagnosticId, "dropped");
|
|
376
|
+
dropped++;
|
|
377
|
+
} else {
|
|
378
|
+
const entry = { manifest, content: serialized };
|
|
379
|
+
queue.set(diagnosticId, entry);
|
|
380
|
+
queuedBytes += manifest.byteLength;
|
|
381
|
+
state(diagnosticId, "pending");
|
|
382
|
+
const writing = persist(entry).catch(() => {
|
|
383
|
+
state(diagnosticId, "spool_failed");
|
|
384
|
+
}).finally(() => {
|
|
385
|
+
writes.delete(writing);
|
|
386
|
+
});
|
|
387
|
+
writes.add(writing);
|
|
388
|
+
schedule();
|
|
389
|
+
}
|
|
390
|
+
const result = {
|
|
391
|
+
diagnosticId,
|
|
392
|
+
diagnosticCapture: content.capture.status,
|
|
393
|
+
diagnosticDelivery: states.get(diagnosticId),
|
|
394
|
+
details: (0, import_telemetry_contracts.summarizeDiagnostic)(content.data)
|
|
395
|
+
};
|
|
396
|
+
if (object) {
|
|
397
|
+
const byScope = captured.get(object) ?? /* @__PURE__ */ new Map();
|
|
398
|
+
byScope.set(scope, result);
|
|
399
|
+
captured.set(object, byScope);
|
|
400
|
+
}
|
|
401
|
+
return result;
|
|
402
|
+
};
|
|
403
|
+
const flushWithDeadline = async (timeoutMs = 5e3) => {
|
|
404
|
+
let deadline;
|
|
405
|
+
let timedOut = false;
|
|
406
|
+
await Promise.race([
|
|
407
|
+
flush(),
|
|
408
|
+
new Promise((resolve) => {
|
|
409
|
+
deadline = setTimeout(
|
|
410
|
+
() => {
|
|
411
|
+
timedOut = true;
|
|
412
|
+
resolve();
|
|
413
|
+
},
|
|
414
|
+
Math.max(0, timeoutMs)
|
|
415
|
+
);
|
|
416
|
+
})
|
|
417
|
+
]);
|
|
418
|
+
if (deadline) clearTimeout(deadline);
|
|
419
|
+
return {
|
|
420
|
+
timedOut,
|
|
421
|
+
pending: queue.size,
|
|
422
|
+
pendingBytes: queuedBytes,
|
|
423
|
+
dropped,
|
|
424
|
+
states: Object.fromEntries(states)
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
return {
|
|
428
|
+
capture,
|
|
429
|
+
flush,
|
|
430
|
+
flushWithDeadline,
|
|
431
|
+
getState: (id) => states.get(id),
|
|
432
|
+
getDroppedCount: () => dropped
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/event-mapper.ts
|
|
437
|
+
var import_errors2 = require("@kortyx/core/errors");
|
|
438
|
+
var import_internal2 = require("@kortyx/hooks/internal");
|
|
439
|
+
var import_telemetry_contracts2 = require("@kortyx/telemetry-contracts");
|
|
137
440
|
var stringValue = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
138
441
|
var shouldCapture = (value, side) => {
|
|
139
442
|
if (value === true) return true;
|
|
140
443
|
return Boolean(value && typeof value === "object" && value[side]);
|
|
141
444
|
};
|
|
142
|
-
var asErrorPayload = (error, project) => {
|
|
143
|
-
if ((0,
|
|
445
|
+
var asErrorPayload = (error, project, captured) => {
|
|
446
|
+
if ((0, import_errors2.isControlFlowError)(error))
|
|
144
447
|
return {
|
|
145
|
-
name: (0,
|
|
146
|
-
code: (0,
|
|
448
|
+
name: (0, import_errors2.errorProperty)(error, "name"),
|
|
449
|
+
code: (0, import_errors2.errorProperty)(error, "code"),
|
|
147
450
|
message: "Execution paused or cancelled.",
|
|
148
451
|
controlFlow: true
|
|
149
452
|
};
|
|
150
|
-
const failure = (0,
|
|
151
|
-
const diagnostic = (0,
|
|
453
|
+
const failure = (0, import_errors2.serializeFailure)(error);
|
|
454
|
+
const diagnostic = captured ? captured.details : (0, import_internal2.exceptionDiagnostics)(error, project);
|
|
455
|
+
const summary = diagnostic ? (0, import_telemetry_contracts2.summarizeDiagnostic)(diagnostic) : null;
|
|
456
|
+
const reference = captured ? Object.fromEntries(
|
|
457
|
+
Object.entries(captured).filter(([key]) => key !== "details")
|
|
458
|
+
) : {};
|
|
152
459
|
return {
|
|
153
460
|
...failure,
|
|
154
|
-
name:
|
|
155
|
-
message:
|
|
156
|
-
...
|
|
157
|
-
...
|
|
461
|
+
name: summary?.type ?? "Error",
|
|
462
|
+
message: summary?.message ?? failure.message,
|
|
463
|
+
...summary?.stack ? { stack: summary.stack } : {},
|
|
464
|
+
...summary?.cause ? { cause: summary.cause } : {},
|
|
465
|
+
...reference
|
|
158
466
|
};
|
|
159
467
|
};
|
|
160
468
|
var correlationFrom = (attributes, active) => {
|
|
@@ -197,7 +505,7 @@ var createEventMapper = (args) => {
|
|
|
197
505
|
...input.context || args.metadata || args.tags ? {
|
|
198
506
|
context: {
|
|
199
507
|
...args.tags ? { tags: args.tags } : {},
|
|
200
|
-
...args.metadata ? { metadata: (0,
|
|
508
|
+
...args.metadata ? { metadata: (0, import_internal2.safeTelemetryMetadata)(args.metadata) } : {},
|
|
201
509
|
...input.context ?? {}
|
|
202
510
|
}
|
|
203
511
|
} : {},
|
|
@@ -211,7 +519,7 @@ var createEventMapper = (args) => {
|
|
|
211
519
|
});
|
|
212
520
|
const spanContext = (telemetry, attributes) => {
|
|
213
521
|
const tags = [...args.tags ?? [], ...telemetry?.tags ?? []];
|
|
214
|
-
const metadata = (0,
|
|
522
|
+
const metadata = (0, import_internal2.safeTelemetryMetadata)({
|
|
215
523
|
...args.metadata ?? {},
|
|
216
524
|
...telemetry?.metadata ?? {}
|
|
217
525
|
});
|
|
@@ -227,7 +535,7 @@ var createEventMapper = (args) => {
|
|
|
227
535
|
const telemetryPayload = (telemetry) => ({
|
|
228
536
|
...telemetry?.operation ? { operation: telemetry.operation } : {},
|
|
229
537
|
...telemetry?.tags?.length ? { tags: telemetry.tags } : {},
|
|
230
|
-
...telemetry?.metadata ? { metadata: (0,
|
|
538
|
+
...telemetry?.metadata ? { metadata: (0, import_internal2.safeTelemetryMetadata)(telemetry.metadata) } : {},
|
|
231
539
|
...telemetry?.prompt ? {
|
|
232
540
|
prompt: {
|
|
233
541
|
...telemetry.prompt.name ? { name: telemetry.prompt.name } : {},
|
|
@@ -238,7 +546,11 @@ var createEventMapper = (args) => {
|
|
|
238
546
|
} : {}
|
|
239
547
|
});
|
|
240
548
|
return {
|
|
241
|
-
asErrorPayload: (error) => asErrorPayload(
|
|
549
|
+
asErrorPayload: (error, context) => asErrorPayload(
|
|
550
|
+
error,
|
|
551
|
+
context?.project ?? args.error,
|
|
552
|
+
context ? args.captureDiagnostic?.(error, context) : void 0
|
|
553
|
+
),
|
|
242
554
|
correlationFrom,
|
|
243
555
|
createEvent,
|
|
244
556
|
shouldCapture,
|
|
@@ -287,8 +599,8 @@ var createTopologyResolver = (args) => {
|
|
|
287
599
|
|
|
288
600
|
// src/trace.ts
|
|
289
601
|
var import_node_async_hooks = require("async_hooks");
|
|
290
|
-
var
|
|
291
|
-
var
|
|
602
|
+
var import_errors3 = require("@kortyx/core/errors");
|
|
603
|
+
var import_telemetry_contracts3 = require("@kortyx/telemetry-contracts");
|
|
292
604
|
var providerPricing = (metadata) => {
|
|
293
605
|
if (metadata?.providerId !== "openrouter") return void 0;
|
|
294
606
|
const details = metadata.costDetails;
|
|
@@ -322,7 +634,7 @@ var createTraceAdapter = (args) => {
|
|
|
322
634
|
correlation,
|
|
323
635
|
span,
|
|
324
636
|
...parent ? { parentSpanId: parent.spanId } : {},
|
|
325
|
-
payload: isTool ?
|
|
637
|
+
payload: isTool ? import_telemetry_contracts3.ToolObservationSchema.parse(attributes) : {
|
|
326
638
|
name: startArgs.name,
|
|
327
639
|
attributes: currentAttributes,
|
|
328
640
|
telemetry: args.eventMapper.telemetryPayload(
|
|
@@ -354,7 +666,7 @@ var createTraceAdapter = (args) => {
|
|
|
354
666
|
const telemetry = endArgs?.telemetry ?? startArgs.telemetry;
|
|
355
667
|
const durationMs = Date.now() - startedAt;
|
|
356
668
|
if (isTool) {
|
|
357
|
-
const payload =
|
|
669
|
+
const payload = import_telemetry_contracts3.ToolObservationSchema.parse(endAttributes);
|
|
358
670
|
const type = payload.observationKind === "reused" ? "tool.reused" : payload.observationKind === "waiting" ? "tool.waiting" : payload.suspended ? "tool.suspended" : payload.outcome === "denied" ? "tool.denied" : payload.outcome === "fault" ? "tool.failed" : payload.outcome === "cancelled" ? "tool.cancelled" : "tool.completed";
|
|
359
671
|
args.enqueue(
|
|
360
672
|
args.eventMapper.createEvent({
|
|
@@ -475,7 +787,7 @@ var createTraceAdapter = (args) => {
|
|
|
475
787
|
end,
|
|
476
788
|
fail: (error, endArgs) => {
|
|
477
789
|
if (ended) return;
|
|
478
|
-
if ((0,
|
|
790
|
+
if ((0, import_errors3.isSuspensionControlFlowError)(error)) {
|
|
479
791
|
suspended = true;
|
|
480
792
|
Object.assign(currentAttributes, {
|
|
481
793
|
"kortyx.control_flow": true,
|
|
@@ -485,6 +797,12 @@ var createTraceAdapter = (args) => {
|
|
|
485
797
|
return;
|
|
486
798
|
}
|
|
487
799
|
failed = true;
|
|
800
|
+
const errorPayload = args.eventMapper.asErrorPayload(error, {
|
|
801
|
+
correlation: { ...correlation, ...span },
|
|
802
|
+
handled: false,
|
|
803
|
+
severity: "error",
|
|
804
|
+
mechanism: "span"
|
|
805
|
+
});
|
|
488
806
|
if (correlation) {
|
|
489
807
|
args.enqueue(
|
|
490
808
|
args.eventMapper.createEvent({
|
|
@@ -494,7 +812,7 @@ var createTraceAdapter = (args) => {
|
|
|
494
812
|
...parent ? { parentSpanId: parent.spanId } : {},
|
|
495
813
|
payload: {
|
|
496
814
|
name: startArgs.name,
|
|
497
|
-
error:
|
|
815
|
+
error: errorPayload,
|
|
498
816
|
handled: false,
|
|
499
817
|
severity: "error",
|
|
500
818
|
durationMs: Date.now() - startedAt
|
|
@@ -536,7 +854,19 @@ var createTraceAdapter = (args) => {
|
|
|
536
854
|
reportError: (error, options = {}) => {
|
|
537
855
|
try {
|
|
538
856
|
const active = activeSpans.getStore();
|
|
539
|
-
|
|
857
|
+
const payload = args.eventMapper.asErrorPayload(error, {
|
|
858
|
+
correlation: {
|
|
859
|
+
...active?.correlation,
|
|
860
|
+
...active ? { traceId: active.traceId, spanId: active.spanId } : {},
|
|
861
|
+
...options.correlation
|
|
862
|
+
},
|
|
863
|
+
handled: true,
|
|
864
|
+
severity: options.severity === "warning" ? "warning" : "error",
|
|
865
|
+
mechanism: options.mechanism ?? "report",
|
|
866
|
+
project: options.error
|
|
867
|
+
});
|
|
868
|
+
if (!active)
|
|
869
|
+
return typeof payload.diagnosticId === "string" ? payload.diagnosticId : void 0;
|
|
540
870
|
args.enqueue(
|
|
541
871
|
args.eventMapper.createEvent({
|
|
542
872
|
type: "error.reported",
|
|
@@ -545,7 +875,7 @@ var createTraceAdapter = (args) => {
|
|
|
545
875
|
payload: {
|
|
546
876
|
handled: true,
|
|
547
877
|
severity: options.severity === "warning" ? "warning" : "error",
|
|
548
|
-
error:
|
|
878
|
+
error: payload
|
|
549
879
|
},
|
|
550
880
|
context: args.eventMapper.spanContext(
|
|
551
881
|
{
|
|
@@ -556,7 +886,9 @@ var createTraceAdapter = (args) => {
|
|
|
556
886
|
)
|
|
557
887
|
})
|
|
558
888
|
);
|
|
889
|
+
return typeof payload.diagnosticId === "string" ? payload.diagnosticId : void 0;
|
|
559
890
|
} catch {
|
|
891
|
+
return void 0;
|
|
560
892
|
}
|
|
561
893
|
}
|
|
562
894
|
};
|
|
@@ -568,7 +900,7 @@ var DEFAULT_FLUSH_INTERVAL_MS = 250;
|
|
|
568
900
|
var DEFAULT_MAX_QUEUE_SIZE = 1e3;
|
|
569
901
|
var createId = () => {
|
|
570
902
|
try {
|
|
571
|
-
return (0,
|
|
903
|
+
return (0, import_node_crypto2.randomUUID)();
|
|
572
904
|
} catch {
|
|
573
905
|
return `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
574
906
|
}
|
|
@@ -600,12 +932,14 @@ function createKortyxTelemetryAdapter(options) {
|
|
|
600
932
|
await send("/v1/telemetry/events:batch", { events });
|
|
601
933
|
}
|
|
602
934
|
});
|
|
935
|
+
const diagnostics = createDiagnosticDelivery(options);
|
|
603
936
|
const eventMapper = createEventMapper({
|
|
604
937
|
environment: options.environment,
|
|
605
938
|
service: options.service,
|
|
606
939
|
...options.metadata ? { metadata: options.metadata } : {},
|
|
607
940
|
...options.tags ? { tags: options.tags } : {},
|
|
608
941
|
createId,
|
|
942
|
+
captureDiagnostic: diagnostics.capture,
|
|
609
943
|
...options.error ? { error: options.error } : {}
|
|
610
944
|
});
|
|
611
945
|
const topology = createTopologyResolver({
|
|
@@ -638,7 +972,13 @@ function createKortyxTelemetryAdapter(options) {
|
|
|
638
972
|
...options.captureContent ? { captureContent: options.captureContent } : {},
|
|
639
973
|
...options.metadata ? { metadata: options.metadata } : {},
|
|
640
974
|
...options.tags ? { tags: options.tags } : {},
|
|
641
|
-
flush:
|
|
975
|
+
flush: async () => {
|
|
976
|
+
await delivery.flush();
|
|
977
|
+
await diagnostics.flush();
|
|
978
|
+
},
|
|
979
|
+
flushDiagnostics: diagnostics.flushWithDeadline,
|
|
980
|
+
getDiagnosticDeliveryState: diagnostics.getState,
|
|
981
|
+
getDroppedDiagnosticCount: diagnostics.getDroppedCount,
|
|
642
982
|
getDroppedEventCount: delivery.getDroppedEventCount,
|
|
643
983
|
getPermanentDeliveryFailureCount: delivery.getPermanentDeliveryFailureCount
|
|
644
984
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/delivery.ts","../src/event-mapper.ts","../src/topology.ts","../src/trace.ts"],"sourcesContent":["export { createKortyxTelemetryAdapter } from \"./adapter\";\nexport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n","import { randomUUID } from \"node:crypto\";\nimport type {\n EnsureWorkflowTopologyResponse,\n KortyxTelemetryEvent,\n} from \"@kortyx/hooks\";\nimport { createDelivery, TelemetryHttpError } from \"./delivery\";\nimport { createEventMapper } from \"./event-mapper\";\nimport { createTopologyResolver } from \"./topology\";\nimport { createTraceAdapter } from \"./trace\";\nimport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n\nexport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 250;\nconst DEFAULT_MAX_QUEUE_SIZE = 1_000;\n\nconst createId = (): string => {\n try {\n return randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n};\n\nconst endpointFor = (endpoint: string, path: string): string =>\n `${endpoint.replace(/\\/$/, \"\")}${path}`;\n\n/**\n * Creates the optional Kortyx Studio HTTP adapter. Execution paths only enqueue\n * telemetry; delivery remains best-effort and cannot fail a workflow.\n */\nexport function createKortyxTelemetryAdapter(\n options: CreateKortyxTelemetryAdapterOptions,\n): KortyxTelemetryAdapter {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new Error(\n \"createKortyxTelemetryAdapter requires a fetch implementation.\",\n );\n }\n\n const send = async (path: string, body: unknown): Promise<Response> => {\n const response = await fetchImpl(endpointFor(options.endpoint, path), {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${options.apiKey}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new TelemetryHttpError(response.status);\n return response;\n };\n\n const delivery = createDelivery({\n maxQueueSize: options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n flushIntervalMs: options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n send: async (events) => {\n await send(\"/v1/telemetry/events:batch\", { events });\n },\n });\n const eventMapper = createEventMapper({\n environment: options.environment,\n service: options.service,\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n createId,\n ...(options.error ? { error: options.error } : {}),\n });\n const topology = createTopologyResolver({\n ensure: async (snapshot) => {\n const response = await send(\n \"/v1/telemetry/workflow-revisions:ensure\",\n snapshot,\n );\n return (await response.json()) as EnsureWorkflowTopologyResponse;\n },\n });\n const trace = createTraceAdapter({\n ...(options.captureContent\n ? { captureContent: options.captureContent }\n : {}),\n createId,\n enqueue: delivery.enqueue,\n eventMapper,\n });\n const emit = async (events: KortyxTelemetryEvent[]): Promise<void> => {\n for (const event of events) delivery.enqueue(event);\n };\n\n return {\n trace,\n reporter: {\n ensureWorkflowTopology: topology.ensureWorkflowTopology,\n emit,\n getWorkflowRevisionId: topology.getWorkflowRevisionId,\n },\n environment: options.environment,\n service: options.service,\n ...(options.captureContent\n ? { captureContent: options.captureContent }\n : {}),\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n flush: delivery.flush,\n getDroppedEventCount: delivery.getDroppedEventCount,\n getPermanentDeliveryFailureCount: delivery.getPermanentDeliveryFailureCount,\n };\n}\n","import type { KortyxTelemetryEvent } from \"@kortyx/hooks\";\n\nexport class TelemetryHttpError extends Error {\n constructor(readonly status: number) {\n super(`Kortyx telemetry request failed (${status}).`);\n }\n}\n\nexport const createDelivery = (args: {\n maxQueueSize: number;\n flushIntervalMs: number;\n send: (events: KortyxTelemetryEvent[]) => Promise<void>;\n}) => {\n const queue: KortyxTelemetryEvent[] = [];\n let dropped = 0;\n let permanentFailures = 0;\n let retryAttempt = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let inFlight: Promise<{ retryDelay: number | null }> | undefined;\n const sendBatch = async (events: KortyxTelemetryEvent[]): Promise<void> => {\n try {\n await args.send(events);\n } catch (error) {\n const status =\n error instanceof TelemetryHttpError ? error.status : undefined;\n // One invalid event (or an oversized request) must not discard the other\n // lifecycle facts in the same flush. Event IDs make a later retry safe.\n if (\n events.length > 1 &&\n (status === 400 || status === 413 || status === 422)\n ) {\n const middle = Math.floor(events.length / 2);\n await sendBatch(events.slice(0, middle));\n await sendBatch(events.slice(middle));\n return;\n }\n if (\n events.length === 1 &&\n status !== undefined &&\n status !== 429 &&\n status < 500\n ) {\n permanentFailures += 1;\n return;\n }\n throw error;\n }\n };\n const schedule = (delay = args.flushIntervalMs) => {\n if (timer || inFlight || queue.length === 0) return;\n timer = setTimeout(() => {\n timer = undefined;\n void flush();\n }, delay);\n if (typeof timer === \"object\" && \"unref\" in timer) timer.unref?.();\n };\n const flush = async (): Promise<void> => {\n while (true) {\n if (inFlight) {\n const result = await inFlight;\n if (result.retryDelay !== null) return;\n continue;\n }\n if (timer) {\n clearTimeout(timer);\n timer = undefined;\n }\n if (queue.length === 0) return;\n const events = queue.splice(0);\n const current = (async (): Promise<{ retryDelay: number | null }> => {\n try {\n await sendBatch(events);\n retryAttempt = 0;\n return { retryDelay: null };\n } catch (error) {\n const status =\n error instanceof TelemetryHttpError ? error.status : undefined;\n if (status !== undefined && status !== 429 && status < 500) {\n permanentFailures += events.length;\n return { retryDelay: null };\n }\n const overflow = Math.max(\n 0,\n queue.length + events.length - args.maxQueueSize,\n );\n if (overflow) {\n dropped += overflow;\n events.splice(0, overflow);\n }\n queue.unshift(...events);\n retryAttempt += 1;\n const backoff = Math.min(30_000, 250 * 2 ** (retryAttempt - 1));\n return {\n retryDelay: Math.floor(backoff * (0.5 + Math.random() * 0.5)),\n };\n }\n })();\n inFlight = current;\n const result = await current;\n if (inFlight === current) inFlight = undefined;\n if (result.retryDelay !== null) {\n schedule(result.retryDelay);\n return;\n }\n }\n };\n return {\n enqueue: (event: KortyxTelemetryEvent) => {\n if (queue.length >= args.maxQueueSize) {\n queue.shift();\n dropped += 1;\n }\n queue.push(event);\n schedule();\n },\n flush,\n getDroppedEventCount: () => dropped,\n getPermanentDeliveryFailureCount: () => permanentFailures,\n };\n};\n","import {\n errorProperty,\n isControlFlowError,\n serializeFailure,\n} from \"@kortyx/core/errors\";\nimport type {\n KortyxTelemetryConfig,\n KortyxTelemetryEvent,\n KortyxTelemetryEventType,\n ReasonTraceAttributes,\n ReasonTraceSpanStartArgs,\n} from \"@kortyx/hooks\";\nimport {\n exceptionDiagnostics,\n safeTelemetryMetadata,\n} from \"@kortyx/hooks/internal\";\nimport type { ActiveSpan, SpanContext } from \"./types\";\n\nconst stringValue = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value : undefined;\n\nconst shouldCapture = (\n value: KortyxTelemetryConfig[\"captureContent\"] | undefined,\n side: \"input\" | \"output\",\n): boolean => {\n if (value === true) return true;\n return Boolean(value && typeof value === \"object\" && value[side]);\n};\n\nconst asErrorPayload = (\n error: unknown,\n project?: import(\"@kortyx/hooks\").KortyxTraceErrorProjection,\n): Record<string, unknown> => {\n if (isControlFlowError(error))\n return {\n name: errorProperty(error, \"name\"),\n code: errorProperty(error, \"code\"),\n message: \"Execution paused or cancelled.\",\n controlFlow: true,\n };\n const failure = serializeFailure(error);\n const diagnostic = exceptionDiagnostics(error, project);\n return {\n ...failure,\n name: diagnostic?.type ?? \"Error\",\n message: diagnostic?.message ?? failure.message,\n ...(diagnostic?.stack ? { stack: diagnostic.stack } : {}),\n ...(diagnostic?.cause ? { cause: diagnostic.cause } : {}),\n };\n};\n\nconst correlationFrom = (\n attributes: ReasonTraceAttributes | undefined,\n active: ActiveSpan | undefined,\n): KortyxTelemetryEvent[\"correlation\"] | undefined => {\n const source = attributes ?? {};\n const runId = stringValue(source.runId) ?? active?.correlation.runId;\n const workflowId =\n stringValue(source.workflowId) ?? active?.correlation.workflowId;\n if (!runId || !workflowId) return undefined;\n\n const sameWorkflow = workflowId === active?.correlation.workflowId;\n const sessionId =\n stringValue(source.sessionId) ?? active?.correlation.sessionId;\n const workflowRevisionId =\n stringValue(source.workflowRevisionId) ??\n (sameWorkflow ? active?.correlation.workflowRevisionId : undefined);\n const topologyHash =\n stringValue(source.topologyHash) ??\n (sameWorkflow ? active?.correlation.topologyHash : undefined);\n const nodeId =\n stringValue(source.nodeId) ??\n (sameWorkflow ? active?.correlation.nodeId : undefined);\n return {\n runId,\n workflowId,\n ...Object.fromEntries(\n [\"invocationId\", \"parentInvocationId\", \"branchId\"].flatMap((key) => {\n const value =\n stringValue(source[key]) ??\n active?.correlation[key as \"invocationId\"];\n return value ? [[key, value]] : [];\n }),\n ),\n ...(sessionId ? { sessionId } : {}),\n ...(workflowRevisionId ? { workflowRevisionId } : {}),\n ...(topologyHash ? { topologyHash } : {}),\n ...(nodeId ? { nodeId } : {}),\n };\n};\n\nexport const createEventMapper = (args: {\n environment: string;\n service: KortyxTelemetryEvent[\"service\"];\n metadata?: Record<string, unknown> | undefined;\n tags?: string[] | undefined;\n createId: () => string;\n error?: import(\"@kortyx/hooks\").KortyxTraceErrorProjection;\n}) => {\n const createEvent = (input: {\n type: KortyxTelemetryEventType;\n correlation: KortyxTelemetryEvent[\"correlation\"];\n span?: SpanContext | undefined;\n parentSpanId?: string | undefined;\n payload: Record<string, unknown>;\n context?: KortyxTelemetryEvent[\"context\"] | undefined;\n }): KortyxTelemetryEvent => ({\n schemaVersion: 1,\n eventId: args.createId(),\n occurredAt: new Date().toISOString(),\n environment: args.environment,\n service: args.service,\n correlation: {\n ...input.correlation,\n ...(input.span\n ? { traceId: input.span.traceId, spanId: input.span.spanId }\n : {}),\n ...(input.parentSpanId ? { parentSpanId: input.parentSpanId } : {}),\n },\n ...(input.context || args.metadata || args.tags\n ? {\n context: {\n ...(args.tags ? { tags: args.tags } : {}),\n ...(args.metadata\n ? { metadata: safeTelemetryMetadata(args.metadata) }\n : {}),\n ...(input.context ?? {}),\n },\n }\n : {}),\n type: input.type,\n payload: {\n ...input.payload,\n ...(input.correlation.invocationId\n ? { invocationId: input.correlation.invocationId }\n : {}),\n ...(input.correlation.parentInvocationId\n ? { parentInvocationId: input.correlation.parentInvocationId }\n : {}),\n ...(input.correlation.branchId\n ? { branchId: input.correlation.branchId }\n : {}),\n },\n });\n\n const spanContext = (\n telemetry: ReasonTraceSpanStartArgs[\"telemetry\"] | undefined,\n attributes: ReasonTraceAttributes,\n ): KortyxTelemetryEvent[\"context\"] | undefined => {\n const tags = [...(args.tags ?? []), ...(telemetry?.tags ?? [])];\n const metadata = safeTelemetryMetadata({\n ...(args.metadata ?? {}),\n ...(telemetry?.metadata ?? {}),\n });\n const userId = stringValue(attributes.userId);\n const tenantId = stringValue(attributes.tenantId);\n return userId || tenantId || tags.length || Object.keys(metadata).length\n ? {\n ...(userId ? { userId } : {}),\n ...(tenantId ? { tenantId } : {}),\n ...(tags.length ? { tags } : {}),\n ...(Object.keys(metadata).length ? { metadata } : {}),\n }\n : undefined;\n };\n\n const telemetryPayload = (\n telemetry: ReasonTraceSpanStartArgs[\"telemetry\"] | undefined,\n ): Record<string, unknown> => ({\n ...(telemetry?.operation ? { operation: telemetry.operation } : {}),\n ...(telemetry?.tags?.length ? { tags: telemetry.tags } : {}),\n ...(telemetry?.metadata\n ? { metadata: safeTelemetryMetadata(telemetry.metadata) }\n : {}),\n ...(telemetry?.prompt\n ? {\n prompt: {\n ...(telemetry.prompt.name ? { name: telemetry.prompt.name } : {}),\n ...(telemetry.prompt.version !== undefined\n ? { version: telemetry.prompt.version }\n : {}),\n ...(telemetry.prompt.type ? { type: telemetry.prompt.type } : {}),\n ...(telemetry.prompt.source\n ? { source: telemetry.prompt.source }\n : {}),\n },\n }\n : {}),\n });\n\n return {\n asErrorPayload: (error: unknown) => asErrorPayload(error, args.error),\n correlationFrom,\n createEvent,\n shouldCapture,\n spanContext,\n stringValue,\n telemetryPayload,\n };\n};\n","import type {\n EnsureWorkflowTopologyRequest,\n EnsureWorkflowTopologyResponse,\n} from \"@kortyx/hooks\";\n\ntype TopologyKey = {\n environment: string;\n workflowId: string;\n topologyHash: string;\n};\n\nconst keyFor = ({ environment, workflowId, topologyHash }: TopologyKey) =>\n `${environment}:${workflowId}:${topologyHash}`;\n\n/** Caches successful topology ensures and coalesces concurrent requests. */\nexport const createTopologyResolver = (args: {\n ensure: (\n snapshot: EnsureWorkflowTopologyRequest,\n ) => Promise<EnsureWorkflowTopologyResponse>;\n}) => {\n const revisions = new Map<string, string>();\n const pending = new Map<string, Promise<EnsureWorkflowTopologyResponse>>();\n\n const ensureWorkflowTopology = (\n snapshot: EnsureWorkflowTopologyRequest,\n ): Promise<EnsureWorkflowTopologyResponse> => {\n const key = keyFor({\n environment: snapshot.environment,\n workflowId: snapshot.workflow.id,\n topologyHash: snapshot.workflow.topologyHash,\n });\n const revision = revisions.get(key);\n if (revision) {\n return Promise.resolve({ workflowRevisionId: revision, created: false });\n }\n\n const existing = pending.get(key);\n if (existing) return existing;\n\n const request = args\n .ensure(snapshot)\n .then((result) => {\n if (!result.workflowRevisionId) {\n throw new Error(\n \"Telemetry API returned an invalid workflow revision.\",\n );\n }\n revisions.set(key, result.workflowRevisionId);\n return result;\n })\n .finally(() => {\n pending.delete(key);\n });\n pending.set(key, request);\n return request;\n };\n\n return {\n ensureWorkflowTopology,\n getWorkflowRevisionId: (args: TopologyKey) => revisions.get(keyFor(args)),\n };\n};\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { isSuspensionControlFlowError } from \"@kortyx/core/errors\";\nimport type {\n KortyxTelemetryConfig,\n KortyxTelemetryEvent,\n ReasonTraceAdapter,\n ReasonTraceSpan,\n ReasonTraceSpanEndArgs,\n ReasonTraceSpanStartArgs,\n} from \"@kortyx/hooks\";\nimport { ToolObservationSchema } from \"@kortyx/telemetry-contracts\";\nimport type { createEventMapper } from \"./event-mapper\";\nimport type { ActiveSpan, SpanContext } from \"./types\";\n\nconst providerPricing = (\n metadata: ReasonTraceSpanEndArgs[\"providerMetadata\"],\n): Record<string, unknown> | undefined => {\n if (metadata?.providerId !== \"openrouter\") return undefined;\n const details = metadata.costDetails;\n const upstreamCost =\n details && typeof details === \"object\" && !Array.isArray(details)\n ? (details as Record<string, unknown>).upstreamInferenceCost\n : undefined;\n const cost = metadata.isByok === true ? upstreamCost : metadata.cost;\n if (typeof cost !== \"number\" || !Number.isFinite(cost) || cost < 0)\n return undefined;\n return {\n source: \"provider\",\n currency: \"USD\",\n actualCostMicros: Math.round(cost * 1_000_000),\n };\n};\n\n/** Maps generic SDK trace calls to Kortyx Studio's span and generation facts. */\nexport const createTraceAdapter = (args: {\n captureContent?: KortyxTelemetryConfig[\"captureContent\"] | undefined;\n createId: () => string;\n enqueue: (event: KortyxTelemetryEvent) => void;\n eventMapper: ReturnType<typeof createEventMapper>;\n}): ReasonTraceAdapter => {\n const activeSpans = new AsyncLocalStorage<ActiveSpan>();\n\n const createSpan = (\n startArgs: ReasonTraceSpanStartArgs,\n ): { span: ReasonTraceSpan; active?: ActiveSpan | undefined } => {\n const parent = activeSpans.getStore();\n const span: SpanContext = {\n traceId: parent?.traceId ?? args.createId(),\n spanId: args.createId(),\n };\n const attributes = { ...(startArgs.attributes ?? {}) };\n const currentAttributes = { ...attributes };\n const correlation = args.eventMapper.correlationFrom(attributes, parent);\n const startedAt = Date.now();\n\n const isTool = startArgs.name === \"kortyx.tool\";\n if (correlation && (!isTool || attributes.executed === true)) {\n args.enqueue(\n args.eventMapper.createEvent({\n type: isTool ? \"tool.started\" : \"span.started\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: isTool\n ? ToolObservationSchema.parse(attributes)\n : {\n name: startArgs.name,\n attributes: currentAttributes,\n telemetry: args.eventMapper.telemetryPayload(\n startArgs.telemetry,\n ),\n ...(args.eventMapper.shouldCapture(\n startArgs.telemetry?.captureContent ?? args.captureContent,\n \"input\",\n )\n ? { input: startArgs.telemetry?.input }\n : {}),\n },\n context: args.eventMapper.spanContext(\n startArgs.telemetry,\n currentAttributes,\n ),\n }),\n );\n }\n\n let ended = false;\n let failed = false;\n let suspended = false;\n const end = (endArgs?: ReasonTraceSpanEndArgs): void => {\n if (ended) return;\n ended = true;\n if (!correlation) return;\n\n const endAttributes = {\n ...currentAttributes,\n ...(endArgs?.attributes ?? {}),\n };\n const telemetry = endArgs?.telemetry ?? startArgs.telemetry;\n const durationMs = Date.now() - startedAt;\n if (isTool) {\n const payload = ToolObservationSchema.parse(endAttributes);\n const type =\n payload.observationKind === \"reused\"\n ? \"tool.reused\"\n : payload.observationKind === \"waiting\"\n ? \"tool.waiting\"\n : payload.suspended\n ? \"tool.suspended\"\n : payload.outcome === \"denied\"\n ? \"tool.denied\"\n : payload.outcome === \"fault\"\n ? \"tool.failed\"\n : payload.outcome === \"cancelled\"\n ? \"tool.cancelled\"\n : \"tool.completed\";\n args.enqueue(\n args.eventMapper.createEvent({\n type,\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload,\n }),\n );\n return;\n }\n\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"span.ended\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n name: startArgs.name,\n attributes: endAttributes,\n durationMs,\n telemetry: args.eventMapper.telemetryPayload(telemetry),\n ...(args.eventMapper.shouldCapture(\n endArgs?.telemetry?.captureContent ??\n startArgs.telemetry?.captureContent ??\n args.captureContent,\n \"output\",\n )\n ? { output: endArgs?.telemetry?.output }\n : {}),\n },\n context: args.eventMapper.spanContext(telemetry, endAttributes),\n }),\n );\n\n if (startArgs.name !== \"runReasonEngine\" || suspended) return;\n const ttftMs = nonnegativeNumber(endAttributes.ttftMs);\n const streamDurationMs = nonnegativeNumber(\n endAttributes.streamDurationMs,\n );\n const timeToLastTokenMs = nonnegativeNumber(\n endAttributes.timeToLastTokenMs,\n );\n const pricing = providerPricing(endArgs?.providerMetadata);\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"generation.completed\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n outcome: failed ? \"failed\" : \"completed\",\n provider:\n args.eventMapper.stringValue(attributes.providerId) ?? \"unknown\",\n model:\n args.eventMapper.stringValue(attributes.modelId) ?? \"unknown\",\n durationMs,\n ...(ttftMs !== undefined ? { ttftMs } : {}),\n ...(streamDurationMs !== undefined ? { streamDurationMs } : {}),\n ...(timeToLastTokenMs !== undefined\n ? {\n postStreamDurationMs: Math.max(\n 0,\n durationMs - timeToLastTokenMs,\n ),\n }\n : {}),\n ...(endArgs?.usage\n ? {\n usage: failed\n ? Object.fromEntries(\n Object.entries(endArgs.usage).filter(\n ([key, value]) =>\n ([\n \"input\",\n \"output\",\n \"total\",\n \"reasoning\",\n \"cacheRead\",\n \"cacheWrite\",\n \"cacheWrite1h\",\n ].includes(key) &&\n typeof value === \"number\" &&\n Number.isFinite(value)) ||\n ([\n \"outputIncludesReasoning\",\n \"inputIncludesCacheRead\",\n \"inputIncludesCacheWrite\",\n ].includes(key) &&\n typeof value === \"boolean\"),\n ),\n )\n : endArgs.usage,\n }\n : {}),\n ...(endArgs?.finishReason\n ? { finishReason: endArgs.finishReason }\n : {}),\n ...(endArgs?.warnings ? { warnings: endArgs.warnings } : {}),\n ...(pricing ? { pricing } : {}),\n ...(endArgs?.providerMetadata && !failed\n ? { providerMetadata: endArgs.providerMetadata }\n : {}),\n },\n context: args.eventMapper.spanContext(telemetry, currentAttributes),\n }),\n );\n };\n\n const traceSpan: ReasonTraceSpan = {\n setAttributes: (nextAttributes) => {\n Object.assign(currentAttributes, nextAttributes);\n },\n addEvent: (name, eventAttributes = {}) => {\n if (\n !correlation ||\n activeSpans.getStore()?.name === \"kortyx.tool\" ||\n startArgs.name === \"kortyx.tool\"\n )\n return;\n const type =\n name === \"useReason.tool-call.start\"\n ? \"tool.started\"\n : name === \"useReason.tool-call.complete\"\n ? \"tool.completed\"\n : name === \"useReason.tool-call.error\"\n ? \"tool.failed\"\n : name === \"useReason.output.emitted\"\n ? \"output.emitted\"\n : name === \"useReason.output.invalidated\"\n ? \"output.invalidated\"\n : undefined;\n if (!type) return;\n const payload =\n type === \"output.emitted\"\n ? {\n ...Object.fromEntries(\n Object.entries(eventAttributes).filter(\n ([key]) => key !== \"data\",\n ),\n ),\n ...(args.eventMapper.shouldCapture(\n startArgs.telemetry?.captureContent ?? args.captureContent,\n \"output\",\n ) && \"data\" in eventAttributes\n ? { data: eventAttributes.data }\n : {}),\n }\n : eventAttributes;\n args.enqueue(\n args.eventMapper.createEvent({\n type,\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload,\n }),\n );\n },\n end,\n fail: (error, endArgs) => {\n if (ended) return;\n if (isSuspensionControlFlowError(error)) {\n suspended = true;\n Object.assign(currentAttributes, {\n \"kortyx.control_flow\": true,\n \"kortyx.suspended\": true,\n });\n end(endArgs);\n return;\n }\n failed = true;\n if (correlation) {\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"span.failed\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n name: startArgs.name,\n error: args.eventMapper.asErrorPayload(error),\n handled: false,\n severity: \"error\",\n durationMs: Date.now() - startedAt,\n },\n }),\n );\n }\n end(endArgs);\n },\n };\n\n return {\n span: traceSpan,\n ...(correlation\n ? { active: { ...span, name: startArgs.name, correlation } }\n : {}),\n };\n };\n\n return {\n startSpan: (startArgs) => createSpan(startArgs).span,\n withSpan: async (startArgs, fn) => {\n const created = createSpan(startArgs);\n const run = async (): Promise<Awaited<ReturnType<typeof fn>>> => {\n try {\n const result = await fn(created.span);\n created.span.end?.();\n return result;\n } catch (error) {\n try {\n created.span.fail?.(error);\n } catch {\n /* Preserve the callback failure. */\n }\n throw error;\n }\n };\n return created.active ? activeSpans.run(created.active, run) : run();\n },\n getActiveContext: () => {\n const active = activeSpans.getStore();\n return active\n ? { traceId: active.traceId, spanId: active.spanId }\n : undefined;\n },\n reportError: (error, options = {}) => {\n try {\n const active = activeSpans.getStore();\n if (!active) return;\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"error.reported\",\n correlation: active.correlation,\n span: active,\n payload: {\n handled: true,\n severity: options.severity === \"warning\" ? \"warning\" : \"error\",\n error: args.eventMapper.asErrorPayload(error),\n },\n context: args.eventMapper.spanContext(\n {\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n },\n {},\n ),\n }),\n );\n } catch {\n // Error reporting is an observer and cannot change execution.\n }\n },\n };\n};\n\nconst nonnegativeNumber = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) && value >= 0\n ? value\n : undefined;\n"],"mappings":"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","names":["result","args","import_errors"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/delivery.ts","../src/diagnostics.ts","../src/event-mapper.ts","../src/topology.ts","../src/trace.ts"],"sourcesContent":["export { createKortyxTelemetryAdapter } from \"./adapter\";\nexport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n","import { randomUUID } from \"node:crypto\";\nimport type {\n EnsureWorkflowTopologyResponse,\n KortyxTelemetryEvent,\n} from \"@kortyx/hooks\";\nimport { createDelivery, TelemetryHttpError } from \"./delivery\";\nimport { createDiagnosticDelivery } from \"./diagnostics\";\nimport { createEventMapper } from \"./event-mapper\";\nimport { createTopologyResolver } from \"./topology\";\nimport { createTraceAdapter } from \"./trace\";\nimport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n\nexport type {\n CreateKortyxTelemetryAdapterOptions,\n KortyxTelemetryAdapter,\n} from \"./types\";\n\nconst DEFAULT_FLUSH_INTERVAL_MS = 250;\nconst DEFAULT_MAX_QUEUE_SIZE = 1_000;\n\nconst createId = (): string => {\n try {\n return randomUUID();\n } catch {\n return `${Date.now()}-${Math.random().toString(36).slice(2)}`;\n }\n};\n\nconst endpointFor = (endpoint: string, path: string): string =>\n `${endpoint.replace(/\\/$/, \"\")}${path}`;\n\n/**\n * Creates the optional Kortyx Studio HTTP adapter. Execution paths only enqueue\n * telemetry; delivery remains best-effort and cannot fail a workflow.\n */\nexport function createKortyxTelemetryAdapter(\n options: CreateKortyxTelemetryAdapterOptions,\n): KortyxTelemetryAdapter {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new Error(\n \"createKortyxTelemetryAdapter requires a fetch implementation.\",\n );\n }\n\n const send = async (path: string, body: unknown): Promise<Response> => {\n const response = await fetchImpl(endpointFor(options.endpoint, path), {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${options.apiKey}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new TelemetryHttpError(response.status);\n return response;\n };\n\n const delivery = createDelivery({\n maxQueueSize: options.maxQueueSize ?? DEFAULT_MAX_QUEUE_SIZE,\n flushIntervalMs: options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,\n send: async (events) => {\n await send(\"/v1/telemetry/events:batch\", { events });\n },\n });\n const diagnostics = createDiagnosticDelivery(options);\n const eventMapper = createEventMapper({\n environment: options.environment,\n service: options.service,\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n createId,\n captureDiagnostic: diagnostics.capture,\n ...(options.error ? { error: options.error } : {}),\n });\n const topology = createTopologyResolver({\n ensure: async (snapshot) => {\n const response = await send(\n \"/v1/telemetry/workflow-revisions:ensure\",\n snapshot,\n );\n return (await response.json()) as EnsureWorkflowTopologyResponse;\n },\n });\n const trace = createTraceAdapter({\n ...(options.captureContent\n ? { captureContent: options.captureContent }\n : {}),\n createId,\n enqueue: delivery.enqueue,\n eventMapper,\n });\n const emit = async (events: KortyxTelemetryEvent[]): Promise<void> => {\n for (const event of events) delivery.enqueue(event);\n };\n\n return {\n trace,\n reporter: {\n ensureWorkflowTopology: topology.ensureWorkflowTopology,\n emit,\n getWorkflowRevisionId: topology.getWorkflowRevisionId,\n },\n environment: options.environment,\n service: options.service,\n ...(options.captureContent\n ? { captureContent: options.captureContent }\n : {}),\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n flush: async () => {\n await delivery.flush();\n await diagnostics.flush();\n },\n flushDiagnostics: diagnostics.flushWithDeadline,\n getDiagnosticDeliveryState: diagnostics.getState,\n getDroppedDiagnosticCount: diagnostics.getDroppedCount,\n getDroppedEventCount: delivery.getDroppedEventCount,\n getPermanentDeliveryFailureCount: delivery.getPermanentDeliveryFailureCount,\n };\n}\n","import type { KortyxTelemetryEvent } from \"@kortyx/hooks\";\n\nexport class TelemetryHttpError extends Error {\n constructor(readonly status: number) {\n super(`Kortyx telemetry request failed (${status}).`);\n }\n}\n\nexport const createDelivery = (args: {\n maxQueueSize: number;\n flushIntervalMs: number;\n send: (events: KortyxTelemetryEvent[]) => Promise<void>;\n}) => {\n const queue: KortyxTelemetryEvent[] = [];\n let dropped = 0;\n let permanentFailures = 0;\n let retryAttempt = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let inFlight: Promise<{ retryDelay: number | null }> | undefined;\n const sendBatch = async (events: KortyxTelemetryEvent[]): Promise<void> => {\n try {\n await args.send(events);\n } catch (error) {\n const status =\n error instanceof TelemetryHttpError ? error.status : undefined;\n // One invalid event (or an oversized request) must not discard the other\n // lifecycle facts in the same flush. Event IDs make a later retry safe.\n if (\n events.length > 1 &&\n (status === 400 || status === 413 || status === 422)\n ) {\n const middle = Math.floor(events.length / 2);\n await sendBatch(events.slice(0, middle));\n await sendBatch(events.slice(middle));\n return;\n }\n if (\n events.length === 1 &&\n status !== undefined &&\n status !== 429 &&\n status < 500\n ) {\n permanentFailures += 1;\n return;\n }\n throw error;\n }\n };\n const schedule = (delay = args.flushIntervalMs) => {\n if (timer || inFlight || queue.length === 0) return;\n timer = setTimeout(() => {\n timer = undefined;\n void flush();\n }, delay);\n if (typeof timer === \"object\" && \"unref\" in timer) timer.unref?.();\n };\n const flush = async (): Promise<void> => {\n while (true) {\n if (inFlight) {\n const result = await inFlight;\n if (result.retryDelay !== null) return;\n continue;\n }\n if (timer) {\n clearTimeout(timer);\n timer = undefined;\n }\n if (queue.length === 0) return;\n const events = queue.splice(0);\n const current = (async (): Promise<{ retryDelay: number | null }> => {\n try {\n await sendBatch(events);\n retryAttempt = 0;\n return { retryDelay: null };\n } catch (error) {\n const status =\n error instanceof TelemetryHttpError ? error.status : undefined;\n if (status !== undefined && status !== 429 && status < 500) {\n permanentFailures += events.length;\n return { retryDelay: null };\n }\n const overflow = Math.max(\n 0,\n queue.length + events.length - args.maxQueueSize,\n );\n if (overflow) {\n dropped += overflow;\n events.splice(0, overflow);\n }\n queue.unshift(...events);\n retryAttempt += 1;\n const backoff = Math.min(30_000, 250 * 2 ** (retryAttempt - 1));\n return {\n retryDelay: Math.floor(backoff * (0.5 + Math.random() * 0.5)),\n };\n }\n })();\n inFlight = current;\n const result = await current;\n if (inFlight === current) inFlight = undefined;\n if (result.retryDelay !== null) {\n schedule(result.retryDelay);\n return;\n }\n }\n };\n return {\n enqueue: (event: KortyxTelemetryEvent) => {\n if (queue.length >= args.maxQueueSize) {\n queue.shift();\n dropped += 1;\n }\n queue.push(event);\n schedule();\n },\n flush,\n getDroppedEventCount: () => dropped,\n getPermanentDeliveryFailureCount: () => permanentFailures,\n };\n};\n","import { createHash, randomUUID, scryptSync } from \"node:crypto\";\nimport {\n mkdir,\n readdir,\n readFile,\n rename,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { isControlFlowError } from \"@kortyx/core/errors\";\nimport type { KortyxTraceErrorProjection } from \"@kortyx/hooks\";\nimport { captureDiagnosticContent } from \"@kortyx/hooks/internal\";\nimport {\n DIAGNOSTIC_LIMITS,\n DiagnosticContentSchema,\n DiagnosticCorrelationSchema,\n type DiagnosticManifest,\n DiagnosticManifestSchema,\n summarizeDiagnostic,\n} from \"@kortyx/telemetry-contracts\";\nimport type { CreateKortyxTelemetryAdapterOptions } from \"./types\";\n\nexport type DiagnosticDeliveryState =\n | \"pending\"\n | \"available\"\n | \"rejected\"\n | \"dropped\"\n | \"spool_failed\";\nexport type DiagnosticCaptureContext = {\n correlation?: DiagnosticManifest[\"correlation\"] | undefined;\n handled: boolean;\n severity: \"warning\" | \"error\";\n mechanism: DiagnosticManifest[\"mechanism\"];\n project?: KortyxTraceErrorProjection | undefined;\n};\ntype Entry = { manifest: DiagnosticManifest; content: string };\n\n/** Independent diagnostic transport. It never changes application execution. */\nexport function createDiagnosticDelivery(\n options: CreateKortyxTelemetryAdapterOptions,\n) {\n const enabled = options.diagnostics?.enabled === true;\n const queue = new Map<string, Entry>();\n const states = new Map<string, DiagnosticDeliveryState>();\n type CaptureResult = {\n diagnosticId?: string;\n diagnosticCapture: string;\n diagnosticDelivery?: DiagnosticDeliveryState | undefined;\n details: Record<string, unknown> | null;\n };\n const captured = new WeakMap<object, Map<string, CaptureResult>>();\n let queuedBytes = 0;\n let dropped = 0;\n let retryAt = 0;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let inFlight: Promise<void> | undefined;\n const writes = new Set<Promise<void>>();\n const spool = options.diagnostics?.spoolDirectory\n ? join(\n options.diagnostics.spoolDirectory,\n // A stable credential-scoped namespace without storing the API key or\n // a fast credential hash on disk. Only derived when spooling is enabled.\n scryptSync(\n options.apiKey,\n JSON.stringify([options.endpoint, options.environment]),\n 24,\n ).toString(\"hex\"),\n )\n : undefined;\n const state = (id: string, value: DiagnosticDeliveryState) => {\n states.set(id, value);\n if (states.size > 1000) states.delete(states.keys().next().value as string);\n };\n const maxBytes = options.diagnostics?.maxQueueBytes ?? 16 * 1024 * 1024;\n const persist = async (entry: Entry) => {\n if (!spool) return;\n await mkdir(spool, { recursive: true, mode: 0o700 });\n const target = join(spool, `${entry.manifest.diagnosticId}.json`);\n const temporary = `${target}.${randomUUID()}.tmp`;\n await writeFile(temporary, JSON.stringify(entry), { mode: 0o600 });\n await rename(temporary, target);\n };\n const schedule = () => {\n if (!enabled || timer || inFlight || !queue.size) return;\n timer = setTimeout(() => {\n timer = undefined;\n void flush();\n }, options.flushIntervalMs ?? 250);\n timer.unref?.();\n };\n const restored = (async () => {\n if (!enabled || !spool) return;\n try {\n await mkdir(spool, { recursive: true, mode: 0o700 });\n for (const filename of (await readdir(spool)).filter((name) =>\n /^[a-f0-9-]{36}\\.json$/.test(name),\n )) {\n try {\n if (\n (await stat(join(spool, filename))).size >\n DIAGNOSTIC_LIMITS.bytes + 64 * 1024\n )\n throw new Error(\"Spool file exceeds budget\");\n const value = JSON.parse(\n await readFile(join(spool, filename), \"utf8\"),\n ) as Entry;\n const manifest = DiagnosticManifestSchema.parse(value.manifest);\n const bytes = Buffer.byteLength(value.content);\n if (\n bytes !== manifest.byteLength ||\n createHash(\"sha256\").update(value.content).digest(\"hex\") !==\n manifest.checksum\n )\n throw new Error(\"Invalid spool content\");\n DiagnosticContentSchema.parse(JSON.parse(value.content));\n if (queuedBytes + bytes > maxBytes) {\n state(manifest.diagnosticId, \"dropped\");\n dropped++;\n await unlink(join(spool, filename));\n continue;\n }\n if (!queue.has(manifest.diagnosticId)) {\n queue.set(manifest.diagnosticId, {\n manifest,\n content: value.content,\n });\n queuedBytes += bytes;\n state(manifest.diagnosticId, \"pending\");\n }\n } catch {\n dropped++;\n await unlink(join(spool, filename)).catch(() => undefined);\n }\n }\n schedule();\n } catch {\n dropped++;\n }\n })();\n const send = async (path: string, body: unknown) => {\n const response = await (options.fetch ?? globalThis.fetch)(\n `${options.endpoint.replace(/\\/$/, \"\")}/v1/telemetry/diagnostics${path}?env=${encodeURIComponent(options.environment)}`,\n {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${options.apiKey}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(15_000),\n },\n );\n if (!response.ok) {\n const error = new Error(\"Diagnostic delivery failed.\") as Error & {\n status: number;\n };\n error.status = response.status;\n if (response.status === 429) {\n const hint = response.headers.get(\"retry-after\");\n const seconds = Number(hint);\n const delay =\n hint && Number.isFinite(seconds)\n ? seconds * 1000\n : hint\n ? Date.parse(hint) - Date.now()\n : 5000;\n retryAt =\n Date.now() +\n Math.min(\n 60_000,\n Math.max(5000, Number.isFinite(delay) ? delay : 5000),\n );\n }\n throw error;\n }\n return response;\n };\n const flush = async () => {\n await restored;\n await Promise.all([...writes]);\n if (inFlight) {\n await inFlight;\n return;\n }\n if (timer) {\n clearTimeout(timer);\n timer = undefined;\n }\n const work = async () => {\n if (Date.now() < retryAt) return;\n for (const [id, entry] of [...queue]) {\n try {\n await send(\"\", entry.manifest);\n const bytes = Buffer.from(entry.content);\n for (let index = 0; index < entry.manifest.partCount; index++)\n await send(`/${id}/parts`, {\n index,\n data: bytes\n .subarray(\n index * DIAGNOSTIC_LIMITS.partBytes,\n (index + 1) * DIAGNOSTIC_LIMITS.partBytes,\n )\n .toString(\"base64\"),\n });\n const completed = await send(`/${id}/complete`, {});\n const acknowledgement = (await completed.json()) as {\n state?: string;\n };\n if (acknowledgement.state !== \"available\") {\n const error = new Error(\n \"Diagnostic integrity verification failed.\",\n ) as Error & { status: number };\n error.status = 422;\n throw error;\n }\n state(id, \"available\");\n queue.delete(id);\n queuedBytes -= entry.manifest.byteLength;\n if (spool)\n await unlink(join(spool, `${id}.json`)).catch(() => undefined);\n } catch (error) {\n const status = (error as { status?: number }).status;\n if (status && status < 500 && status !== 429) {\n state(id, \"rejected\");\n queue.delete(id);\n queuedBytes -= entry.manifest.byteLength;\n dropped++;\n if (spool)\n await unlink(join(spool, `${id}.json`)).catch(() => undefined);\n }\n // Transient failures retain redacted bytes for a later flush or restart.\n if (status === 429) break;\n }\n }\n };\n inFlight = work();\n try {\n await inFlight;\n } finally {\n inFlight = undefined;\n }\n if (queue.size) {\n timer = setTimeout(\n () => {\n timer = undefined;\n void flush();\n },\n Math.max(5000, retryAt - Date.now()),\n );\n timer.unref?.();\n }\n };\n const capture = (error: unknown, context: DiagnosticCaptureContext) => {\n if (!enabled || isControlFlowError(error)) return undefined;\n const scope = JSON.stringify([\n context.correlation?.runId,\n context.correlation?.invocationId,\n context.correlation?.branchId,\n context.correlation?.attemptId,\n ]);\n const object =\n error && typeof error === \"object\" ? (error as object) : undefined;\n const existing = object ? captured.get(object)?.get(scope) : undefined;\n if (existing)\n return {\n ...existing,\n diagnosticDelivery: existing.diagnosticId\n ? (states.get(existing.diagnosticId) ?? \"pending\")\n : undefined,\n };\n const content = captureDiagnosticContent(\n error,\n context.project ?? options.error,\n );\n if (!content) return { diagnosticCapture: \"suppressed\", details: null };\n const serialized = JSON.stringify(content);\n const diagnosticId = randomUUID();\n const manifest = DiagnosticManifestSchema.parse({\n schemaVersion: 1,\n diagnosticId,\n occurrenceId: randomUUID(),\n occurredAt: new Date().toISOString(),\n environment: options.environment,\n service: options.service,\n correlation: DiagnosticCorrelationSchema.parse(\n Object.fromEntries(\n Object.entries(context.correlation ?? {}).filter(\n ([key]) => key !== \"topologyHash\",\n ),\n ),\n ),\n handled: context.handled,\n severity: context.severity,\n mechanism: context.mechanism,\n summary: {\n type: String(content.data.type ?? \"Error\").slice(0, 256),\n message: summarizeDiagnostic(content.data).message,\n },\n captureStatus: content.capture.status,\n byteLength: Buffer.byteLength(serialized),\n checksum: createHash(\"sha256\").update(serialized).digest(\"hex\"),\n partCount: Math.ceil(\n Buffer.byteLength(serialized) / DIAGNOSTIC_LIMITS.partBytes,\n ),\n });\n if (queuedBytes + manifest.byteLength > maxBytes) {\n state(diagnosticId, \"dropped\");\n dropped++;\n } else {\n const entry = { manifest, content: serialized };\n queue.set(diagnosticId, entry);\n queuedBytes += manifest.byteLength;\n state(diagnosticId, \"pending\");\n const writing = persist(entry)\n .catch(() => {\n state(diagnosticId, \"spool_failed\");\n })\n .finally(() => {\n writes.delete(writing);\n });\n writes.add(writing);\n schedule();\n }\n const result = {\n diagnosticId,\n diagnosticCapture: content.capture.status,\n diagnosticDelivery: states.get(diagnosticId),\n details: summarizeDiagnostic(content.data),\n };\n if (object) {\n const byScope = captured.get(object) ?? new Map<string, CaptureResult>();\n byScope.set(scope, result);\n captured.set(object, byScope);\n }\n return result;\n };\n const flushWithDeadline = async (timeoutMs = 5000) => {\n let deadline: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n await Promise.race([\n flush(),\n new Promise<void>((resolve) => {\n deadline = setTimeout(\n () => {\n timedOut = true;\n resolve();\n },\n Math.max(0, timeoutMs),\n );\n }),\n ]);\n if (deadline) clearTimeout(deadline);\n return {\n timedOut,\n pending: queue.size,\n pendingBytes: queuedBytes,\n dropped,\n states: Object.fromEntries(states),\n };\n };\n return {\n capture,\n flush,\n flushWithDeadline,\n getState: (id: string) => states.get(id),\n getDroppedCount: () => dropped,\n };\n}\n","import {\n errorProperty,\n isControlFlowError,\n serializeFailure,\n} from \"@kortyx/core/errors\";\nimport type {\n KortyxTelemetryConfig,\n KortyxTelemetryEvent,\n KortyxTelemetryEventType,\n ReasonTraceAttributes,\n ReasonTraceSpanStartArgs,\n} from \"@kortyx/hooks\";\nimport {\n exceptionDiagnostics,\n safeTelemetryMetadata,\n} from \"@kortyx/hooks/internal\";\nimport { summarizeDiagnostic } from \"@kortyx/telemetry-contracts\";\nimport type {\n createDiagnosticDelivery,\n DiagnosticCaptureContext,\n} from \"./diagnostics\";\nimport type { ActiveSpan, SpanContext } from \"./types\";\n\nconst stringValue = (value: unknown): string | undefined =>\n typeof value === \"string\" && value.length > 0 ? value : undefined;\n\nconst shouldCapture = (\n value: KortyxTelemetryConfig[\"captureContent\"] | undefined,\n side: \"input\" | \"output\",\n): boolean => {\n if (value === true) return true;\n return Boolean(value && typeof value === \"object\" && value[side]);\n};\n\nconst asErrorPayload = (\n error: unknown,\n project?: import(\"@kortyx/hooks\").KortyxTraceErrorProjection,\n captured?: ReturnType<ReturnType<typeof createDiagnosticDelivery>[\"capture\"]>,\n): Record<string, unknown> => {\n if (isControlFlowError(error))\n return {\n name: errorProperty(error, \"name\"),\n code: errorProperty(error, \"code\"),\n message: \"Execution paused or cancelled.\",\n controlFlow: true,\n };\n const failure = serializeFailure(error);\n const diagnostic = captured\n ? captured.details\n : exceptionDiagnostics(error, project);\n const summary = diagnostic ? summarizeDiagnostic(diagnostic) : null;\n const reference = captured\n ? Object.fromEntries(\n Object.entries(captured).filter(([key]) => key !== \"details\"),\n )\n : {};\n return {\n ...failure,\n name: summary?.type ?? \"Error\",\n message: summary?.message ?? failure.message,\n ...(summary?.stack ? { stack: summary.stack } : {}),\n ...(summary?.cause ? { cause: summary.cause } : {}),\n ...reference,\n };\n};\n\nconst correlationFrom = (\n attributes: ReasonTraceAttributes | undefined,\n active: ActiveSpan | undefined,\n): KortyxTelemetryEvent[\"correlation\"] | undefined => {\n const source = attributes ?? {};\n const runId = stringValue(source.runId) ?? active?.correlation.runId;\n const workflowId =\n stringValue(source.workflowId) ?? active?.correlation.workflowId;\n if (!runId || !workflowId) return undefined;\n\n const sameWorkflow = workflowId === active?.correlation.workflowId;\n const sessionId =\n stringValue(source.sessionId) ?? active?.correlation.sessionId;\n const workflowRevisionId =\n stringValue(source.workflowRevisionId) ??\n (sameWorkflow ? active?.correlation.workflowRevisionId : undefined);\n const topologyHash =\n stringValue(source.topologyHash) ??\n (sameWorkflow ? active?.correlation.topologyHash : undefined);\n const nodeId =\n stringValue(source.nodeId) ??\n (sameWorkflow ? active?.correlation.nodeId : undefined);\n return {\n runId,\n workflowId,\n ...Object.fromEntries(\n [\"invocationId\", \"parentInvocationId\", \"branchId\"].flatMap((key) => {\n const value =\n stringValue(source[key]) ??\n active?.correlation[key as \"invocationId\"];\n return value ? [[key, value]] : [];\n }),\n ),\n ...(sessionId ? { sessionId } : {}),\n ...(workflowRevisionId ? { workflowRevisionId } : {}),\n ...(topologyHash ? { topologyHash } : {}),\n ...(nodeId ? { nodeId } : {}),\n };\n};\n\nexport const createEventMapper = (args: {\n environment: string;\n service: KortyxTelemetryEvent[\"service\"];\n metadata?: Record<string, unknown> | undefined;\n tags?: string[] | undefined;\n createId: () => string;\n error?: import(\"@kortyx/hooks\").KortyxTraceErrorProjection;\n captureDiagnostic?: ReturnType<typeof createDiagnosticDelivery>[\"capture\"];\n}) => {\n const createEvent = (input: {\n type: KortyxTelemetryEventType;\n correlation: KortyxTelemetryEvent[\"correlation\"];\n span?: SpanContext | undefined;\n parentSpanId?: string | undefined;\n payload: Record<string, unknown>;\n context?: KortyxTelemetryEvent[\"context\"] | undefined;\n }): KortyxTelemetryEvent => ({\n schemaVersion: 1,\n eventId: args.createId(),\n occurredAt: new Date().toISOString(),\n environment: args.environment,\n service: args.service,\n correlation: {\n ...input.correlation,\n ...(input.span\n ? { traceId: input.span.traceId, spanId: input.span.spanId }\n : {}),\n ...(input.parentSpanId ? { parentSpanId: input.parentSpanId } : {}),\n },\n ...(input.context || args.metadata || args.tags\n ? {\n context: {\n ...(args.tags ? { tags: args.tags } : {}),\n ...(args.metadata\n ? { metadata: safeTelemetryMetadata(args.metadata) }\n : {}),\n ...(input.context ?? {}),\n },\n }\n : {}),\n type: input.type,\n payload: {\n ...input.payload,\n ...(input.correlation.invocationId\n ? { invocationId: input.correlation.invocationId }\n : {}),\n ...(input.correlation.parentInvocationId\n ? { parentInvocationId: input.correlation.parentInvocationId }\n : {}),\n ...(input.correlation.branchId\n ? { branchId: input.correlation.branchId }\n : {}),\n },\n });\n\n const spanContext = (\n telemetry: ReasonTraceSpanStartArgs[\"telemetry\"] | undefined,\n attributes: ReasonTraceAttributes,\n ): KortyxTelemetryEvent[\"context\"] | undefined => {\n const tags = [...(args.tags ?? []), ...(telemetry?.tags ?? [])];\n const metadata = safeTelemetryMetadata({\n ...(args.metadata ?? {}),\n ...(telemetry?.metadata ?? {}),\n });\n const userId = stringValue(attributes.userId);\n const tenantId = stringValue(attributes.tenantId);\n return userId || tenantId || tags.length || Object.keys(metadata).length\n ? {\n ...(userId ? { userId } : {}),\n ...(tenantId ? { tenantId } : {}),\n ...(tags.length ? { tags } : {}),\n ...(Object.keys(metadata).length ? { metadata } : {}),\n }\n : undefined;\n };\n\n const telemetryPayload = (\n telemetry: ReasonTraceSpanStartArgs[\"telemetry\"] | undefined,\n ): Record<string, unknown> => ({\n ...(telemetry?.operation ? { operation: telemetry.operation } : {}),\n ...(telemetry?.tags?.length ? { tags: telemetry.tags } : {}),\n ...(telemetry?.metadata\n ? { metadata: safeTelemetryMetadata(telemetry.metadata) }\n : {}),\n ...(telemetry?.prompt\n ? {\n prompt: {\n ...(telemetry.prompt.name ? { name: telemetry.prompt.name } : {}),\n ...(telemetry.prompt.version !== undefined\n ? { version: telemetry.prompt.version }\n : {}),\n ...(telemetry.prompt.type ? { type: telemetry.prompt.type } : {}),\n ...(telemetry.prompt.source\n ? { source: telemetry.prompt.source }\n : {}),\n },\n }\n : {}),\n });\n\n return {\n asErrorPayload: (error: unknown, context?: DiagnosticCaptureContext) =>\n asErrorPayload(\n error,\n context?.project ?? args.error,\n context ? args.captureDiagnostic?.(error, context) : undefined,\n ),\n correlationFrom,\n createEvent,\n shouldCapture,\n spanContext,\n stringValue,\n telemetryPayload,\n };\n};\n","import type {\n EnsureWorkflowTopologyRequest,\n EnsureWorkflowTopologyResponse,\n} from \"@kortyx/hooks\";\n\ntype TopologyKey = {\n environment: string;\n workflowId: string;\n topologyHash: string;\n};\n\nconst keyFor = ({ environment, workflowId, topologyHash }: TopologyKey) =>\n `${environment}:${workflowId}:${topologyHash}`;\n\n/** Caches successful topology ensures and coalesces concurrent requests. */\nexport const createTopologyResolver = (args: {\n ensure: (\n snapshot: EnsureWorkflowTopologyRequest,\n ) => Promise<EnsureWorkflowTopologyResponse>;\n}) => {\n const revisions = new Map<string, string>();\n const pending = new Map<string, Promise<EnsureWorkflowTopologyResponse>>();\n\n const ensureWorkflowTopology = (\n snapshot: EnsureWorkflowTopologyRequest,\n ): Promise<EnsureWorkflowTopologyResponse> => {\n const key = keyFor({\n environment: snapshot.environment,\n workflowId: snapshot.workflow.id,\n topologyHash: snapshot.workflow.topologyHash,\n });\n const revision = revisions.get(key);\n if (revision) {\n return Promise.resolve({ workflowRevisionId: revision, created: false });\n }\n\n const existing = pending.get(key);\n if (existing) return existing;\n\n const request = args\n .ensure(snapshot)\n .then((result) => {\n if (!result.workflowRevisionId) {\n throw new Error(\n \"Telemetry API returned an invalid workflow revision.\",\n );\n }\n revisions.set(key, result.workflowRevisionId);\n return result;\n })\n .finally(() => {\n pending.delete(key);\n });\n pending.set(key, request);\n return request;\n };\n\n return {\n ensureWorkflowTopology,\n getWorkflowRevisionId: (args: TopologyKey) => revisions.get(keyFor(args)),\n };\n};\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { isSuspensionControlFlowError } from \"@kortyx/core/errors\";\nimport type {\n KortyxTelemetryConfig,\n KortyxTelemetryEvent,\n ReasonTraceAdapter,\n ReasonTraceSpan,\n ReasonTraceSpanEndArgs,\n ReasonTraceSpanStartArgs,\n} from \"@kortyx/hooks\";\nimport { ToolObservationSchema } from \"@kortyx/telemetry-contracts\";\nimport type { createEventMapper } from \"./event-mapper\";\nimport type { ActiveSpan, SpanContext } from \"./types\";\n\nconst providerPricing = (\n metadata: ReasonTraceSpanEndArgs[\"providerMetadata\"],\n): Record<string, unknown> | undefined => {\n if (metadata?.providerId !== \"openrouter\") return undefined;\n const details = metadata.costDetails;\n const upstreamCost =\n details && typeof details === \"object\" && !Array.isArray(details)\n ? (details as Record<string, unknown>).upstreamInferenceCost\n : undefined;\n const cost = metadata.isByok === true ? upstreamCost : metadata.cost;\n if (typeof cost !== \"number\" || !Number.isFinite(cost) || cost < 0)\n return undefined;\n return {\n source: \"provider\",\n currency: \"USD\",\n actualCostMicros: Math.round(cost * 1_000_000),\n };\n};\n\n/** Maps generic SDK trace calls to Kortyx Studio's span and generation facts. */\nexport const createTraceAdapter = (args: {\n captureContent?: KortyxTelemetryConfig[\"captureContent\"] | undefined;\n createId: () => string;\n enqueue: (event: KortyxTelemetryEvent) => void;\n eventMapper: ReturnType<typeof createEventMapper>;\n}): ReasonTraceAdapter => {\n const activeSpans = new AsyncLocalStorage<ActiveSpan>();\n\n const createSpan = (\n startArgs: ReasonTraceSpanStartArgs,\n ): { span: ReasonTraceSpan; active?: ActiveSpan | undefined } => {\n const parent = activeSpans.getStore();\n const span: SpanContext = {\n traceId: parent?.traceId ?? args.createId(),\n spanId: args.createId(),\n };\n const attributes = { ...(startArgs.attributes ?? {}) };\n const currentAttributes = { ...attributes };\n const correlation = args.eventMapper.correlationFrom(attributes, parent);\n const startedAt = Date.now();\n\n const isTool = startArgs.name === \"kortyx.tool\";\n if (correlation && (!isTool || attributes.executed === true)) {\n args.enqueue(\n args.eventMapper.createEvent({\n type: isTool ? \"tool.started\" : \"span.started\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: isTool\n ? ToolObservationSchema.parse(attributes)\n : {\n name: startArgs.name,\n attributes: currentAttributes,\n telemetry: args.eventMapper.telemetryPayload(\n startArgs.telemetry,\n ),\n ...(args.eventMapper.shouldCapture(\n startArgs.telemetry?.captureContent ?? args.captureContent,\n \"input\",\n )\n ? { input: startArgs.telemetry?.input }\n : {}),\n },\n context: args.eventMapper.spanContext(\n startArgs.telemetry,\n currentAttributes,\n ),\n }),\n );\n }\n\n let ended = false;\n let failed = false;\n let suspended = false;\n const end = (endArgs?: ReasonTraceSpanEndArgs): void => {\n if (ended) return;\n ended = true;\n if (!correlation) return;\n\n const endAttributes = {\n ...currentAttributes,\n ...(endArgs?.attributes ?? {}),\n };\n const telemetry = endArgs?.telemetry ?? startArgs.telemetry;\n const durationMs = Date.now() - startedAt;\n if (isTool) {\n const payload = ToolObservationSchema.parse(endAttributes);\n const type =\n payload.observationKind === \"reused\"\n ? \"tool.reused\"\n : payload.observationKind === \"waiting\"\n ? \"tool.waiting\"\n : payload.suspended\n ? \"tool.suspended\"\n : payload.outcome === \"denied\"\n ? \"tool.denied\"\n : payload.outcome === \"fault\"\n ? \"tool.failed\"\n : payload.outcome === \"cancelled\"\n ? \"tool.cancelled\"\n : \"tool.completed\";\n args.enqueue(\n args.eventMapper.createEvent({\n type,\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload,\n }),\n );\n return;\n }\n\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"span.ended\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n name: startArgs.name,\n attributes: endAttributes,\n durationMs,\n telemetry: args.eventMapper.telemetryPayload(telemetry),\n ...(args.eventMapper.shouldCapture(\n endArgs?.telemetry?.captureContent ??\n startArgs.telemetry?.captureContent ??\n args.captureContent,\n \"output\",\n )\n ? { output: endArgs?.telemetry?.output }\n : {}),\n },\n context: args.eventMapper.spanContext(telemetry, endAttributes),\n }),\n );\n\n if (startArgs.name !== \"runReasonEngine\" || suspended) return;\n const ttftMs = nonnegativeNumber(endAttributes.ttftMs);\n const streamDurationMs = nonnegativeNumber(\n endAttributes.streamDurationMs,\n );\n const timeToLastTokenMs = nonnegativeNumber(\n endAttributes.timeToLastTokenMs,\n );\n const pricing = providerPricing(endArgs?.providerMetadata);\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"generation.completed\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n outcome: failed ? \"failed\" : \"completed\",\n provider:\n args.eventMapper.stringValue(attributes.providerId) ?? \"unknown\",\n model:\n args.eventMapper.stringValue(attributes.modelId) ?? \"unknown\",\n durationMs,\n ...(ttftMs !== undefined ? { ttftMs } : {}),\n ...(streamDurationMs !== undefined ? { streamDurationMs } : {}),\n ...(timeToLastTokenMs !== undefined\n ? {\n postStreamDurationMs: Math.max(\n 0,\n durationMs - timeToLastTokenMs,\n ),\n }\n : {}),\n ...(endArgs?.usage\n ? {\n usage: failed\n ? Object.fromEntries(\n Object.entries(endArgs.usage).filter(\n ([key, value]) =>\n ([\n \"input\",\n \"output\",\n \"total\",\n \"reasoning\",\n \"cacheRead\",\n \"cacheWrite\",\n \"cacheWrite1h\",\n ].includes(key) &&\n typeof value === \"number\" &&\n Number.isFinite(value)) ||\n ([\n \"outputIncludesReasoning\",\n \"inputIncludesCacheRead\",\n \"inputIncludesCacheWrite\",\n ].includes(key) &&\n typeof value === \"boolean\"),\n ),\n )\n : endArgs.usage,\n }\n : {}),\n ...(endArgs?.finishReason\n ? { finishReason: endArgs.finishReason }\n : {}),\n ...(endArgs?.warnings ? { warnings: endArgs.warnings } : {}),\n ...(pricing ? { pricing } : {}),\n ...(endArgs?.providerMetadata && !failed\n ? { providerMetadata: endArgs.providerMetadata }\n : {}),\n },\n context: args.eventMapper.spanContext(telemetry, currentAttributes),\n }),\n );\n };\n\n const traceSpan: ReasonTraceSpan = {\n setAttributes: (nextAttributes) => {\n Object.assign(currentAttributes, nextAttributes);\n },\n addEvent: (name, eventAttributes = {}) => {\n if (\n !correlation ||\n activeSpans.getStore()?.name === \"kortyx.tool\" ||\n startArgs.name === \"kortyx.tool\"\n )\n return;\n const type =\n name === \"useReason.tool-call.start\"\n ? \"tool.started\"\n : name === \"useReason.tool-call.complete\"\n ? \"tool.completed\"\n : name === \"useReason.tool-call.error\"\n ? \"tool.failed\"\n : name === \"useReason.output.emitted\"\n ? \"output.emitted\"\n : name === \"useReason.output.invalidated\"\n ? \"output.invalidated\"\n : undefined;\n if (!type) return;\n const payload =\n type === \"output.emitted\"\n ? {\n ...Object.fromEntries(\n Object.entries(eventAttributes).filter(\n ([key]) => key !== \"data\",\n ),\n ),\n ...(args.eventMapper.shouldCapture(\n startArgs.telemetry?.captureContent ?? args.captureContent,\n \"output\",\n ) && \"data\" in eventAttributes\n ? { data: eventAttributes.data }\n : {}),\n }\n : eventAttributes;\n args.enqueue(\n args.eventMapper.createEvent({\n type,\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload,\n }),\n );\n },\n end,\n fail: (error, endArgs) => {\n if (ended) return;\n if (isSuspensionControlFlowError(error)) {\n suspended = true;\n Object.assign(currentAttributes, {\n \"kortyx.control_flow\": true,\n \"kortyx.suspended\": true,\n });\n end(endArgs);\n return;\n }\n failed = true;\n const errorPayload = args.eventMapper.asErrorPayload(error, {\n correlation: { ...correlation, ...span },\n handled: false,\n severity: \"error\",\n mechanism: \"span\",\n });\n if (correlation) {\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"span.failed\",\n correlation,\n span,\n ...(parent ? { parentSpanId: parent.spanId } : {}),\n payload: {\n name: startArgs.name,\n error: errorPayload,\n handled: false,\n severity: \"error\",\n durationMs: Date.now() - startedAt,\n },\n }),\n );\n }\n end(endArgs);\n },\n };\n\n return {\n span: traceSpan,\n ...(correlation\n ? { active: { ...span, name: startArgs.name, correlation } }\n : {}),\n };\n };\n\n return {\n startSpan: (startArgs) => createSpan(startArgs).span,\n withSpan: async (startArgs, fn) => {\n const created = createSpan(startArgs);\n const run = async (): Promise<Awaited<ReturnType<typeof fn>>> => {\n try {\n const result = await fn(created.span);\n created.span.end?.();\n return result;\n } catch (error) {\n try {\n created.span.fail?.(error);\n } catch {\n /* Preserve the callback failure. */\n }\n throw error;\n }\n };\n return created.active ? activeSpans.run(created.active, run) : run();\n },\n getActiveContext: () => {\n const active = activeSpans.getStore();\n return active\n ? { traceId: active.traceId, spanId: active.spanId }\n : undefined;\n },\n reportError: (error, options = {}) => {\n try {\n const active = activeSpans.getStore();\n const payload = args.eventMapper.asErrorPayload(error, {\n correlation: {\n ...active?.correlation,\n ...(active\n ? { traceId: active.traceId, spanId: active.spanId }\n : {}),\n ...options.correlation,\n },\n handled: true,\n severity: options.severity === \"warning\" ? \"warning\" : \"error\",\n mechanism: options.mechanism ?? \"report\",\n project: options.error,\n });\n if (!active)\n return typeof payload.diagnosticId === \"string\"\n ? payload.diagnosticId\n : undefined;\n args.enqueue(\n args.eventMapper.createEvent({\n type: \"error.reported\",\n correlation: active.correlation,\n span: active,\n payload: {\n handled: true,\n severity: options.severity === \"warning\" ? \"warning\" : \"error\",\n error: payload,\n },\n context: args.eventMapper.spanContext(\n {\n ...(options.metadata ? { metadata: options.metadata } : {}),\n ...(options.tags ? { tags: options.tags } : {}),\n },\n {},\n ),\n }),\n );\n return typeof payload.diagnosticId === \"string\"\n ? payload.diagnosticId\n : undefined;\n } catch {\n // Error reporting is an observer and cannot change execution.\n return undefined;\n }\n },\n };\n};\n\nconst nonnegativeNumber = (value: unknown): number | undefined =>\n typeof value === \"number\" && Number.isFinite(value) && value >= 0\n ? value\n : undefined;\n"],"mappings":"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","names":["import_node_crypto","result","import_errors","import_internal","import_telemetry_contracts","args","import_errors","import_telemetry_contracts"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kortyx/telemetry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Kortyx Studio telemetry HTTP adapter.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"CHANGELOG.md"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@kortyx/hooks": "0.
|
|
22
|
-
"@kortyx/telemetry-contracts": "0.
|
|
23
|
-
"@kortyx/core": "0.
|
|
21
|
+
"@kortyx/hooks": "0.31.0",
|
|
22
|
+
"@kortyx/telemetry-contracts": "0.15.0",
|
|
23
|
+
"@kortyx/core": "0.12.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"tsup": "^8.5.1",
|
|
27
|
-
"turbo": "2.
|
|
27
|
+
"turbo": "2.9.14",
|
|
28
28
|
"typescript": "5.9.3",
|
|
29
|
-
"vitest": "^4.1.
|
|
29
|
+
"vitest": "^4.1.11"
|
|
30
30
|
},
|
|
31
31
|
"sideEffects": false,
|
|
32
32
|
"repository": {
|