@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,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
  import { z } from 'zod';
4
6
  import { MCP_GATEWAY_EVALUATE_RESEARCH_CONTRACT_ENDPOINT, MCP_GATEWAY_EVALUATE_ENGINEERING_CONTRACT_ENDPOINT, MCP_GATEWAY_BEGIN_BUILD_SESSION_ENDPOINT, MCP_GATEWAY_WRITE_POLICY_CHECK_ENDPOINT, MCP_GATEWAY_BOOTSTRAP_ENDPOINT } from '@lucern/contracts/mcp-gateway-boundary.contract';
5
7
  import * as v1 from '@lucern/contracts/graph/v1';
@@ -177,6 +179,33 @@ function createCanonicalAuthHeaders(authContext) {
177
179
  }
178
180
 
179
181
  // src/coreClient.ts
182
+ var DEFAULT_GATEWAY_TIMEOUT_MS = 15e3;
183
+ var DEFAULT_GATEWAY_MAX_RETRIES = 2;
184
+ var DEFAULT_ENV_TIMEOUT_MS = "LUCERN_REQUEST_TIMEOUT_MS";
185
+ var DEFAULT_ENV_MAX_RETRIES = "LUCERN_GATEWAY_MAX_RETRIES";
186
+ var ENV_TIMEOUT_BY_METHOD_PREFIX = "LUCERN_REQUEST_TIMEOUT_MS_";
187
+ var GatewayTimeoutError = class extends Error {
188
+ retryable = true;
189
+ timeoutMs;
190
+ constructor(timeoutMs) {
191
+ super(`Request timed out after ${timeoutMs}ms`);
192
+ this.name = "AbortError";
193
+ this.timeoutMs = timeoutMs;
194
+ }
195
+ };
196
+ var GatewayTransportError = class extends Error {
197
+ retryable;
198
+ cause;
199
+ constructor(message, options) {
200
+ super(message);
201
+ this.name = "GatewayTransportError";
202
+ this.retryable = options?.retryable ?? true;
203
+ this.cause = options?.cause;
204
+ }
205
+ };
206
+ function isGatewayRetryableError(error) {
207
+ return error instanceof GatewayTimeoutError && error.retryable || error instanceof GatewayTransportError && error.retryable || false;
208
+ }
180
209
  var LucernApiError = class extends Error {
181
210
  code;
182
211
  status;
@@ -243,6 +272,99 @@ function generatePortableRequestId() {
243
272
  8
244
273
  ).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
245
274
  }
275
+ function resolveEnvironment() {
276
+ const processEnv = typeof globalThis === "object" && globalThis !== null && "process" in globalThis ? globalThis.process : void 0;
277
+ const env = processEnv !== void 0 && typeof processEnv === "object" && processEnv !== null && typeof processEnv.env === "object" ? processEnv.env : void 0;
278
+ return {
279
+ get: (name) => {
280
+ const value = env?.[name];
281
+ return typeof value === "string" && value.length > 0 ? value : void 0;
282
+ }
283
+ };
284
+ }
285
+ function telemetryEnvironmentRecord(environment) {
286
+ const names = [
287
+ "LUCERN_TELEMETRY_ENABLED",
288
+ "AXIOM_TELEMETRY_ENABLED",
289
+ "LUCERN_AXIOM_TOKEN",
290
+ "AXIOM_TOKEN",
291
+ "LUCERN_AXIOM_EVENTS_DATASET",
292
+ "LUCERN_AXIOM_DATASET",
293
+ "AXIOM_EVENTS_DATASET",
294
+ "AXIOM_DATASET",
295
+ "LUCERN_AXIOM_API_URL",
296
+ "AXIOM_URL",
297
+ "LUCERN_ENVIRONMENT",
298
+ "NODE_ENV",
299
+ "LUCERN_RELEASE",
300
+ "SENTRY_RELEASE",
301
+ "VERCEL_GIT_COMMIT_SHA"
302
+ ];
303
+ return Object.fromEntries(
304
+ names.map((name) => [name, environment.get(name)])
305
+ );
306
+ }
307
+ function resolveRequestProfile(config, environment) {
308
+ const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
309
+ const parsedMaxRetries = parseIntegerFromString(
310
+ config.maxRetries,
311
+ environment.get(DEFAULT_ENV_MAX_RETRIES)
312
+ );
313
+ const parsedTimeoutMs = parseIntegerFromString(
314
+ config.timeoutMs,
315
+ environment.get(DEFAULT_ENV_TIMEOUT_MS)
316
+ );
317
+ const methodTimeouts = {
318
+ ...config.timeoutMsByMethod
319
+ };
320
+ for (const method of ["GET", "POST", "PUT", "PATCH", "DELETE"]) {
321
+ const envKey = `${ENV_TIMEOUT_BY_METHOD_PREFIX}${method}`;
322
+ const raw = environment.get(envKey);
323
+ if (!raw || methodTimeouts[method] !== void 0) {
324
+ continue;
325
+ }
326
+ const parsed = parseIntegerFromString(void 0, raw);
327
+ if (typeof parsed === "number") {
328
+ methodTimeouts[method] = parsed;
329
+ }
330
+ }
331
+ return {
332
+ maxRetries: parsedMaxRetries ?? DEFAULT_GATEWAY_MAX_RETRIES,
333
+ timeoutMs: parsedTimeoutMs ?? DEFAULT_GATEWAY_TIMEOUT_MS,
334
+ timeoutMsByMethod: methodTimeouts,
335
+ requestIdFactory
336
+ };
337
+ }
338
+ function createGatewayRuntime(config, environment) {
339
+ return {
340
+ fetch: config.fetchImpl ?? fetch,
341
+ now: () => Date.now(),
342
+ sleep: (ms) => delay(ms),
343
+ env: environment,
344
+ redaction: resolveRequestRedactionValue,
345
+ profile: resolveRequestProfile(config, environment)
346
+ };
347
+ }
348
+ function parseIntegerFromString(value, rawValue) {
349
+ if (typeof value === "number" && Number.isInteger(value) && value >= 0) {
350
+ return value;
351
+ }
352
+ if (typeof rawValue !== "string" || !rawValue.trim()) {
353
+ return void 0;
354
+ }
355
+ const parsed = Number.parseInt(rawValue, 10);
356
+ return Number.isInteger(parsed) && parsed >= 0 ? parsed : void 0;
357
+ }
358
+ function resolveRequestRedactionValue(value) {
359
+ return redactDiagnosticValue(value);
360
+ }
361
+ function resolveGatewayBaseUrl(configBaseUrl, environment) {
362
+ const envBaseUrl = environment.get("LUCERN_API_URL") ?? environment.get("LUCERN_BASE_URL") ?? environment.get("LUCERN_GATEWAY_BASE_URL");
363
+ return (configBaseUrl ?? envBaseUrl ?? "").replace(/\/+$/, "");
364
+ }
365
+ function normalizeGatewayEnvironment(value) {
366
+ return value === "sandbox" || value === "production" ? value : void 0;
367
+ }
246
368
  var randomIdempotencyKey = generatePortableRequestId;
247
369
  function fallbackErrorCode(status) {
248
370
  if (status === 401) {
@@ -282,10 +404,8 @@ function computeRetryDelayMs(args) {
282
404
  const jitterWindow = Math.max(250, Math.round(baseDelay * 0.25));
283
405
  return baseDelay + Math.round(Math.random() * jitterWindow);
284
406
  }
285
- function timeoutError(timeoutMs) {
286
- const error = new Error(`Request timed out after ${timeoutMs}ms`);
287
- error.name = "AbortError";
288
- return error;
407
+ function classifyGatewayErrorForRetry(error) {
408
+ return isGatewayRetryableError(error) || classifyRetry({ error }).retryable;
289
409
  }
290
410
  function isRecord(value) {
291
411
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -340,10 +460,18 @@ function cleanHeaderValue(value) {
340
460
  return normalized ? normalized : void 0;
341
461
  }
342
462
  function createGatewayRequestClient(config = {}) {
343
- const fetchImpl = config.fetchImpl ?? fetch;
344
- const baseUrl = config.baseUrl?.replace(/\/+$/, "") ?? "";
345
- const maxRetries = config.maxRetries ?? 2;
346
- const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
463
+ const env = resolveEnvironment();
464
+ const runtime = createGatewayRuntime(config, env);
465
+ const baseUrl = resolveGatewayBaseUrl(config.baseUrl, env);
466
+ const maxRetries = runtime.profile.maxRetries;
467
+ const requestIdFactory = runtime.profile.requestIdFactory;
468
+ const requestTimeoutByMethod = runtime.profile.timeoutMsByMethod;
469
+ const defaultRequestTimeoutMs = runtime.profile.timeoutMs;
470
+ const normalizedEnvironment = normalizeGatewayEnvironment(config.environment);
471
+ const telemetryExporter = config.telemetryEnabled === false ? null : config.telemetryExporter ?? createTelemetryExporterFromEnv(telemetryEnvironmentRecord(env), {
472
+ service: "lucern-sdk",
473
+ environment: normalizedEnvironment
474
+ });
347
475
  async function resolveAuthHeaders() {
348
476
  const provided = config.getAuthHeaders ? await config.getAuthHeaders() : {};
349
477
  const headers = new Headers(provided);
@@ -355,7 +483,7 @@ function createGatewayRequestClient(config = {}) {
355
483
  };
356
484
  setIfAbsent("x-lucern-key", config.apiKey);
357
485
  setIfAbsent("x-lucern-session-token", config.userToken);
358
- setIfAbsent("x-lucern-environment", config.environment);
486
+ setIfAbsent("x-lucern-environment", normalizedEnvironment);
359
487
  setIfAbsent("x-lucern-clerk-id", config.clerkId);
360
488
  setIfAbsent("x-lucern-user-id", config.userId ?? config.clerkId);
361
489
  setIfAbsent("x-lucern-deployment-host", config.deploymentHost);
@@ -370,19 +498,73 @@ function createGatewayRequestClient(config = {}) {
370
498
  return mergeHeaderRecord(base, createCanonicalAuthHeaders(authContext));
371
499
  }
372
500
  async function fetchWithTimeout(url, init, timeoutMs) {
501
+ const normalizeTransportError = (error, isTimeout) => {
502
+ if (isTimeout) {
503
+ return new GatewayTimeoutError(timeoutMs);
504
+ }
505
+ return error instanceof GatewayTimeoutError || error instanceof GatewayTransportError ? error : new GatewayTransportError(
506
+ error instanceof Error ? error.message : "Gateway transport error",
507
+ {
508
+ cause: error,
509
+ retryable: classifyGatewayErrorForRetry(error)
510
+ }
511
+ );
512
+ };
373
513
  const controller = new AbortController();
374
514
  const timer = setTimeout(() => controller.abort(), timeoutMs);
515
+ const requestEffect = Effect.tryPromise({
516
+ try: () => runtime.fetch(url, { ...init, signal: controller.signal }),
517
+ catch: (error) => normalizeTransportError(error, controller.signal.aborted)
518
+ });
375
519
  try {
376
- return await fetchImpl(url, { ...init, signal: controller.signal });
377
- } catch (error) {
378
- if (controller.signal.aborted) {
379
- throw timeoutError(timeoutMs);
520
+ const exit = await Effect.runPromiseExit(requestEffect);
521
+ if (Exit.isSuccess(exit)) {
522
+ return exit.value;
380
523
  }
381
- throw error;
524
+ const failure = Array.from(Cause.failures(exit.cause))[0];
525
+ if (failure !== void 0) {
526
+ throw failure;
527
+ }
528
+ throw Cause.squash(exit.cause);
382
529
  } finally {
383
530
  clearTimeout(timer);
384
531
  }
385
532
  }
533
+ async function emitSdkResponseTelemetry(context) {
534
+ const retry = classifyRetry({
535
+ status: context.status,
536
+ error: context.error,
537
+ retryAfter: context.retryAfterMs !== null && context.retryAfterMs !== void 0 ? String(context.retryAfterMs / 1e3) : void 0
538
+ });
539
+ await emitTelemetrySignal(telemetryExporter, {
540
+ signalType: "trace",
541
+ surface: "sdk-retry",
542
+ eventName: context.willRetry ? "sdk.retry" : context.error ? "sdk.request.error" : "sdk.request.complete",
543
+ severity: context.error ? context.willRetry ? "warn" : "error" : "info",
544
+ durationMs: context.durationMs,
545
+ metricName: "sdk.request.duration_ms",
546
+ metricValue: context.durationMs,
547
+ correlationId: context.correlationId ?? context.requestId,
548
+ policyTraceId: context.policyTraceId ?? null,
549
+ tenantId: context.headers.get("x-lucern-tenant-id") ?? context.headers.get("x-lucern-tenant") ?? void 0,
550
+ workspaceId: context.headers.get("x-lucern-workspace-id") ?? context.headers.get("x-lucern-workspace") ?? void 0,
551
+ attributes: {
552
+ service: "lucern-sdk",
553
+ operation: "gateway.request",
554
+ path: context.path,
555
+ httpMethod: context.method,
556
+ httpStatus: context.status,
557
+ attempt: context.attempt,
558
+ maxRetries: context.maxRetries,
559
+ retryReason: retry.reason,
560
+ retryAfterMs: context.retryAfterMs ?? retry.retryAfterMs,
561
+ willRetry: context.willRetry,
562
+ retryable: retry.retryable,
563
+ errorName: context.error instanceof Error ? context.error.name : void 0,
564
+ errorMessage: context.error instanceof Error ? context.error.message : void 0
565
+ }
566
+ });
567
+ }
386
568
  async function parsePayload(response) {
387
569
  const text = await response.text();
388
570
  if (!text) {
@@ -398,11 +580,11 @@ function createGatewayRequestClient(config = {}) {
398
580
  if (typeof requestTimeoutMs === "number") {
399
581
  return requestTimeoutMs;
400
582
  }
401
- const methodTimeoutMs = config.timeoutMsByMethod?.[method];
583
+ const methodTimeoutMs = requestTimeoutByMethod?.[method];
402
584
  if (typeof methodTimeoutMs === "number") {
403
585
  return methodTimeoutMs;
404
586
  }
405
- return config.timeoutMs ?? 15e3;
587
+ return defaultRequestTimeoutMs;
406
588
  }
407
589
  function tryParseGatewayEnvelopeJson(text) {
408
590
  const trimmed = text.trim();
@@ -423,8 +605,8 @@ function createGatewayRequestClient(config = {}) {
423
605
  const legacyError = failure && isRecord(failure.error) ? failure.error : failure?.legacyError;
424
606
  const correlationId = failure?.correlationId ?? args.response.headers.get("x-lucern-correlation-id")?.trim() ?? args.requestId;
425
607
  const policyTraceId = failure?.policyTraceId ?? args.response.headers.get("x-lucern-policy-trace-id")?.trim() ?? null;
426
- const details = redactJsonDiagnosticValue(
427
- failure?.details ?? legacyError?.details
608
+ const details = runtime.redaction(
609
+ redactJsonDiagnosticValue(failure?.details ?? legacyError?.details)
428
610
  );
429
611
  const policySummary = readPolicySummaryFromDetails(details);
430
612
  const failureMessage = typeof failure?.error === "string" ? failure.error : legacyError?.message;
@@ -494,7 +676,7 @@ function createGatewayRequestClient(config = {}) {
494
676
  failure
495
677
  });
496
678
  const willRetry = attempt < maxRetries && retry.retryable;
497
- await config.onResponse?.({
679
+ const responseContext2 = {
498
680
  ...hookRequestContext,
499
681
  durationMs: Date.now() - startedAt,
500
682
  status: response.status,
@@ -504,7 +686,9 @@ function createGatewayRequestClient(config = {}) {
504
686
  policyTraceId: apiError.policyTraceId ?? null,
505
687
  retryAfterMs,
506
688
  willRetry
507
- });
689
+ };
690
+ await config.onResponse?.(responseContext2);
691
+ await emitSdkResponseTelemetry(responseContext2);
508
692
  if (willRetry) {
509
693
  lastError = apiError;
510
694
  await delay(
@@ -519,7 +703,7 @@ function createGatewayRequestClient(config = {}) {
519
703
  throw apiError;
520
704
  }
521
705
  const successPayload = payload;
522
- await config.onResponse?.({
706
+ const responseContext = {
523
707
  ...hookRequestContext,
524
708
  durationMs: Date.now() - startedAt,
525
709
  status: response.status,
@@ -529,22 +713,25 @@ function createGatewayRequestClient(config = {}) {
529
713
  idempotentReplay: successPayload.idempotentReplay,
530
714
  retryAfterMs,
531
715
  willRetry: false
532
- });
716
+ };
717
+ await config.onResponse?.(responseContext);
718
+ await emitSdkResponseTelemetry(responseContext);
533
719
  return successPayload;
534
720
  } catch (fetchError) {
535
721
  if (fetchError instanceof LucernApiError) {
536
722
  throw fetchError;
537
723
  }
538
- const retry = classifyRetry({ error: fetchError });
539
- const willRetry = attempt < maxRetries && retry.retryable;
540
- await config.onResponse?.({
724
+ const willRetry = attempt < maxRetries && classifyGatewayErrorForRetry(fetchError);
725
+ const responseContext = {
541
726
  ...hookRequestContext,
542
727
  durationMs: Date.now() - startedAt,
543
728
  error: fetchError,
544
729
  correlationId: requestId,
545
730
  policyTraceId: null,
546
731
  willRetry
547
- });
732
+ };
733
+ await config.onResponse?.(responseContext);
734
+ await emitSdkResponseTelemetry(responseContext);
548
735
  lastError = fetchError;
549
736
  if (willRetry) {
550
737
  await delay(computeRetryDelayMs({ attempt }));
@@ -9336,7 +9523,7 @@ function createToolRegistryClient(config = {}) {
9336
9523
  }
9337
9524
 
9338
9525
  // src/version.ts
9339
- var LUCERN_SDK_VERSION = "1.0.1";
9526
+ var LUCERN_SDK_VERSION = "1.0.3";
9340
9527
 
9341
9528
  // src/workflowClient.ts
9342
9529
  function normalizeLensQuery(value) {