@lucern/sdk 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/accessControl.d.ts +1 -0
  3. package/dist/accessControl.js +213 -26
  4. package/dist/accessControl.js.map +1 -1
  5. package/dist/adminClient.d.ts +1 -0
  6. package/dist/adminClient.js +213 -26
  7. package/dist/adminClient.js.map +1 -1
  8. package/dist/answersClient.d.ts +1 -0
  9. package/dist/answersClient.js +213 -26
  10. package/dist/answersClient.js.map +1 -1
  11. package/dist/audiencesClient.d.ts +1 -0
  12. package/dist/audiencesClient.js +213 -26
  13. package/dist/audiencesClient.js.map +1 -1
  14. package/dist/auditClient.d.ts +1 -0
  15. package/dist/auditClient.js +213 -26
  16. package/dist/auditClient.js.map +1 -1
  17. package/dist/authDeviceClient.d.ts +1 -0
  18. package/dist/beliefs/index.d.ts +1 -0
  19. package/dist/beliefs/index.js +214 -27
  20. package/dist/beliefs/index.js.map +1 -1
  21. package/dist/beliefsClient.d.ts +1 -0
  22. package/dist/beliefsClient.js +213 -26
  23. package/dist/beliefsClient.js.map +1 -1
  24. package/dist/client.d.ts +1 -0
  25. package/dist/client.js +214 -27
  26. package/dist/client.js.map +1 -1
  27. package/dist/clientConfig.d.ts +1 -0
  28. package/dist/clientEvidenceCompat.d.ts +1 -0
  29. package/dist/clientKnowledgeNamespaces.d.ts +1 -0
  30. package/dist/clientLocalHelpers.d.ts +1 -0
  31. package/dist/clientLocalHelpers.js +2 -0
  32. package/dist/clientLocalHelpers.js.map +1 -1
  33. package/dist/clientPlatformNamespaces.d.ts +1 -0
  34. package/dist/clientRuntime.d.ts +1 -0
  35. package/dist/clientWorkflowNamespaces.d.ts +1 -0
  36. package/dist/contextClient.d.ts +1 -0
  37. package/dist/contextClient.js +213 -26
  38. package/dist/contextClient.js.map +1 -1
  39. package/dist/contradictions/index.d.ts +1 -0
  40. package/dist/contradictions/index.js +214 -27
  41. package/dist/contradictions/index.js.map +1 -1
  42. package/dist/control-plane.d.ts +1 -0
  43. package/dist/control-plane.js +213 -26
  44. package/dist/control-plane.js.map +1 -1
  45. package/dist/coreClient.d.ts +25 -1
  46. package/dist/coreClient.js +217 -27
  47. package/dist/coreClient.js.map +1 -1
  48. package/dist/decisions/index.d.ts +1 -0
  49. package/dist/decisions/index.js +214 -27
  50. package/dist/decisions/index.js.map +1 -1
  51. package/dist/decisionsClient.d.ts +1 -0
  52. package/dist/decisionsClient.js +213 -26
  53. package/dist/decisionsClient.js.map +1 -1
  54. package/dist/edges/index.d.ts +1 -0
  55. package/dist/edges/index.js +214 -27
  56. package/dist/edges/index.js.map +1 -1
  57. package/dist/embeddingsClient.d.ts +1 -0
  58. package/dist/embeddingsClient.js +213 -26
  59. package/dist/embeddingsClient.js.map +1 -1
  60. package/dist/eventingClient.d.ts +1 -0
  61. package/dist/eventingClient.js +213 -26
  62. package/dist/eventingClient.js.map +1 -1
  63. package/dist/eventsCore.d.ts +1 -0
  64. package/dist/eventsCore.js +213 -26
  65. package/dist/eventsCore.js.map +1 -1
  66. package/dist/evidence/index.d.ts +1 -0
  67. package/dist/evidence/index.js +214 -27
  68. package/dist/evidence/index.js.map +1 -1
  69. package/dist/evidenceClient.d.ts +1 -0
  70. package/dist/evidenceClient.js +213 -26
  71. package/dist/evidenceClient.js.map +1 -1
  72. package/dist/functionSurface.d.ts +1 -0
  73. package/dist/functionSurface.js +213 -26
  74. package/dist/functionSurface.js.map +1 -1
  75. package/dist/functionSurfaceClient.d.ts +1 -0
  76. package/dist/functionSurfaceClient.js +213 -26
  77. package/dist/functionSurfaceClient.js.map +1 -1
  78. package/dist/gatewayFacades.d.ts +1 -0
  79. package/dist/gatewayFacades.factories.d.ts +1 -0
  80. package/dist/gatewayFacades.factories.js +213 -26
  81. package/dist/gatewayFacades.factories.js.map +1 -1
  82. package/dist/gatewayFacades.js +213 -26
  83. package/dist/gatewayFacades.js.map +1 -1
  84. package/dist/graphAnalysisClient.d.ts +1 -0
  85. package/dist/graphAnalysisClient.js +213 -26
  86. package/dist/graphAnalysisClient.js.map +1 -1
  87. package/dist/graphClient.d.ts +1 -0
  88. package/dist/graphClient.js +213 -26
  89. package/dist/graphClient.js.map +1 -1
  90. package/dist/graphRecommendationsClient.d.ts +1 -0
  91. package/dist/graphRecommendationsClient.js +213 -26
  92. package/dist/graphRecommendationsClient.js.map +1 -1
  93. package/dist/graphStateClassifierClient.d.ts +1 -0
  94. package/dist/graphStateClassifierClient.js +213 -26
  95. package/dist/graphStateClassifierClient.js.map +1 -1
  96. package/dist/harnessClient.d.ts +1 -0
  97. package/dist/harnessClient.js +213 -26
  98. package/dist/harnessClient.js.map +1 -1
  99. package/dist/identityClient.d.ts +1 -0
  100. package/dist/identityClient.js +213 -26
  101. package/dist/identityClient.js.map +1 -1
  102. package/dist/index.d.ts +2 -1
  103. package/dist/index.js +237 -28
  104. package/dist/index.js.map +1 -1
  105. package/dist/jobsClient.d.ts +1 -0
  106. package/dist/jobsClient.js +213 -26
  107. package/dist/jobsClient.js.map +1 -1
  108. package/dist/learningClient.d.ts +1 -0
  109. package/dist/learningClient.js +213 -26
  110. package/dist/learningClient.js.map +1 -1
  111. package/dist/lenses/index.d.ts +1 -0
  112. package/dist/lenses/index.js +214 -27
  113. package/dist/lenses/index.js.map +1 -1
  114. package/dist/mcpClient.d.ts +1 -0
  115. package/dist/mcpClient.js +213 -26
  116. package/dist/mcpClient.js.map +1 -1
  117. package/dist/modelRuntimeClient.d.ts +1 -0
  118. package/dist/modelRuntimeClient.js +213 -26
  119. package/dist/modelRuntimeClient.js.map +1 -1
  120. package/dist/nodes/index.d.ts +1 -0
  121. package/dist/nodes/index.js +214 -27
  122. package/dist/nodes/index.js.map +1 -1
  123. package/dist/ontologies/index.d.ts +1 -0
  124. package/dist/ontologies/index.js +214 -27
  125. package/dist/ontologies/index.js.map +1 -1
  126. package/dist/ontologyClient.d.ts +1 -0
  127. package/dist/ontologyClient.js +213 -26
  128. package/dist/ontologyClient.js.map +1 -1
  129. package/dist/ontologyLinksClient.d.ts +1 -0
  130. package/dist/ontologyLinksClient.js +213 -26
  131. package/dist/ontologyLinksClient.js.map +1 -1
  132. package/dist/orgGraphSearchClient.d.ts +1 -0
  133. package/dist/orgGraphSearchClient.js +213 -26
  134. package/dist/orgGraphSearchClient.js.map +1 -1
  135. package/dist/packsClient.d.ts +1 -0
  136. package/dist/packsClient.js +213 -26
  137. package/dist/packsClient.js.map +1 -1
  138. package/dist/policyClient.d.ts +1 -0
  139. package/dist/policyClient.js +213 -26
  140. package/dist/policyClient.js.map +1 -1
  141. package/dist/proof-attestation.json +45 -0
  142. package/dist/questions/index.d.ts +1 -0
  143. package/dist/questions/index.js +214 -27
  144. package/dist/questions/index.js.map +1 -1
  145. package/dist/reportsClient.d.ts +1 -0
  146. package/dist/reportsClient.js +213 -26
  147. package/dist/reportsClient.js.map +1 -1
  148. package/dist/schemaClient.d.ts +1 -0
  149. package/dist/schemaClient.js +213 -26
  150. package/dist/schemaClient.js.map +1 -1
  151. package/dist/sdkSurface.d.ts +1 -0
  152. package/dist/sourcesClient.d.ts +1 -0
  153. package/dist/sourcesClient.js +213 -26
  154. package/dist/sourcesClient.js.map +1 -1
  155. package/dist/telemetryClient.d.ts +1 -0
  156. package/dist/telemetryClient.js +213 -26
  157. package/dist/telemetryClient.js.map +1 -1
  158. package/dist/toolRegistryClient.d.ts +1 -0
  159. package/dist/toolRegistryClient.js +213 -26
  160. package/dist/toolRegistryClient.js.map +1 -1
  161. package/dist/topics/index.d.ts +1 -0
  162. package/dist/topics/index.js +214 -27
  163. package/dist/topics/index.js.map +1 -1
  164. package/dist/topicsClient.d.ts +1 -0
  165. package/dist/topicsClient.js +213 -26
  166. package/dist/topicsClient.js.map +1 -1
  167. package/dist/version.d.ts +1 -1
  168. package/dist/version.js +1 -1
  169. package/dist/version.js.map +1 -1
  170. package/dist/workflowClient.d.ts +1 -0
  171. package/dist/workflowClient.js +213 -26
  172. package/dist/workflowClient.js.map +1 -1
  173. package/dist/worktrees/index.d.ts +1 -0
  174. package/dist/worktrees/index.js +214 -27
  175. package/dist/worktrees/index.js.map +1 -1
  176. package/package.json +6 -5
@@ -1,5 +1,6 @@
1
1
  import { GatewayClientConfig, PlatformGatewaySuccess } from './coreClient.js';
2
2
  import { TopicIdentifierInput, JsonObject, TopicListResponse, TopicRecord, TopicTreeResponse, TopicCoverageResponse } from './types.js';
3
+ import '@lucern/transport-core';
3
4
  import './authContext.js';
4
5
  import './contracts/auth-session.contract.js';
5
6
  import './contracts/workflow-runtime.contract.js';
@@ -1,5 +1,7 @@
1
+ import { createTelemetryExporterFromEnv, emitTelemetrySignal } from '@lucern/transport-core';
1
2
  import { redactDiagnosticValue } from '@lucern/transport-core/redaction';
2
3
  import { classifyRetry } from '@lucern/transport-core/transport';
4
+ import { Effect, Exit, Cause } from 'effect';
3
5
 
4
6
  // src/coreClient.ts
5
7
 
@@ -171,6 +173,33 @@ function createCanonicalAuthHeaders(authContext) {
171
173
  }
172
174
 
173
175
  // src/coreClient.ts
176
+ var DEFAULT_GATEWAY_TIMEOUT_MS = 15e3;
177
+ var DEFAULT_GATEWAY_MAX_RETRIES = 2;
178
+ var DEFAULT_ENV_TIMEOUT_MS = "LUCERN_REQUEST_TIMEOUT_MS";
179
+ var DEFAULT_ENV_MAX_RETRIES = "LUCERN_GATEWAY_MAX_RETRIES";
180
+ var ENV_TIMEOUT_BY_METHOD_PREFIX = "LUCERN_REQUEST_TIMEOUT_MS_";
181
+ var GatewayTimeoutError = class extends Error {
182
+ retryable = true;
183
+ timeoutMs;
184
+ constructor(timeoutMs) {
185
+ super(`Request timed out after ${timeoutMs}ms`);
186
+ this.name = "AbortError";
187
+ this.timeoutMs = timeoutMs;
188
+ }
189
+ };
190
+ var GatewayTransportError = class extends Error {
191
+ retryable;
192
+ cause;
193
+ constructor(message, options) {
194
+ super(message);
195
+ this.name = "GatewayTransportError";
196
+ this.retryable = options?.retryable ?? true;
197
+ this.cause = options?.cause;
198
+ }
199
+ };
200
+ function isGatewayRetryableError(error) {
201
+ return error instanceof GatewayTimeoutError && error.retryable || error instanceof GatewayTransportError && error.retryable || false;
202
+ }
174
203
  var LucernApiError = class extends Error {
175
204
  code;
176
205
  status;
@@ -237,6 +266,99 @@ function generatePortableRequestId() {
237
266
  8
238
267
  ).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
239
268
  }
269
+ function resolveEnvironment() {
270
+ const processEnv = typeof globalThis === "object" && globalThis !== null && "process" in globalThis ? globalThis.process : void 0;
271
+ const env = processEnv !== void 0 && typeof processEnv === "object" && processEnv !== null && typeof processEnv.env === "object" ? processEnv.env : void 0;
272
+ return {
273
+ get: (name) => {
274
+ const value = env?.[name];
275
+ return typeof value === "string" && value.length > 0 ? value : void 0;
276
+ }
277
+ };
278
+ }
279
+ function telemetryEnvironmentRecord(environment) {
280
+ const names = [
281
+ "LUCERN_TELEMETRY_ENABLED",
282
+ "AXIOM_TELEMETRY_ENABLED",
283
+ "LUCERN_AXIOM_TOKEN",
284
+ "AXIOM_TOKEN",
285
+ "LUCERN_AXIOM_EVENTS_DATASET",
286
+ "LUCERN_AXIOM_DATASET",
287
+ "AXIOM_EVENTS_DATASET",
288
+ "AXIOM_DATASET",
289
+ "LUCERN_AXIOM_API_URL",
290
+ "AXIOM_URL",
291
+ "LUCERN_ENVIRONMENT",
292
+ "NODE_ENV",
293
+ "LUCERN_RELEASE",
294
+ "SENTRY_RELEASE",
295
+ "VERCEL_GIT_COMMIT_SHA"
296
+ ];
297
+ return Object.fromEntries(
298
+ names.map((name) => [name, environment.get(name)])
299
+ );
300
+ }
301
+ function resolveRequestProfile(config, environment) {
302
+ const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
303
+ const parsedMaxRetries = parseIntegerFromString(
304
+ config.maxRetries,
305
+ environment.get(DEFAULT_ENV_MAX_RETRIES)
306
+ );
307
+ const parsedTimeoutMs = parseIntegerFromString(
308
+ config.timeoutMs,
309
+ environment.get(DEFAULT_ENV_TIMEOUT_MS)
310
+ );
311
+ const methodTimeouts = {
312
+ ...config.timeoutMsByMethod
313
+ };
314
+ for (const method of ["GET", "POST", "PUT", "PATCH", "DELETE"]) {
315
+ const envKey = `${ENV_TIMEOUT_BY_METHOD_PREFIX}${method}`;
316
+ const raw = environment.get(envKey);
317
+ if (!raw || methodTimeouts[method] !== void 0) {
318
+ continue;
319
+ }
320
+ const parsed = parseIntegerFromString(void 0, raw);
321
+ if (typeof parsed === "number") {
322
+ methodTimeouts[method] = parsed;
323
+ }
324
+ }
325
+ return {
326
+ maxRetries: parsedMaxRetries ?? DEFAULT_GATEWAY_MAX_RETRIES,
327
+ timeoutMs: parsedTimeoutMs ?? DEFAULT_GATEWAY_TIMEOUT_MS,
328
+ timeoutMsByMethod: methodTimeouts,
329
+ requestIdFactory
330
+ };
331
+ }
332
+ function createGatewayRuntime(config, environment) {
333
+ return {
334
+ fetch: config.fetchImpl ?? fetch,
335
+ now: () => Date.now(),
336
+ sleep: (ms) => delay(ms),
337
+ env: environment,
338
+ redaction: resolveRequestRedactionValue,
339
+ profile: resolveRequestProfile(config, environment)
340
+ };
341
+ }
342
+ function parseIntegerFromString(value, rawValue) {
343
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0) {
344
+ return value;
345
+ }
346
+ if (typeof rawValue !== "string" || !rawValue.trim()) {
347
+ return void 0;
348
+ }
349
+ const parsed = Number.parseInt(rawValue, 10);
350
+ return Number.isInteger(parsed) && parsed >= 0 ? parsed : void 0;
351
+ }
352
+ function resolveRequestRedactionValue(value) {
353
+ return redactDiagnosticValue(value);
354
+ }
355
+ function resolveGatewayBaseUrl(configBaseUrl, environment) {
356
+ const envBaseUrl = environment.get("LUCERN_API_URL") ?? environment.get("LUCERN_BASE_URL") ?? environment.get("LUCERN_GATEWAY_BASE_URL");
357
+ return (configBaseUrl ?? envBaseUrl ?? "").replace(/\/+$/, "");
358
+ }
359
+ function normalizeGatewayEnvironment(value) {
360
+ return value === "sandbox" || value === "production" ? value : void 0;
361
+ }
240
362
  var randomIdempotencyKey = generatePortableRequestId;
241
363
  function fallbackErrorCode(status) {
242
364
  if (status === 401) {
@@ -276,10 +398,8 @@ function computeRetryDelayMs(args) {
276
398
  const jitterWindow = Math.max(250, Math.round(baseDelay * 0.25));
277
399
  return baseDelay + Math.round(Math.random() * jitterWindow);
278
400
  }
279
- function timeoutError(timeoutMs) {
280
- const error = new Error(`Request timed out after ${timeoutMs}ms`);
281
- error.name = "AbortError";
282
- return error;
401
+ function classifyGatewayErrorForRetry(error) {
402
+ return isGatewayRetryableError(error) || classifyRetry({ error }).retryable;
283
403
  }
284
404
  function isRecord(value) {
285
405
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -334,10 +454,18 @@ function cleanHeaderValue(value) {
334
454
  return normalized ? normalized : void 0;
335
455
  }
336
456
  function createGatewayRequestClient(config = {}) {
337
- const fetchImpl = config.fetchImpl ?? fetch;
338
- const baseUrl = config.baseUrl?.replace(/\/+$/, "") ?? "";
339
- const maxRetries = config.maxRetries ?? 2;
340
- const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
457
+ const env = resolveEnvironment();
458
+ const runtime = createGatewayRuntime(config, env);
459
+ const baseUrl = resolveGatewayBaseUrl(config.baseUrl, env);
460
+ const maxRetries = runtime.profile.maxRetries;
461
+ const requestIdFactory = runtime.profile.requestIdFactory;
462
+ const requestTimeoutByMethod = runtime.profile.timeoutMsByMethod;
463
+ const defaultRequestTimeoutMs = runtime.profile.timeoutMs;
464
+ const normalizedEnvironment = normalizeGatewayEnvironment(config.environment);
465
+ const telemetryExporter = config.telemetryEnabled === false ? null : config.telemetryExporter ?? createTelemetryExporterFromEnv(telemetryEnvironmentRecord(env), {
466
+ service: "lucern-sdk",
467
+ environment: normalizedEnvironment
468
+ });
341
469
  async function resolveAuthHeaders() {
342
470
  const provided = config.getAuthHeaders ? await config.getAuthHeaders() : {};
343
471
  const headers = new Headers(provided);
@@ -349,7 +477,7 @@ function createGatewayRequestClient(config = {}) {
349
477
  };
350
478
  setIfAbsent("x-lucern-key", config.apiKey);
351
479
  setIfAbsent("x-lucern-session-token", config.userToken);
352
- setIfAbsent("x-lucern-environment", config.environment);
480
+ setIfAbsent("x-lucern-environment", normalizedEnvironment);
353
481
  setIfAbsent("x-lucern-clerk-id", config.clerkId);
354
482
  setIfAbsent("x-lucern-user-id", config.userId ?? config.clerkId);
355
483
  setIfAbsent("x-lucern-deployment-host", config.deploymentHost);
@@ -364,19 +492,73 @@ function createGatewayRequestClient(config = {}) {
364
492
  return mergeHeaderRecord(base, createCanonicalAuthHeaders(authContext));
365
493
  }
366
494
  async function fetchWithTimeout(url, init, timeoutMs) {
495
+ const normalizeTransportError = (error, isTimeout) => {
496
+ if (isTimeout) {
497
+ return new GatewayTimeoutError(timeoutMs);
498
+ }
499
+ return error instanceof GatewayTimeoutError || error instanceof GatewayTransportError ? error : new GatewayTransportError(
500
+ error instanceof Error ? error.message : "Gateway transport error",
501
+ {
502
+ cause: error,
503
+ retryable: classifyGatewayErrorForRetry(error)
504
+ }
505
+ );
506
+ };
367
507
  const controller = new AbortController();
368
508
  const timer = setTimeout(() => controller.abort(), timeoutMs);
509
+ const requestEffect = Effect.tryPromise({
510
+ try: () => runtime.fetch(url, { ...init, signal: controller.signal }),
511
+ catch: (error) => normalizeTransportError(error, controller.signal.aborted)
512
+ });
369
513
  try {
370
- return await fetchImpl(url, { ...init, signal: controller.signal });
371
- } catch (error) {
372
- if (controller.signal.aborted) {
373
- throw timeoutError(timeoutMs);
514
+ const exit = await Effect.runPromiseExit(requestEffect);
515
+ if (Exit.isSuccess(exit)) {
516
+ return exit.value;
374
517
  }
375
- throw error;
518
+ const failure = Array.from(Cause.failures(exit.cause))[0];
519
+ if (failure !== void 0) {
520
+ throw failure;
521
+ }
522
+ throw Cause.squash(exit.cause);
376
523
  } finally {
377
524
  clearTimeout(timer);
378
525
  }
379
526
  }
527
+ async function emitSdkResponseTelemetry(context) {
528
+ const retry = classifyRetry({
529
+ status: context.status,
530
+ error: context.error,
531
+ retryAfter: context.retryAfterMs !== null && context.retryAfterMs !== void 0 ? String(context.retryAfterMs / 1e3) : void 0
532
+ });
533
+ await emitTelemetrySignal(telemetryExporter, {
534
+ signalType: "trace",
535
+ surface: "sdk-retry",
536
+ eventName: context.willRetry ? "sdk.retry" : context.error ? "sdk.request.error" : "sdk.request.complete",
537
+ severity: context.error ? context.willRetry ? "warn" : "error" : "info",
538
+ durationMs: context.durationMs,
539
+ metricName: "sdk.request.duration_ms",
540
+ metricValue: context.durationMs,
541
+ correlationId: context.correlationId ?? context.requestId,
542
+ policyTraceId: context.policyTraceId ?? null,
543
+ tenantId: context.headers.get("x-lucern-tenant-id") ?? context.headers.get("x-lucern-tenant") ?? void 0,
544
+ workspaceId: context.headers.get("x-lucern-workspace-id") ?? context.headers.get("x-lucern-workspace") ?? void 0,
545
+ attributes: {
546
+ service: "lucern-sdk",
547
+ operation: "gateway.request",
548
+ path: context.path,
549
+ httpMethod: context.method,
550
+ httpStatus: context.status,
551
+ attempt: context.attempt,
552
+ maxRetries: context.maxRetries,
553
+ retryReason: retry.reason,
554
+ retryAfterMs: context.retryAfterMs ?? retry.retryAfterMs,
555
+ willRetry: context.willRetry,
556
+ retryable: retry.retryable,
557
+ errorName: context.error instanceof Error ? context.error.name : void 0,
558
+ errorMessage: context.error instanceof Error ? context.error.message : void 0
559
+ }
560
+ });
561
+ }
380
562
  async function parsePayload(response) {
381
563
  const text = await response.text();
382
564
  if (!text) {
@@ -392,11 +574,11 @@ function createGatewayRequestClient(config = {}) {
392
574
  if (typeof requestTimeoutMs === "number") {
393
575
  return requestTimeoutMs;
394
576
  }
395
- const methodTimeoutMs = config.timeoutMsByMethod?.[method];
577
+ const methodTimeoutMs = requestTimeoutByMethod?.[method];
396
578
  if (typeof methodTimeoutMs === "number") {
397
579
  return methodTimeoutMs;
398
580
  }
399
- return config.timeoutMs ?? 15e3;
581
+ return defaultRequestTimeoutMs;
400
582
  }
401
583
  function tryParseGatewayEnvelopeJson(text) {
402
584
  const trimmed = text.trim();
@@ -417,8 +599,8 @@ function createGatewayRequestClient(config = {}) {
417
599
  const legacyError = failure && isRecord(failure.error) ? failure.error : failure?.legacyError;
418
600
  const correlationId = failure?.correlationId ?? args.response.headers.get("x-lucern-correlation-id")?.trim() ?? args.requestId;
419
601
  const policyTraceId = failure?.policyTraceId ?? args.response.headers.get("x-lucern-policy-trace-id")?.trim() ?? null;
420
- const details = redactJsonDiagnosticValue(
421
- failure?.details ?? legacyError?.details
602
+ const details = runtime.redaction(
603
+ redactJsonDiagnosticValue(failure?.details ?? legacyError?.details)
422
604
  );
423
605
  const policySummary = readPolicySummaryFromDetails(details);
424
606
  const failureMessage = typeof failure?.error === "string" ? failure.error : legacyError?.message;
@@ -488,7 +670,7 @@ function createGatewayRequestClient(config = {}) {
488
670
  failure
489
671
  });
490
672
  const willRetry = attempt < maxRetries && retry.retryable;
491
- await config.onResponse?.({
673
+ const responseContext2 = {
492
674
  ...hookRequestContext,
493
675
  durationMs: Date.now() - startedAt,
494
676
  status: response.status,
@@ -498,7 +680,9 @@ function createGatewayRequestClient(config = {}) {
498
680
  policyTraceId: apiError.policyTraceId ?? null,
499
681
  retryAfterMs,
500
682
  willRetry
501
- });
683
+ };
684
+ await config.onResponse?.(responseContext2);
685
+ await emitSdkResponseTelemetry(responseContext2);
502
686
  if (willRetry) {
503
687
  lastError = apiError;
504
688
  await delay(
@@ -513,7 +697,7 @@ function createGatewayRequestClient(config = {}) {
513
697
  throw apiError;
514
698
  }
515
699
  const successPayload = payload;
516
- await config.onResponse?.({
700
+ const responseContext = {
517
701
  ...hookRequestContext,
518
702
  durationMs: Date.now() - startedAt,
519
703
  status: response.status,
@@ -523,22 +707,25 @@ function createGatewayRequestClient(config = {}) {
523
707
  idempotentReplay: successPayload.idempotentReplay,
524
708
  retryAfterMs,
525
709
  willRetry: false
526
- });
710
+ };
711
+ await config.onResponse?.(responseContext);
712
+ await emitSdkResponseTelemetry(responseContext);
527
713
  return successPayload;
528
714
  } catch (fetchError) {
529
715
  if (fetchError instanceof LucernApiError) {
530
716
  throw fetchError;
531
717
  }
532
- const retry = classifyRetry({ error: fetchError });
533
- const willRetry = attempt < maxRetries && retry.retryable;
534
- await config.onResponse?.({
718
+ const willRetry = attempt < maxRetries && classifyGatewayErrorForRetry(fetchError);
719
+ const responseContext = {
535
720
  ...hookRequestContext,
536
721
  durationMs: Date.now() - startedAt,
537
722
  error: fetchError,
538
723
  correlationId: requestId,
539
724
  policyTraceId: null,
540
725
  willRetry
541
- });
726
+ };
727
+ await config.onResponse?.(responseContext);
728
+ await emitSdkResponseTelemetry(responseContext);
542
729
  lastError = fetchError;
543
730
  if (willRetry) {
544
731
  await delay(computeRetryDelayMs({ attempt }));