agentid-sdk 0.1.25 → 0.1.26

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.
@@ -1149,6 +1149,79 @@ var PIIManager = class {
1149
1149
  }
1150
1150
  };
1151
1151
 
1152
+ // src/context-intent.ts
1153
+ var EDUCATIONAL_MARKERS = [
1154
+ "explain",
1155
+ "analysis",
1156
+ "analyze",
1157
+ "analyse",
1158
+ "review",
1159
+ "summarize",
1160
+ "summarise",
1161
+ "summary",
1162
+ "plain-language explanation",
1163
+ "red flags",
1164
+ "security workshop",
1165
+ "training",
1166
+ "lesson",
1167
+ "quoted attack",
1168
+ "quoted example",
1169
+ "attack example",
1170
+ "security event",
1171
+ "security log",
1172
+ "audit log",
1173
+ "incident report",
1174
+ "trace timeline"
1175
+ ];
1176
+ var WARNING_MARKERS = [
1177
+ "dangerous",
1178
+ "risky",
1179
+ "risk",
1180
+ "warning",
1181
+ "warn",
1182
+ "malicious",
1183
+ "security indicator",
1184
+ "red flags"
1185
+ ];
1186
+ var NON_EXECUTION_MARKERS = [
1187
+ "do not execute",
1188
+ "do not run",
1189
+ "do not return commands",
1190
+ "do not output commands",
1191
+ "do not provide executable steps",
1192
+ "for explanation only",
1193
+ "non-executable"
1194
+ ];
1195
+ function normalizeIntentInput(input) {
1196
+ return input.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, " ").trim();
1197
+ }
1198
+ function hasAnyMarker(input, markers) {
1199
+ return markers.some((marker) => input.includes(marker));
1200
+ }
1201
+ function classifyInjectionContextIntent(input) {
1202
+ const normalized = normalizeIntentInput(input ?? "");
1203
+ if (!normalized) {
1204
+ return {
1205
+ educational: false,
1206
+ quotedExample: false,
1207
+ warningOnly: false,
1208
+ nonExecutableConstraint: false,
1209
+ promptInjectionExempt: false
1210
+ };
1211
+ }
1212
+ const educational = hasAnyMarker(normalized, EDUCATIONAL_MARKERS);
1213
+ const warningOnly = hasAnyMarker(normalized, WARNING_MARKERS);
1214
+ const nonExecutableConstraint = hasAnyMarker(normalized, NON_EXECUTION_MARKERS);
1215
+ const quotedExample = /["'`]/.test(input) || normalized.includes("quoted") || normalized.includes("quote") || normalized.includes("phrase") || normalized.includes("attack example");
1216
+ return {
1217
+ educational,
1218
+ quotedExample,
1219
+ warningOnly,
1220
+ nonExecutableConstraint,
1221
+ promptInjectionExempt: educational && (quotedExample || warningOnly || nonExecutableConstraint || normalized.includes("prompt injection indicator") || normalized.includes("jailbreak prompt"))
1222
+ };
1223
+ }
1224
+
1152
1225
  // src/security.ts
1153
1226
  var MAX_ANALYSIS_WINDOW = 8192;
1154
1227
  var WINDOW_SLICE_SIZE = 4e3;
@@ -1311,6 +1384,10 @@ function findRegexMatch(prompt) {
1311
1384
  if (!prompt) {
1312
1385
  return null;
1313
1386
  }
1387
+ const contextIntent = classifyInjectionContextIntent(prompt);
1388
+ if (contextIntent.promptInjectionExempt) {
1389
+ return null;
1390
+ }
1314
1391
  const normalizedPrompt = normalizeForHeuristics(prompt);
1315
1392
  for (const rule of HEURISTIC_RULES) {
1316
1393
  try {
@@ -1444,7 +1521,8 @@ async function reportSecurityEvent(options) {
1444
1521
  language: options.language,
1445
1522
  ai_scan_status: options.aiStatus ?? null,
1446
1523
  reason: options.reason ?? null,
1447
- client_event_id: eventId
1524
+ client_event_id: eventId,
1525
+ ...options.telemetryMetadata ?? {}
1448
1526
  };
1449
1527
  if (options.storePii) {
1450
1528
  metadata.snippet = snippet;
@@ -1492,7 +1570,8 @@ var InjectionScanner = class _InjectionScanner {
1492
1570
  source: options?.source,
1493
1571
  systemId: options?.systemId,
1494
1572
  eventId: options?.eventId,
1495
- clientEventId: options?.clientEventId
1573
+ clientEventId: options?.clientEventId,
1574
+ telemetryMetadata: options?.telemetryMetadata
1496
1575
  });
1497
1576
  }
1498
1577
  async scan(params) {
@@ -1504,6 +1583,11 @@ var InjectionScanner = class _InjectionScanner {
1504
1583
  const storePii = params.storePii === true;
1505
1584
  const aiScanEnabled = params.aiScanEnabled !== false;
1506
1585
  const language = detectLanguageTag(prompt);
1586
+ const scanStartedAt = Date.now();
1587
+ const buildTelemetryMetadata = () => ({
1588
+ ...params.telemetryMetadata ?? {},
1589
+ sdk_local_scan_ms: Math.max(0, Date.now() - scanStartedAt)
1590
+ });
1507
1591
  const regexMatch = findRegexMatch(prompt);
1508
1592
  if (regexMatch) {
1509
1593
  await reportSecurityEvent({
@@ -1518,7 +1602,8 @@ var InjectionScanner = class _InjectionScanner {
1518
1602
  language,
1519
1603
  systemId: params.systemId,
1520
1604
  eventId: params.eventId,
1521
- clientEventId: params.clientEventId
1605
+ clientEventId: params.clientEventId,
1606
+ telemetryMetadata: buildTelemetryMetadata()
1522
1607
  });
1523
1608
  throw new Error(`AgentID: Prompt injection blocked (${regexMatch.rule})`);
1524
1609
  }
@@ -1542,7 +1627,8 @@ var InjectionScanner = class _InjectionScanner {
1542
1627
  reason: "ai_scan_disabled_for_high_risk_language",
1543
1628
  systemId: params.systemId,
1544
1629
  eventId: params.eventId,
1545
- clientEventId: params.clientEventId
1630
+ clientEventId: params.clientEventId,
1631
+ telemetryMetadata: buildTelemetryMetadata()
1546
1632
  });
1547
1633
  return;
1548
1634
  }
@@ -1564,7 +1650,8 @@ var InjectionScanner = class _InjectionScanner {
1564
1650
  reason: aiResult.reason,
1565
1651
  systemId: params.systemId,
1566
1652
  eventId: params.eventId,
1567
- clientEventId: params.clientEventId
1653
+ clientEventId: params.clientEventId,
1654
+ telemetryMetadata: buildTelemetryMetadata()
1568
1655
  });
1569
1656
  return;
1570
1657
  }
@@ -1583,7 +1670,8 @@ var InjectionScanner = class _InjectionScanner {
1583
1670
  reason: aiResult.reason,
1584
1671
  systemId: params.systemId,
1585
1672
  eventId: params.eventId,
1586
- clientEventId: params.clientEventId
1673
+ clientEventId: params.clientEventId,
1674
+ telemetryMetadata: buildTelemetryMetadata()
1587
1675
  });
1588
1676
  throw new Error(`AgentID: Prompt injection blocked (${aiResult.reason})`);
1589
1677
  }
@@ -1595,7 +1683,7 @@ function getInjectionScanner() {
1595
1683
 
1596
1684
  // src/sdk-version.ts
1597
1685
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
1598
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.25".trim().length > 0 ? "js-0.1.25" : FALLBACK_SDK_VERSION;
1686
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.26".trim().length > 0 ? "js-0.1.26" : FALLBACK_SDK_VERSION;
1599
1687
 
1600
1688
  // src/local-security-enforcer.ts
1601
1689
  var DEFAULT_FAIL_OPEN_CONFIG = {
@@ -1708,8 +1796,8 @@ var LocalSecurityEnforcer = class {
1708
1796
 
1709
1797
  // src/capability-config.ts
1710
1798
  var CONFIG_TTL_MS = 5 * 60 * 1e3;
1711
- var CONFIG_TIMEOUT_MS = 8e3;
1712
- var CONFIG_RETRY_DELAY_MS = 1e3;
1799
+ var CONFIG_TIMEOUT_MS = 1500;
1800
+ var CONFIG_RETRY_DELAY_MS = 150;
1713
1801
  var MAX_CAPABILITY_CACHE_ENTRIES = 500;
1714
1802
  var CapabilityConfigFetchError = class extends Error {
1715
1803
  constructor(message, params) {
@@ -2050,6 +2138,19 @@ function normalizeIngestTimeoutMs(value) {
2050
2138
  }
2051
2139
  return rounded;
2052
2140
  }
2141
+ function setFiniteDurationMetadata(metadata, key, value) {
2142
+ if (typeof value === "number" && Number.isFinite(value)) {
2143
+ metadata[key] = Math.max(0, Math.trunc(value));
2144
+ }
2145
+ }
2146
+ function buildSdkTimingMetadata(params) {
2147
+ const metadata = {};
2148
+ setFiniteDurationMetadata(metadata, "sdk_config_fetch_ms", params.sdkConfigFetchMs);
2149
+ setFiniteDurationMetadata(metadata, "sdk_local_scan_ms", params.sdkLocalScanMs);
2150
+ setFiniteDurationMetadata(metadata, "sdk_guard_ms", params.sdkGuardMs);
2151
+ setFiniteDurationMetadata(metadata, "sdk_ingest_ms", params.sdkIngestMs);
2152
+ return metadata;
2153
+ }
2053
2154
  function resolveConfiguredApiKey(value) {
2054
2155
  const explicit = typeof value === "string" ? value.trim() : "";
2055
2156
  const fromEnv = globalThis.process?.env?.AGENTID_API_KEY ?? "";
@@ -2063,6 +2164,9 @@ function isInfrastructureGuardReason(reason) {
2063
2164
  if (!reason) return false;
2064
2165
  return reason === "system_failure" || reason === "system_failure_db_unavailable" || reason === "logging_failed" || reason === "server_error" || reason === "guard_unreachable" || reason === "api_key_pepper_missing" || reason === "encryption_key_missing";
2065
2166
  }
2167
+ function isGuardFailureEligibleForLocalFallback(reason) {
2168
+ return reason === "network_error_strict_mode" || reason === "server_error" || isInfrastructureGuardReason(reason);
2169
+ }
2066
2170
  function isFailCloseIngestReason(reason) {
2067
2171
  if (!reason) return false;
2068
2172
  return reason === "system_failure" || reason === "system_failure_db_unavailable" || reason === "server_error" || reason === "redis_rate_limit_unavailable" || reason === "redis_quota_unavailable" || reason === "redis_token_quota_unavailable";
@@ -2272,6 +2376,7 @@ var AgentID = class {
2272
2376
  this.baseUrl = normalizeBaseUrl3(config.baseUrl ?? "https://app.getagentid.com/api/v1");
2273
2377
  this.configuredPiiMasking = typeof config.piiMasking === "boolean" ? config.piiMasking : null;
2274
2378
  this.checkInjection = config.checkInjection !== false;
2379
+ this.clientFastFail = config.clientFastFail === true || config.client_fast_fail === true;
2275
2380
  this.aiScanEnabled = config.aiScanEnabled !== false;
2276
2381
  this.storePii = config.storePii === true;
2277
2382
  this.strictMode = config.strictMode === true;
@@ -2374,6 +2479,14 @@ var AgentID = class {
2374
2479
  force
2375
2480
  });
2376
2481
  }
2482
+ async getCapabilityConfigWithTelemetry(force = false, options) {
2483
+ const configStartedAt = Date.now();
2484
+ const capabilityConfig = await this.getCapabilityConfig(force, options);
2485
+ return {
2486
+ capabilityConfig,
2487
+ sdkConfigFetchMs: Math.max(0, Date.now() - configStartedAt)
2488
+ };
2489
+ }
2377
2490
  getCachedCapabilityConfig(options) {
2378
2491
  const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2379
2492
  return getCachedCapabilityConfig({
@@ -2417,37 +2530,45 @@ var AgentID = class {
2417
2530
  }
2418
2531
  return config.block_on_heuristic;
2419
2532
  }
2420
- async prepareInputForDispatch(params, options) {
2421
- const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2422
- const capabilityConfig = await this.getCapabilityConfig(false, options);
2423
- if (!params.skipInjectionScan && params.input && this.shouldRunLocalInjectionScan(capabilityConfig)) {
2533
+ async applyLocalPolicyChecks(params) {
2534
+ const localScanStartedAt = Date.now();
2535
+ if (params.runPromptInjectionCheck && params.input && this.shouldRunLocalInjectionScan(params.capabilityConfig)) {
2424
2536
  await this.injectionScanner.scan({
2425
2537
  prompt: params.input,
2426
- apiKey: effectiveApiKey,
2538
+ apiKey: params.apiKey,
2427
2539
  baseUrl: this.baseUrl,
2428
2540
  aiScanEnabled: this.aiScanEnabled,
2429
2541
  storePii: this.storePii,
2430
2542
  piiManager: this.pii,
2431
- source: "js_sdk"
2543
+ source: "js_sdk",
2544
+ systemId: params.systemId,
2545
+ eventId: params.clientEventId,
2546
+ clientEventId: params.clientEventId,
2547
+ telemetryMetadata: buildSdkTimingMetadata({
2548
+ sdkConfigFetchMs: params.sdkConfigFetchMs
2549
+ })
2432
2550
  });
2433
2551
  }
2434
2552
  try {
2435
2553
  const enforced = this.localEnforcer.enforce({
2436
2554
  input: params.input,
2437
2555
  stream: params.stream,
2438
- config: capabilityConfig
2556
+ config: params.capabilityConfig
2439
2557
  });
2558
+ const sdkLocalScanMs = Math.max(0, Date.now() - localScanStartedAt);
2440
2559
  for (const event of enforced.events) {
2441
2560
  this.logSecurityPolicyViolation({
2442
2561
  systemId: params.systemId,
2443
2562
  violationType: event.violationType,
2444
2563
  actionTaken: event.actionTaken,
2445
- apiKey: effectiveApiKey
2564
+ apiKey: params.apiKey,
2565
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
2566
+ sdkLocalScanMs
2446
2567
  });
2447
2568
  }
2448
2569
  return {
2449
2570
  sanitizedInput: enforced.sanitizedInput,
2450
- capabilityConfig
2571
+ sdkLocalScanMs
2451
2572
  };
2452
2573
  } catch (error) {
2453
2574
  if (error instanceof SecurityPolicyViolationError) {
@@ -2455,17 +2576,76 @@ var AgentID = class {
2455
2576
  systemId: params.systemId,
2456
2577
  violationType: error.violationType,
2457
2578
  actionTaken: error.actionTaken,
2458
- apiKey: effectiveApiKey
2579
+ apiKey: params.apiKey,
2580
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
2581
+ sdkLocalScanMs: Math.max(0, Date.now() - localScanStartedAt)
2459
2582
  });
2460
2583
  }
2461
2584
  throw error;
2462
2585
  }
2463
2586
  }
2587
+ async prepareInputForDispatch(params, options) {
2588
+ const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2589
+ const { capabilityConfig, sdkConfigFetchMs } = await this.getCapabilityConfigWithTelemetry(
2590
+ false,
2591
+ options
2592
+ );
2593
+ if (!this.clientFastFail) {
2594
+ return {
2595
+ sanitizedInput: params.input,
2596
+ capabilityConfig,
2597
+ sdkConfigFetchMs,
2598
+ sdkLocalScanMs: 0
2599
+ };
2600
+ }
2601
+ const enforced = await this.applyLocalPolicyChecks({
2602
+ input: params.input,
2603
+ systemId: params.systemId,
2604
+ stream: params.stream,
2605
+ capabilityConfig,
2606
+ apiKey: effectiveApiKey,
2607
+ clientEventId: params.clientEventId,
2608
+ sdkConfigFetchMs,
2609
+ runPromptInjectionCheck: !params.skipInjectionScan
2610
+ });
2611
+ return {
2612
+ sanitizedInput: enforced.sanitizedInput,
2613
+ capabilityConfig,
2614
+ sdkConfigFetchMs,
2615
+ sdkLocalScanMs: enforced.sdkLocalScanMs
2616
+ };
2617
+ }
2618
+ async applyLocalFallbackForGuardFailure(params, options) {
2619
+ const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2620
+ const resolvedConfig = params.capabilityConfig && typeof params.sdkConfigFetchMs === "number" ? {
2621
+ capabilityConfig: params.capabilityConfig,
2622
+ sdkConfigFetchMs: params.sdkConfigFetchMs
2623
+ } : await this.getCapabilityConfigWithTelemetry(false, options);
2624
+ const enforced = await this.applyLocalPolicyChecks({
2625
+ input: params.input,
2626
+ systemId: params.systemId,
2627
+ stream: params.stream,
2628
+ capabilityConfig: resolvedConfig.capabilityConfig,
2629
+ apiKey: effectiveApiKey,
2630
+ clientEventId: params.clientEventId,
2631
+ sdkConfigFetchMs: resolvedConfig.sdkConfigFetchMs,
2632
+ runPromptInjectionCheck: true
2633
+ });
2634
+ return {
2635
+ sanitizedInput: enforced.sanitizedInput,
2636
+ capabilityConfig: resolvedConfig.capabilityConfig,
2637
+ sdkConfigFetchMs: resolvedConfig.sdkConfigFetchMs,
2638
+ sdkLocalScanMs: enforced.sdkLocalScanMs
2639
+ };
2640
+ }
2464
2641
  async scanPromptInjection(input, options) {
2465
2642
  if (!input) {
2466
2643
  return;
2467
2644
  }
2468
- const capabilityConfig = await this.getCapabilityConfig(false, options);
2645
+ const { capabilityConfig, sdkConfigFetchMs } = await this.getCapabilityConfigWithTelemetry(
2646
+ false,
2647
+ options
2648
+ );
2469
2649
  if (!this.shouldRunLocalInjectionScan(capabilityConfig)) {
2470
2650
  return;
2471
2651
  }
@@ -2480,7 +2660,10 @@ var AgentID = class {
2480
2660
  source: "js_sdk",
2481
2661
  systemId: options?.systemId,
2482
2662
  eventId: options?.clientEventId,
2483
- clientEventId: options?.clientEventId
2663
+ clientEventId: options?.clientEventId,
2664
+ telemetryMetadata: buildSdkTimingMetadata({
2665
+ sdkConfigFetchMs
2666
+ })
2484
2667
  });
2485
2668
  }
2486
2669
  withMaskedOpenAIRequest(req, maskedText) {
@@ -2529,7 +2712,11 @@ var AgentID = class {
2529
2712
  system_id: params.systemId,
2530
2713
  violation_type: params.violationType,
2531
2714
  input_snippet: "[REDACTED_SAMPLE]",
2532
- action_taken: params.actionTaken
2715
+ action_taken: params.actionTaken,
2716
+ ...buildSdkTimingMetadata({
2717
+ sdkConfigFetchMs: params.sdkConfigFetchMs,
2718
+ sdkLocalScanMs: params.sdkLocalScanMs
2719
+ })
2533
2720
  }
2534
2721
  }, { apiKey: params.apiKey });
2535
2722
  }
@@ -2555,6 +2742,42 @@ var AgentID = class {
2555
2742
  { apiKey: params.apiKey }
2556
2743
  );
2557
2744
  }
2745
+ async finalizeIngestTelemetry(params) {
2746
+ const controller = new AbortController();
2747
+ const timeoutId = setTimeout(
2748
+ () => controller.abort(),
2749
+ Math.min(this.ingestTimeoutMs, 2e3)
2750
+ );
2751
+ try {
2752
+ const response = await fetch(`${this.baseUrl}/ingest/finalize`, {
2753
+ method: "POST",
2754
+ headers: {
2755
+ "Content-Type": "application/json",
2756
+ "x-agentid-api-key": params.apiKey,
2757
+ "x-correlation-id": params.clientEventId,
2758
+ "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER
2759
+ },
2760
+ body: JSON.stringify({
2761
+ client_event_id: params.clientEventId,
2762
+ system_id: params.systemId,
2763
+ sdk_ingest_ms: params.sdkIngestMs
2764
+ }),
2765
+ signal: controller.signal
2766
+ });
2767
+ if (!response.ok) {
2768
+ console.warn(
2769
+ `[AgentID] Ingest telemetry finalize failed (status=${response.status}, client_event_id=${params.clientEventId}).`
2770
+ );
2771
+ }
2772
+ } catch (error) {
2773
+ const label = error && typeof error === "object" && error.name === "AbortError" ? "timeout" : "network";
2774
+ console.warn(
2775
+ `[AgentID] Ingest telemetry finalize failed (${label}, client_event_id=${params.clientEventId}).`
2776
+ );
2777
+ } finally {
2778
+ clearTimeout(timeoutId);
2779
+ }
2780
+ }
2558
2781
  /**
2559
2782
  * GUARD: Checks limits, PII, and security before execution.
2560
2783
  * strictMode=false (default): FAIL-OPEN on connectivity/timeouts.
@@ -2712,15 +2935,16 @@ var AgentID = class {
2712
2935
  }
2713
2936
  return withGuardLatency({ allowed: true, reason: "guard_unreachable" });
2714
2937
  }
2715
- async sendIngest(params, options) {
2938
+ async sendIngest(params, options, internal) {
2939
+ const ingestStartedAt = Date.now();
2716
2940
  const effectiveApiKey = this.resolveApiKey(options?.apiKey);
2717
- const eventId = createEventId2(params.event_id);
2941
+ const transportEventId = createEventId2(internal?.transportEventId ?? params.event_id);
2718
2942
  const timestamp = params.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
2719
2943
  const metadata = {
2720
2944
  ...params.metadata ?? {}
2721
2945
  };
2722
2946
  const metadataClientEventId = typeof metadata.client_event_id === "string" && isUuidLike2(metadata.client_event_id) ? metadata.client_event_id : null;
2723
- const canonicalClientEventId = metadataClientEventId ?? eventId;
2947
+ const canonicalClientEventId = metadataClientEventId ?? transportEventId;
2724
2948
  if (!metadataClientEventId) {
2725
2949
  metadata.client_event_id = canonicalClientEventId;
2726
2950
  }
@@ -2730,7 +2954,7 @@ var AgentID = class {
2730
2954
  void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2731
2955
  const payload = {
2732
2956
  ...params,
2733
- event_id: canonicalClientEventId,
2957
+ event_id: internal?.transportEventId ? transportEventId : canonicalClientEventId,
2734
2958
  timestamp,
2735
2959
  input: sanitizeIngestText(params.input),
2736
2960
  output: sanitizeIngestText(params.output),
@@ -2755,6 +2979,14 @@ var AgentID = class {
2755
2979
  });
2756
2980
  const responseBody = await safeReadJson2(response);
2757
2981
  if (response.ok) {
2982
+ if (!internal?.disableFinalize) {
2983
+ void this.finalizeIngestTelemetry({
2984
+ apiKey: effectiveApiKey,
2985
+ clientEventId: canonicalClientEventId,
2986
+ systemId: params.system_id,
2987
+ sdkIngestMs: Math.max(0, Date.now() - ingestStartedAt)
2988
+ });
2989
+ }
2758
2990
  return { ok: true, status: response.status, reason: null };
2759
2991
  }
2760
2992
  const reason = responseBody && typeof responseBody === "object" && typeof responseBody.reason === "string" ? responseBody.reason ?? null : null;
@@ -2955,20 +3187,19 @@ var AgentID = class {
2955
3187
  let createArgs = normalizedCreateArgs;
2956
3188
  let mapping = {};
2957
3189
  let shouldDeanonymize = false;
3190
+ let sdkConfigFetchMs = 0;
3191
+ let sdkLocalScanMs = 0;
2958
3192
  if (userText) {
2959
- await this.scanPromptInjection(userText, {
2960
- ...requestOptions,
2961
- clientEventId,
2962
- systemId
2963
- });
2964
3193
  const prepared = await this.prepareInputForDispatch({
2965
3194
  input: userText,
2966
3195
  systemId,
2967
3196
  stream,
2968
- skipInjectionScan: true
3197
+ clientEventId
2969
3198
  }, requestOptions);
2970
3199
  capabilityConfig = prepared.capabilityConfig;
2971
3200
  maskedText = prepared.sanitizedInput;
3201
+ sdkConfigFetchMs = prepared.sdkConfigFetchMs ?? 0;
3202
+ sdkLocalScanMs = prepared.sdkLocalScanMs ?? 0;
2972
3203
  if (maskedText !== userText) {
2973
3204
  maskedReq = this.withMaskedOpenAIRequest(
2974
3205
  req,
@@ -3015,8 +3246,39 @@ var AgentID = class {
3015
3246
  capabilityConfig
3016
3247
  )
3017
3248
  }, requestOptions);
3249
+ let localFallbackApplied = false;
3250
+ let localFallbackReason = null;
3018
3251
  if (!verdict.allowed) {
3019
- throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3252
+ if (effectiveStrictMode && isGuardFailureEligibleForLocalFallback(verdict.reason)) {
3253
+ localFallbackApplied = true;
3254
+ localFallbackReason = verdict.reason ?? "guard_unreachable";
3255
+ if (sdkLocalScanMs === 0) {
3256
+ const fallback = await this.applyLocalPolicyChecks({
3257
+ input: maskedText,
3258
+ systemId,
3259
+ stream,
3260
+ capabilityConfig,
3261
+ apiKey: effectiveApiKey,
3262
+ clientEventId,
3263
+ sdkConfigFetchMs,
3264
+ runPromptInjectionCheck: true
3265
+ });
3266
+ maskedText = fallback.sanitizedInput;
3267
+ sdkLocalScanMs = fallback.sdkLocalScanMs;
3268
+ }
3269
+ } else {
3270
+ throw new SecurityBlockError(verdict.reason ?? "guard_denied");
3271
+ }
3272
+ }
3273
+ const currentRequestInput = adapter.extractInput(maskedReq);
3274
+ if (maskedText !== currentRequestInput) {
3275
+ maskedReq = this.withMaskedOpenAIRequest(
3276
+ req,
3277
+ maskedText
3278
+ );
3279
+ const nextCreateArgs = [...normalizedCreateArgs];
3280
+ nextCreateArgs[0] = maskedReq;
3281
+ createArgs = nextCreateArgs;
3020
3282
  }
3021
3283
  const canonicalClientEventId = typeof verdict.client_event_id === "string" && isUuidLike2(verdict.client_event_id) ? verdict.client_event_id : clientEventId;
3022
3284
  const guardEventId = typeof verdict.guard_event_id === "string" && verdict.guard_event_id.length > 0 ? verdict.guard_event_id : null;
@@ -3067,12 +3329,19 @@ var AgentID = class {
3067
3329
  simulated_decision: verdict.simulated_decision ?? null,
3068
3330
  simulated_output_decision: isShadowMode && result.outputMasked ? "masked" : "allowed",
3069
3331
  response_streamed: true,
3332
+ sdk_local_fallback_applied: localFallbackApplied,
3333
+ sdk_local_fallback_reason: localFallbackReason,
3070
3334
  guard_latency_ms: guardLatencyMs,
3071
3335
  model_latency_ms: modelLatencyMs2,
3072
3336
  total_pipeline_latency_ms: totalPipelineLatencyMs2,
3073
3337
  guard_event_id: guardEventId,
3074
3338
  client_event_id: canonicalClientEventId,
3075
- transparency
3339
+ transparency,
3340
+ ...buildSdkTimingMetadata({
3341
+ sdkConfigFetchMs,
3342
+ sdkLocalScanMs,
3343
+ sdkGuardMs: guardLatencyMs
3344
+ })
3076
3345
  },
3077
3346
  client_capabilities: this.buildClientCapabilities(
3078
3347
  "openai",
@@ -3126,12 +3395,19 @@ var AgentID = class {
3126
3395
  simulated_decision: verdict.simulated_decision ?? null,
3127
3396
  simulated_output_decision: isShadowMode && wrappedCompletion.outputMasked ? "masked" : "allowed",
3128
3397
  response_streamed: false,
3398
+ sdk_local_fallback_applied: localFallbackApplied,
3399
+ sdk_local_fallback_reason: localFallbackReason,
3129
3400
  guard_latency_ms: guardLatencyMs,
3130
3401
  model_latency_ms: modelLatencyMs,
3131
3402
  total_pipeline_latency_ms: totalPipelineLatencyMs,
3132
3403
  guard_event_id: guardEventId,
3133
3404
  client_event_id: canonicalClientEventId,
3134
- transparency
3405
+ transparency,
3406
+ ...buildSdkTimingMetadata({
3407
+ sdkConfigFetchMs,
3408
+ sdkLocalScanMs,
3409
+ sdkGuardMs: guardLatencyMs
3410
+ })
3135
3411
  },
3136
3412
  client_capabilities: this.buildClientCapabilities(
3137
3413
  "openai",
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TransparencyMetadata } from './agentid-B5Y1g2Ko.mjs';
2
- export { A as AgentID, D as DependencyError, G as GuardParams, a as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions, S as SecurityBlockError } from './agentid-B5Y1g2Ko.mjs';
1
+ import { T as TransparencyMetadata } from './agentid-DviYzyAM.mjs';
2
+ export { A as AgentID, D as DependencyError, G as GuardParams, a as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions, S as SecurityBlockError } from './agentid-DviYzyAM.mjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  type PIIMapping = Record<string, string>;
@@ -43,6 +43,7 @@ type InjectionScanParams = {
43
43
  systemId?: string;
44
44
  eventId?: string;
45
45
  clientEventId?: string;
46
+ telemetryMetadata?: Record<string, unknown>;
46
47
  };
47
48
  declare function scanWithRegex(prompt: string): string | null;
48
49
  declare class InjectionScanner {
@@ -55,6 +56,7 @@ declare class InjectionScanner {
55
56
  systemId?: string;
56
57
  eventId?: string;
57
58
  clientEventId?: string;
59
+ telemetryMetadata?: Record<string, unknown>;
58
60
  }): Promise<void>;
59
61
  scan(params: InjectionScanParams): Promise<void>;
60
62
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TransparencyMetadata } from './agentid-B5Y1g2Ko.js';
2
- export { A as AgentID, D as DependencyError, G as GuardParams, a as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions, S as SecurityBlockError } from './agentid-B5Y1g2Ko.js';
1
+ import { T as TransparencyMetadata } from './agentid-DviYzyAM.js';
2
+ export { A as AgentID, D as DependencyError, G as GuardParams, a as GuardResponse, L as LogParams, P as PreparedInput, R as RequestOptions, S as SecurityBlockError } from './agentid-DviYzyAM.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
 
5
5
  type PIIMapping = Record<string, string>;
@@ -43,6 +43,7 @@ type InjectionScanParams = {
43
43
  systemId?: string;
44
44
  eventId?: string;
45
45
  clientEventId?: string;
46
+ telemetryMetadata?: Record<string, unknown>;
46
47
  };
47
48
  declare function scanWithRegex(prompt: string): string | null;
48
49
  declare class InjectionScanner {
@@ -55,6 +56,7 @@ declare class InjectionScanner {
55
56
  systemId?: string;
56
57
  eventId?: string;
57
58
  clientEventId?: string;
59
+ telemetryMetadata?: Record<string, unknown>;
58
60
  }): Promise<void>;
59
61
  scan(params: InjectionScanParams): Promise<void>;
60
62
  }