agentid-sdk 0.1.22 → 0.1.23

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/README.md CHANGED
@@ -205,6 +205,56 @@ By default, AgentID is designed to keep your application running if the AgentID
205
205
  - Local prompt-injection heuristics are enabled only when dashboard policy enables injection blocking (`block_on_heuristic` / legacy injection flags). `strictMode` does not force local heuristic blocking.
206
206
  - Ingest retries transient failures (5xx/429) and logs warnings if persistence fails.
207
207
 
208
+ ### Event Identity Model
209
+
210
+ For consistent lifecycle correlation in Activity/Prompts, use this model:
211
+
212
+ - `client_event_id`: external correlation ID for one end-to-end action.
213
+ - `guard_event_id`: ID of the preflight guard event returned by `guard()`.
214
+ - `event_id` on `log()`: idempotency key for ingest. In the JS SDK it is canonicalized to `client_event_id` for stable one-row lifecycle updates.
215
+
216
+ SDK behavior:
217
+
218
+ - `guard()` sends `client_event_id` and returns canonical `client_event_id` + `guard_event_id`.
219
+ - `log()` sends:
220
+ - `event_id = canonical client_event_id`
221
+ - `metadata.client_event_id`
222
+ - `metadata.guard_event_id` (when available from wrappers/callbacks)
223
+ - `x-correlation-id = client_event_id`
224
+ - SDK requests include `x-agentid-sdk-version` for telemetry/version diagnostics.
225
+
226
+ This keeps Guard + Complete linked under one correlation key while preserving internal event linkage in the dashboard.
227
+
228
+ ### Policy-Pack Runtime Telemetry
229
+
230
+ When the backend uses compiled policy packs, runtime metadata includes:
231
+
232
+ - `policy_pack_version`: active compiled artifact version.
233
+ - `policy_pack_fallback`: `true` means fallback detector path was used.
234
+ - `policy_pack_details`: optional diagnostic detail for fallback/decision trace.
235
+
236
+ Latency interpretation:
237
+
238
+ - Activity `Latency (ms)` maps to synchronous processing (`processing_time_ms`).
239
+ - Async AI audit time is separate (`ai_audit_duration_ms`) and can be higher.
240
+ - First request after warm-up boundaries can be slower than steady-state requests.
241
+
242
+ ### Monorepo QA Commands (Maintainers)
243
+
244
+ If you are validating runtime in the AgentID monorepo:
245
+
246
+ ```bash
247
+ npm run qa:policy-pack-bootstrap -- --base-url=http://127.0.0.1:3000/api/v1 --system-id=<SYSTEM_UUID>
248
+ npm run bench:policy-pack-hotpath
249
+ ```
250
+
251
+ PowerShell diagnostics:
252
+
253
+ ```powershell
254
+ powershell -ExecutionPolicy Bypass -File .\scripts\qa\run-guard-diagnostic.ps1 -BaseUrl http://127.0.0.1:3000/api/v1 -ApiKey $env:AGENTID_API_KEY -SystemId $env:AGENTID_SYSTEM_ID -SkipBenchmark
255
+ powershell -ExecutionPolicy Bypass -File .\scripts\qa\run-ai-label-audit-check.ps1 -BaseUrl http://127.0.0.1:3000/api/v1 -ApiKey $env:AGENTID_API_KEY -SystemId $env:AGENTID_SYSTEM_ID -Model gpt-4o-mini
256
+ ```
257
+
208
258
  ## 7. Security & Compliance
209
259
 
210
260
  - Optional local PII masking and local policy enforcement before model dispatch.
@@ -970,11 +970,87 @@ var PHONE_CONTEXT_RE = new RegExp(
970
970
  `(?:^|[^\\p{L}])(?:${PHONE_CONTEXT_KEYWORDS.map(escapeRegex).join("|")})(?:$|[^\\p{L}])`,
971
971
  "iu"
972
972
  );
973
+ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
974
+ "write",
975
+ "code",
976
+ "script",
977
+ "query",
978
+ "curl",
979
+ "http",
980
+ "https",
981
+ "import",
982
+ "python",
983
+ "javascript",
984
+ "typescript",
985
+ "node",
986
+ "bash",
987
+ "powershell",
988
+ "shell",
989
+ "command",
990
+ "example",
991
+ "demo",
992
+ "developer",
993
+ "mode",
994
+ "system",
995
+ "prompt",
996
+ "policy",
997
+ "security",
998
+ "instructions",
999
+ "instruction",
1000
+ "rules",
1001
+ "rule",
1002
+ "json",
1003
+ "output",
1004
+ "input",
1005
+ "database",
1006
+ "sql",
1007
+ "mongo",
1008
+ "openai",
1009
+ "agentid",
1010
+ "risk",
1011
+ "score",
1012
+ "summary"
1013
+ ]);
1014
+ var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
1015
+ var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
973
1016
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
974
1017
  const start = Math.max(0, matchStartIndex - windowSize);
975
1018
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
976
1019
  return PHONE_CONTEXT_RE.test(windowLower);
977
1020
  }
1021
+ function normalizePersonWord(value) {
1022
+ return value.normalize("NFD").replace(/\p{M}+/gu, "").toLowerCase();
1023
+ }
1024
+ function buildContextWindow(source, index, length) {
1025
+ const start = Math.max(0, index - 28);
1026
+ const end = Math.min(source.length, index + length + 28);
1027
+ return source.slice(start, end);
1028
+ }
1029
+ function isTechnicalContext(contextWindow) {
1030
+ return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1031
+ }
1032
+ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1033
+ const words = candidate.trim().split(/\s+/);
1034
+ if (words.length !== 2) {
1035
+ return false;
1036
+ }
1037
+ if (isTechnicalContext(contextWindow)) {
1038
+ return false;
1039
+ }
1040
+ for (const rawWord of words) {
1041
+ const normalized = normalizePersonWord(rawWord);
1042
+ if (normalized.length < 2) {
1043
+ return false;
1044
+ }
1045
+ if (PERSON_NAME_STOPWORDS.has(normalized)) {
1046
+ return false;
1047
+ }
1048
+ if (!/^\p{L}[\p{L}'-]+$/u.test(rawWord)) {
1049
+ return false;
1050
+ }
1051
+ }
1052
+ return true;
1053
+ }
978
1054
  var PIIManager = class {
979
1055
  /**
980
1056
  * Reversible local-first masking using <TYPE_INDEX> placeholders.
@@ -1019,7 +1095,12 @@ var PIIManager = class {
1019
1095
  const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1020
1096
  for (const m of text.matchAll(personRe)) {
1021
1097
  if (m.index == null) continue;
1022
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PERSON", text: m[0] });
1098
+ const candidate = m[0];
1099
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1100
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1101
+ continue;
1102
+ }
1103
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1023
1104
  }
1024
1105
  const nationalIdMatches = detectNationalIdentifiers(text, {
1025
1106
  deadlineMs: defaultScanDeadlineMs,
@@ -1090,15 +1171,15 @@ var DE_STOPWORDS = /* @__PURE__ */ new Set(["bitte", "anweisung", "system", "reg
1090
1171
  var HEURISTIC_RULES = [
1091
1172
  {
1092
1173
  name: "heuristic_combo_ignore_instructions",
1093
- re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,120}\b(instruction(?:s)?|previous|system|developer|policy|rules|guardrails|safety|instrukce|pokyny|pravidla|syst[eé]m|bezpecnost|politika)\b/i
1174
+ re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,160}\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b/i
1094
1175
  },
1095
1176
  {
1096
1177
  name: "heuristic_combo_instruction_override_reverse",
1097
- re: /\b(instruction(?:s)?|previous|system|developer|policy|rules|guardrails|safety|instrukce|pokyny|pravidla|syst[eé]m|bezpecnost|politika)\b[\s\S]{0,120}\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b/i
1178
+ re: /\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b[\s\S]{0,160}\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b/i
1098
1179
  },
1099
1180
  {
1100
1181
  name: "heuristic_combo_exfil_system_prompt",
1101
- re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,140}\b(system prompt|system instruction(?:s)?|developer message|hidden prompt|internal instruction(?:s)?|policy|guardrails|intern[ií] instrukce)\b/i
1182
+ re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,180}\b(system prompt|system instruction(?:s)?|developer message|hidden prompt|internal instruction(?:s)?|policy|guardrails|interni instrukce|systemove nastaveni)\b/i
1102
1183
  },
1103
1184
  {
1104
1185
  name: "heuristic_role_prefix_system_developer",
@@ -1107,6 +1188,14 @@ var HEURISTIC_RULES = [
1107
1188
  {
1108
1189
  name: "heuristic_delimiter_system_prompt",
1109
1190
  re: /\b(begin|start)\s+(system|developer)\s+prompt\b|\bend\s+(system|developer)\s+prompt\b/i
1191
+ },
1192
+ {
1193
+ name: "heuristic_developer_mode_override",
1194
+ re: /\b(developer\s*mode|dev\s*mode)\b[\s\S]{0,200}\b(ignore|bypass|disable|override|ignoruj|obejdi|zapomen)\b/i
1195
+ },
1196
+ {
1197
+ name: "heuristic_czech_injection_phrase",
1198
+ re: /\b(zapomen|ignoruj)\b[\s\S]{0,220}\b(predchozi\s+instrukce|bezpecnostni\s+pravidla|systemove\s+nastaveni)\b/i
1110
1199
  }
1111
1200
  ];
1112
1201
  var scannerSingleton = null;
@@ -1157,6 +1246,9 @@ ${input.slice(-WINDOW_SLICE_SIZE)}`;
1157
1246
  [...]
1158
1247
  ${input.slice(tailStart)}`;
1159
1248
  }
1249
+ function normalizeForHeuristics(input) {
1250
+ return input.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, " ").trim();
1251
+ }
1160
1252
  function scoreStopwords(tokens, stopwords) {
1161
1253
  let score = 0;
1162
1254
  for (const token of tokens) {
@@ -1199,9 +1291,10 @@ function findRegexMatch(prompt) {
1199
1291
  if (!prompt) {
1200
1292
  return null;
1201
1293
  }
1294
+ const normalizedPrompt = normalizeForHeuristics(prompt);
1202
1295
  for (const rule of HEURISTIC_RULES) {
1203
1296
  try {
1204
- const match = rule.re.exec(prompt);
1297
+ const match = rule.re.exec(normalizedPrompt);
1205
1298
  if (match && typeof match[0] === "string" && match[0].trim()) {
1206
1299
  return {
1207
1300
  rule: rule.name,
@@ -1462,7 +1555,7 @@ function getInjectionScanner() {
1462
1555
 
1463
1556
  // src/sdk-version.ts
1464
1557
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
1465
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.22".trim().length > 0 ? "js-0.1.22" : FALLBACK_SDK_VERSION;
1558
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.23".trim().length > 0 ? "js-0.1.23" : FALLBACK_SDK_VERSION;
1466
1559
 
1467
1560
  // src/local-security-enforcer.ts
1468
1561
  var DEFAULT_FAIL_OPEN_CONFIG = {
@@ -1476,6 +1569,14 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1476
1569
  block_toxicity: false
1477
1570
  };
1478
1571
  var SQL_DATABASE_ACCESS_PATTERN = /\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER)\b[\s\S]+?\b(FROM|INTO|TABLE|DATABASE|VIEW|INDEX)\b/i;
1572
+ var NOSQL_DATABASE_ACCESS_PATTERNS = [
1573
+ /\bdb\.[A-Za-z_][A-Za-z0-9_]*\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
1574
+ /\b(collection|mongodb)\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
1575
+ /\b\$where\b/i,
1576
+ /\b\$expr\b/i,
1577
+ /\b\$regex\b/i,
1578
+ /\bMongoClient\.connect\s*\(/i
1579
+ ];
1479
1580
  var PYTHON_GENERAL_RCE_PATTERN = /(import\s+(os|sys|subprocess)|from\s+(os|sys|subprocess)\s+import|exec\s*\(|eval\s*\(|__import__)/i;
1480
1581
  var SHELL_BASH_RCE_PATTERN = /(wget\s+|curl\s+|rm\s+-rf|chmod\s+\+x|cat\s+\/etc\/passwd|\/bin\/sh|\/bin\/bash)/i;
1481
1582
  var JAVASCRIPT_RCE_PATTERN = /(new\s+Function\(|process\.env|child_process)/i;
@@ -1489,8 +1590,15 @@ var SecurityPolicyViolationError = class extends Error {
1489
1590
  }
1490
1591
  };
1491
1592
  function detectCapabilityViolation(text, config) {
1492
- if (config.block_db_access && SQL_DATABASE_ACCESS_PATTERN.test(text)) {
1493
- return "SQL_INJECTION_ATTEMPT";
1593
+ if (config.block_db_access) {
1594
+ if (SQL_DATABASE_ACCESS_PATTERN.test(text)) {
1595
+ return "SQL_INJECTION_ATTEMPT";
1596
+ }
1597
+ for (const pattern of NOSQL_DATABASE_ACCESS_PATTERNS) {
1598
+ if (pattern.test(text)) {
1599
+ return "SQL_INJECTION_ATTEMPT";
1600
+ }
1601
+ }
1494
1602
  }
1495
1603
  if (config.block_code_execution && (PYTHON_GENERAL_RCE_PATTERN.test(text) || SHELL_BASH_RCE_PATTERN.test(text) || JAVASCRIPT_RCE_PATTERN.test(text))) {
1496
1604
  return "RCE_ATTEMPT";
@@ -2415,13 +2523,18 @@ var AgentID = class {
2415
2523
  const metadata = {
2416
2524
  ...params.metadata ?? {}
2417
2525
  };
2526
+ const metadataClientEventId = typeof metadata.client_event_id === "string" && isUuidLike(metadata.client_event_id) ? metadata.client_event_id : null;
2527
+ const canonicalClientEventId = metadataClientEventId ?? eventId;
2528
+ if (!metadataClientEventId) {
2529
+ metadata.client_event_id = canonicalClientEventId;
2530
+ }
2418
2531
  if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2419
2532
  metadata.agentid_base_url = this.baseUrl;
2420
2533
  }
2421
2534
  void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2422
2535
  const payload = {
2423
2536
  ...params,
2424
- event_id: eventId,
2537
+ event_id: canonicalClientEventId,
2425
2538
  timestamp,
2426
2539
  input: sanitizeIngestText(params.input),
2427
2540
  output: sanitizeIngestText(params.output),
@@ -2438,6 +2551,7 @@ var AgentID = class {
2438
2551
  headers: {
2439
2552
  "Content-Type": "application/json",
2440
2553
  "x-agentid-api-key": effectiveApiKey,
2554
+ "x-correlation-id": canonicalClientEventId,
2441
2555
  "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER
2442
2556
  },
2443
2557
  body: JSON.stringify(payload),
package/dist/index.js CHANGED
@@ -84,7 +84,7 @@ var OpenAIAdapter = class {
84
84
 
85
85
  // src/sdk-version.ts
86
86
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
87
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.22".trim().length > 0 ? "js-0.1.22" : FALLBACK_SDK_VERSION;
87
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.23".trim().length > 0 ? "js-0.1.23" : FALLBACK_SDK_VERSION;
88
88
 
89
89
  // src/pii-national-identifiers.ts
90
90
  var MAX_CANDIDATES_PER_RULE = 256;
@@ -1016,11 +1016,87 @@ var PHONE_CONTEXT_RE = new RegExp(
1016
1016
  `(?:^|[^\\p{L}])(?:${PHONE_CONTEXT_KEYWORDS.map(escapeRegex).join("|")})(?:$|[^\\p{L}])`,
1017
1017
  "iu"
1018
1018
  );
1019
+ var PERSON_NAME_STOPWORDS = /* @__PURE__ */ new Set([
1020
+ "write",
1021
+ "code",
1022
+ "script",
1023
+ "query",
1024
+ "curl",
1025
+ "http",
1026
+ "https",
1027
+ "import",
1028
+ "python",
1029
+ "javascript",
1030
+ "typescript",
1031
+ "node",
1032
+ "bash",
1033
+ "powershell",
1034
+ "shell",
1035
+ "command",
1036
+ "example",
1037
+ "demo",
1038
+ "developer",
1039
+ "mode",
1040
+ "system",
1041
+ "prompt",
1042
+ "policy",
1043
+ "security",
1044
+ "instructions",
1045
+ "instruction",
1046
+ "rules",
1047
+ "rule",
1048
+ "json",
1049
+ "output",
1050
+ "input",
1051
+ "database",
1052
+ "sql",
1053
+ "mongo",
1054
+ "openai",
1055
+ "agentid",
1056
+ "risk",
1057
+ "score",
1058
+ "summary"
1059
+ ]);
1060
+ var TECHNICAL_CONTEXT_WORD_REGEX = /\b(?:curl|http|https|import|python|javascript|typescript|sql|nosql|mongo|database|query|script|code|os\.system|eval|exec|node|npm|api|endpoint|regex|json|xml|yaml|bash|powershell)\b/i;
1061
+ var TECHNICAL_CONTEXT_SYMBOL_REGEX = /:\/\/|`|\{|\}|\[|\]|\(|\)|;|\$|=>|::|\/\//;
1019
1062
  function hasPhoneContext(text, matchStartIndex, windowSize = 50) {
1020
1063
  const start = Math.max(0, matchStartIndex - windowSize);
1021
1064
  const windowLower = text.slice(start, matchStartIndex).toLowerCase();
1022
1065
  return PHONE_CONTEXT_RE.test(windowLower);
1023
1066
  }
1067
+ function normalizePersonWord(value) {
1068
+ return value.normalize("NFD").replace(/\p{M}+/gu, "").toLowerCase();
1069
+ }
1070
+ function buildContextWindow(source, index, length) {
1071
+ const start = Math.max(0, index - 28);
1072
+ const end = Math.min(source.length, index + length + 28);
1073
+ return source.slice(start, end);
1074
+ }
1075
+ function isTechnicalContext(contextWindow) {
1076
+ return TECHNICAL_CONTEXT_WORD_REGEX.test(contextWindow) || TECHNICAL_CONTEXT_SYMBOL_REGEX.test(contextWindow);
1077
+ }
1078
+ function isLikelyPersonNameCandidate(candidate, contextWindow) {
1079
+ const words = candidate.trim().split(/\s+/);
1080
+ if (words.length !== 2) {
1081
+ return false;
1082
+ }
1083
+ if (isTechnicalContext(contextWindow)) {
1084
+ return false;
1085
+ }
1086
+ for (const rawWord of words) {
1087
+ const normalized = normalizePersonWord(rawWord);
1088
+ if (normalized.length < 2) {
1089
+ return false;
1090
+ }
1091
+ if (PERSON_NAME_STOPWORDS.has(normalized)) {
1092
+ return false;
1093
+ }
1094
+ if (!/^\p{L}[\p{L}'-]+$/u.test(rawWord)) {
1095
+ return false;
1096
+ }
1097
+ }
1098
+ return true;
1099
+ }
1024
1100
  var PIIManager = class {
1025
1101
  /**
1026
1102
  * Reversible local-first masking using <TYPE_INDEX> placeholders.
@@ -1065,7 +1141,12 @@ var PIIManager = class {
1065
1141
  const personRe = /(?<!\p{L})\p{Lu}\p{Ll}{2,}\s+\p{Lu}\p{Ll}{2,}(?!\p{L})/gu;
1066
1142
  for (const m of text.matchAll(personRe)) {
1067
1143
  if (m.index == null) continue;
1068
- detections.push({ start: m.index, end: m.index + m[0].length, type: "PERSON", text: m[0] });
1144
+ const candidate = m[0];
1145
+ const contextWindow = buildContextWindow(text, m.index, candidate.length);
1146
+ if (!isLikelyPersonNameCandidate(candidate, contextWindow)) {
1147
+ continue;
1148
+ }
1149
+ detections.push({ start: m.index, end: m.index + candidate.length, type: "PERSON", text: candidate });
1069
1150
  }
1070
1151
  const nationalIdMatches = detectNationalIdentifiers(text, {
1071
1152
  deadlineMs: defaultScanDeadlineMs,
@@ -1126,6 +1207,14 @@ var DEFAULT_FAIL_OPEN_CONFIG = {
1126
1207
  block_toxicity: false
1127
1208
  };
1128
1209
  var SQL_DATABASE_ACCESS_PATTERN = /\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|ALTER)\b[\s\S]+?\b(FROM|INTO|TABLE|DATABASE|VIEW|INDEX)\b/i;
1210
+ var NOSQL_DATABASE_ACCESS_PATTERNS = [
1211
+ /\bdb\.[A-Za-z_][A-Za-z0-9_]*\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
1212
+ /\b(collection|mongodb)\.(find|findOne|aggregate|updateOne|updateMany|deleteOne|deleteMany|insertOne|insertMany)\s*\(/i,
1213
+ /\b\$where\b/i,
1214
+ /\b\$expr\b/i,
1215
+ /\b\$regex\b/i,
1216
+ /\bMongoClient\.connect\s*\(/i
1217
+ ];
1129
1218
  var PYTHON_GENERAL_RCE_PATTERN = /(import\s+(os|sys|subprocess)|from\s+(os|sys|subprocess)\s+import|exec\s*\(|eval\s*\(|__import__)/i;
1130
1219
  var SHELL_BASH_RCE_PATTERN = /(wget\s+|curl\s+|rm\s+-rf|chmod\s+\+x|cat\s+\/etc\/passwd|\/bin\/sh|\/bin\/bash)/i;
1131
1220
  var JAVASCRIPT_RCE_PATTERN = /(new\s+Function\(|process\.env|child_process)/i;
@@ -1139,8 +1228,15 @@ var SecurityPolicyViolationError = class extends Error {
1139
1228
  }
1140
1229
  };
1141
1230
  function detectCapabilityViolation(text, config) {
1142
- if (config.block_db_access && SQL_DATABASE_ACCESS_PATTERN.test(text)) {
1143
- return "SQL_INJECTION_ATTEMPT";
1231
+ if (config.block_db_access) {
1232
+ if (SQL_DATABASE_ACCESS_PATTERN.test(text)) {
1233
+ return "SQL_INJECTION_ATTEMPT";
1234
+ }
1235
+ for (const pattern of NOSQL_DATABASE_ACCESS_PATTERNS) {
1236
+ if (pattern.test(text)) {
1237
+ return "SQL_INJECTION_ATTEMPT";
1238
+ }
1239
+ }
1144
1240
  }
1145
1241
  if (config.block_code_execution && (PYTHON_GENERAL_RCE_PATTERN.test(text) || SHELL_BASH_RCE_PATTERN.test(text) || JAVASCRIPT_RCE_PATTERN.test(text))) {
1146
1242
  return "RCE_ATTEMPT";
@@ -1473,15 +1569,15 @@ var DE_STOPWORDS = /* @__PURE__ */ new Set(["bitte", "anweisung", "system", "reg
1473
1569
  var HEURISTIC_RULES = [
1474
1570
  {
1475
1571
  name: "heuristic_combo_ignore_instructions",
1476
- re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,120}\b(instruction(?:s)?|previous|system|developer|policy|rules|guardrails|safety|instrukce|pokyny|pravidla|syst[eé]m|bezpecnost|politika)\b/i
1572
+ re: /\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b[\s\S]{0,160}\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b/i
1477
1573
  },
1478
1574
  {
1479
1575
  name: "heuristic_combo_instruction_override_reverse",
1480
- re: /\b(instruction(?:s)?|previous|system|developer|policy|rules|guardrails|safety|instrukce|pokyny|pravidla|syst[eé]m|bezpecnost|politika)\b[\s\S]{0,120}\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b/i
1576
+ re: /\b(instruction(?:s)?|previous|system|developer|policy|rules?|guardrails|safety|instrukce|pokyny|pravidla|systemove?|bezpecnost(?:ni)?|politika)\b[\s\S]{0,160}\b(ignore|disregard|forget|override|bypass|disable|jailbreak|dan|ignoruj|zapomen|obejdi|prepis)\b/i
1481
1577
  },
1482
1578
  {
1483
1579
  name: "heuristic_combo_exfil_system_prompt",
1484
- re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,140}\b(system prompt|system instruction(?:s)?|developer message|hidden prompt|internal instruction(?:s)?|policy|guardrails|intern[ií] instrukce)\b/i
1580
+ re: /\b(show|reveal|print|dump|leak|display|expose|tell|extract|ukaz|zobraz|vypis|odhal|prozrad)\b[\s\S]{0,180}\b(system prompt|system instruction(?:s)?|developer message|hidden prompt|internal instruction(?:s)?|policy|guardrails|interni instrukce|systemove nastaveni)\b/i
1485
1581
  },
1486
1582
  {
1487
1583
  name: "heuristic_role_prefix_system_developer",
@@ -1490,6 +1586,14 @@ var HEURISTIC_RULES = [
1490
1586
  {
1491
1587
  name: "heuristic_delimiter_system_prompt",
1492
1588
  re: /\b(begin|start)\s+(system|developer)\s+prompt\b|\bend\s+(system|developer)\s+prompt\b/i
1589
+ },
1590
+ {
1591
+ name: "heuristic_developer_mode_override",
1592
+ re: /\b(developer\s*mode|dev\s*mode)\b[\s\S]{0,200}\b(ignore|bypass|disable|override|ignoruj|obejdi|zapomen)\b/i
1593
+ },
1594
+ {
1595
+ name: "heuristic_czech_injection_phrase",
1596
+ re: /\b(zapomen|ignoruj)\b[\s\S]{0,220}\b(predchozi\s+instrukce|bezpecnostni\s+pravidla|systemove\s+nastaveni)\b/i
1493
1597
  }
1494
1598
  ];
1495
1599
  var scannerSingleton = null;
@@ -1540,6 +1644,9 @@ ${input.slice(-WINDOW_SLICE_SIZE)}`;
1540
1644
  [...]
1541
1645
  ${input.slice(tailStart)}`;
1542
1646
  }
1647
+ function normalizeForHeuristics(input) {
1648
+ return input.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/\s+/g, " ").trim();
1649
+ }
1543
1650
  function scoreStopwords(tokens, stopwords) {
1544
1651
  let score = 0;
1545
1652
  for (const token of tokens) {
@@ -1582,9 +1689,10 @@ function findRegexMatch(prompt) {
1582
1689
  if (!prompt) {
1583
1690
  return null;
1584
1691
  }
1692
+ const normalizedPrompt = normalizeForHeuristics(prompt);
1585
1693
  for (const rule of HEURISTIC_RULES) {
1586
1694
  try {
1587
- const match = rule.re.exec(prompt);
1695
+ const match = rule.re.exec(normalizedPrompt);
1588
1696
  if (match && typeof match[0] === "string" && match[0].trim()) {
1589
1697
  return {
1590
1698
  rule: rule.name,
@@ -2457,13 +2565,18 @@ var AgentID = class {
2457
2565
  const metadata = {
2458
2566
  ...params.metadata ?? {}
2459
2567
  };
2568
+ const metadataClientEventId = typeof metadata.client_event_id === "string" && isUuidLike(metadata.client_event_id) ? metadata.client_event_id : null;
2569
+ const canonicalClientEventId = metadataClientEventId ?? eventId;
2570
+ if (!metadataClientEventId) {
2571
+ metadata.client_event_id = canonicalClientEventId;
2572
+ }
2460
2573
  if (!Object.prototype.hasOwnProperty.call(metadata, "agentid_base_url")) {
2461
2574
  metadata.agentid_base_url = this.baseUrl;
2462
2575
  }
2463
2576
  void this.getCapabilityConfig(false, { apiKey: effectiveApiKey }).catch(() => void 0);
2464
2577
  const payload = {
2465
2578
  ...params,
2466
- event_id: eventId,
2579
+ event_id: canonicalClientEventId,
2467
2580
  timestamp,
2468
2581
  input: sanitizeIngestText(params.input),
2469
2582
  output: sanitizeIngestText(params.output),
@@ -2480,6 +2593,7 @@ var AgentID = class {
2480
2593
  headers: {
2481
2594
  "Content-Type": "application/json",
2482
2595
  "x-agentid-api-key": effectiveApiKey,
2596
+ "x-correlation-id": canonicalClientEventId,
2483
2597
  "X-AgentID-SDK-Version": AGENTID_SDK_VERSION_HEADER
2484
2598
  },
2485
2599
  body: JSON.stringify(payload),
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  SecurityBlockError,
7
7
  getInjectionScanner,
8
8
  scanWithRegex
9
- } from "./chunk-FVTL572H.mjs";
9
+ } from "./chunk-4FSEYTEC.mjs";
10
10
  export {
11
11
  AgentID,
12
12
  InjectionScanner,
package/dist/langchain.js CHANGED
@@ -27,7 +27,7 @@ var import_base = require("@langchain/core/callbacks/base");
27
27
 
28
28
  // src/sdk-version.ts
29
29
  var FALLBACK_SDK_VERSION = "js-0.0.0-dev";
30
- var AGENTID_SDK_VERSION_HEADER = "js-0.1.22".trim().length > 0 ? "js-0.1.22" : FALLBACK_SDK_VERSION;
30
+ var AGENTID_SDK_VERSION_HEADER = "js-0.1.23".trim().length > 0 ? "js-0.1.23" : FALLBACK_SDK_VERSION;
31
31
 
32
32
  // src/pii-national-identifiers.ts
33
33
  var REGION_ANCHORS = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SecurityBlockError
3
- } from "./chunk-FVTL572H.mjs";
3
+ } from "./chunk-4FSEYTEC.mjs";
4
4
 
5
5
  // src/langchain.ts
6
6
  import { BaseCallbackHandler } from "@langchain/core/callbacks/base";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentid-sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "AgentID JavaScript/TypeScript SDK for guard, ingest, tracing, and analytics.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://agentid.ai",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@langchain/core": "^0.3.0 || ^1.0.0",
43
- "openai": "^4.0.0 || ^5.0.0 || ^6.0.0",
44
- "langchain": "^0.1.0"
43
+ "langchain": "^0.1.0",
44
+ "openai": "^4.0.0 || ^5.0.0 || ^6.0.0"
45
45
  },
46
46
  "peerDependenciesMeta": {
47
47
  "@langchain/core": {
@@ -54,5 +54,8 @@
54
54
  "devDependencies": {
55
55
  "tsup": "^8.3.5",
56
56
  "typescript": "^5.0.0"
57
+ },
58
+ "dependencies": {
59
+ "agentid-sdk": "^0.1.21"
57
60
  }
58
61
  }