qati-sdk 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var dotenv = require('dotenv');
4
4
  var zod = require('zod');
5
5
  var axios = require('axios');
6
+ var crypto = require('crypto');
6
7
 
7
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
9
 
@@ -205,36 +206,35 @@ var parseDetail = (response) => {
205
206
  const { headers, status, statusText, data } = response;
206
207
  const requestId = headers["x-request-id"] ?? headers["X-Request-Id"];
207
208
  let message = statusText ?? "";
208
- try {
209
- const body = data;
210
- if (typeof body === "object") {
211
- const msg = body.detail || body.message;
212
- message = typeof msg === "string" ? msg : JSON.stringify(msg);
213
- }
214
- } catch {
215
- message = statusText;
216
- }
217
- return {
209
+ const initialErrorDetail = {
218
210
  status_code: status,
219
211
  message,
220
212
  request_id: requestId
221
213
  };
214
+ if (!data || typeof data !== "object") return initialErrorDetail;
215
+ const body = data;
216
+ const errorContent = body.detail ?? body.message;
217
+ if (errorContent === void 0 || errorContent === null)
218
+ return initialErrorDetail;
219
+ try {
220
+ message = typeof errorContent === "string" ? errorContent : JSON.stringify(errorContent) ?? statusText;
221
+ } catch {
222
+ message = statusText;
223
+ }
224
+ return { ...initialErrorDetail, message };
222
225
  };
223
226
  var qatiApiErrorFromRequestFailure = (err) => {
224
- if (axios__default.default.isAxiosError(err)) {
225
- const ax = err;
226
- if (ax.response) {
227
- const resp = ax.response;
228
- const ErrorCls = STATUS_ERROR_MAP[resp.status] ?? (resp.status >= 500 ? QatiServerError : QatiAPIError);
229
- return new ErrorCls(parseDetail(resp));
230
- }
227
+ if (!axios__default.default.isAxiosError(err))
228
+ throw new TypeError(`Expected Axios error, got ${typeof err}`);
229
+ if (!err.response)
231
230
  return new QatiAPIError({
232
231
  status_code: 0,
233
- message: ax.message || String(ax.code ?? "Axios request error"),
232
+ message: err.message || String(err.code ?? "Axios request error"),
234
233
  request_id: null
235
234
  });
236
- }
237
- throw new TypeError(`Expected Axios error, got ${typeof err}`);
235
+ const { response } = err;
236
+ const ErrorCls = STATUS_ERROR_MAP[response.status] ?? (response.status >= 500 ? QatiServerError : QatiAPIError);
237
+ return new ErrorCls(parseDetail(response));
238
238
  };
239
239
 
240
240
  // src/http/http-client.ts
@@ -309,16 +309,21 @@ var HttpClient = class {
309
309
  headers: resolvedHeaders,
310
310
  data: options.data
311
311
  };
312
- if (!options.retry) {
313
- const { data } = await instance.request(req);
314
- return data.data;
315
- }
312
+ if (!options.retry) return this.requestRaw(req, instance);
316
313
  const response = await this.retryRequest(
317
314
  () => instance.request(req),
318
315
  options
319
316
  );
320
317
  return response.data.data;
321
318
  }
319
+ async requestRaw(req, instance) {
320
+ try {
321
+ const { data } = await instance.request(req);
322
+ return data.data;
323
+ } catch (err) {
324
+ throw qatiApiErrorFromRequestFailure(err);
325
+ }
326
+ }
322
327
  async retryRequest(requestFn, options) {
323
328
  for (let attempt = 0; attempt <= this._config.maxRetries; attempt++) {
324
329
  try {
@@ -602,6 +607,59 @@ var ExplainResource = class {
602
607
  }
603
608
  };
604
609
 
610
+ // src/resources/mcc/mcc-evaluation-resource.ts
611
+ var EVALUATION_ENDPOINT_BASE = "/v1/mcc/evaluations";
612
+ var EVALUATE_ENDPOINT = "/v1/mcc/evaluate";
613
+ var MccEvaluationResource = class {
614
+ constructor(_http) {
615
+ this._http = _http;
616
+ }
617
+ _http;
618
+ apiName = "query_api";
619
+ /**
620
+ * Lists MCC evaluation traces (`GET /v1/mcc/evaluations`).
621
+ *
622
+ * Uses keyset pagination via `after_id` / `next_cursor`; no offset pagination.
623
+ */
624
+ async list(options) {
625
+ return this._http.request(
626
+ "GET",
627
+ EVALUATION_ENDPOINT_BASE,
628
+ {
629
+ api_name: this.apiName,
630
+ params: {
631
+ entity_key: options?.entityKey,
632
+ since: options?.since ? dateToIso8601(options.since) : void 0,
633
+ until: options?.until ? dateToIso8601(options.until) : void 0,
634
+ limit: options?.limit,
635
+ after_id: options?.afterId
636
+ }
637
+ }
638
+ );
639
+ }
640
+ /**
641
+ * Returns one MCC evaluation trace (`GET /v1/mcc/evaluations/{evaluation_id}`).
642
+ */
643
+ async get(evaluationId) {
644
+ return this._http.request(
645
+ "GET",
646
+ `${EVALUATION_ENDPOINT_BASE}/${encodeURIComponent(evaluationId)}`,
647
+ { api_name: this.apiName }
648
+ );
649
+ }
650
+ /**
651
+ * Runs MCC-Lite against the entity's latest trust state (`POST /v1/mcc/evaluate`).
652
+ *
653
+ * @throws When the entity has no trust state record (404).
654
+ */
655
+ async evaluate(entityKey) {
656
+ return this._http.request("POST", EVALUATE_ENDPOINT, {
657
+ api_name: this.apiName,
658
+ data: { entity_key: entityKey }
659
+ });
660
+ }
661
+ };
662
+
605
663
  // src/resources/quota-resource.ts
606
664
  var QuotaResource = class {
607
665
  constructor(_http) {
@@ -728,10 +786,14 @@ var WebhookResource = class {
728
786
  }
729
787
  async delete(tenantId, webhookId) {
730
788
  const instance = this._http.getClient(this.apiName);
731
- await instance.request({
732
- method: "DELETE",
733
- url: `/v1/tenants/${encodeURIComponent(tenantId)}/webhooks/${encodeURIComponent(webhookId)}`
734
- });
789
+ try {
790
+ await instance.request({
791
+ method: "DELETE",
792
+ url: `/v1/tenants/${encodeURIComponent(tenantId)}/webhooks/${encodeURIComponent(webhookId)}`
793
+ });
794
+ } catch (err) {
795
+ throw qatiApiErrorFromRequestFailure(err);
796
+ }
735
797
  }
736
798
  async test(tenantId, webhookId) {
737
799
  return this._http.request(
@@ -751,6 +813,7 @@ var Client = class extends HttpClient {
751
813
  _events;
752
814
  _webhooks;
753
815
  _quotas;
816
+ _mccEvaluation;
754
817
  /**
755
818
  * @param config - Resolved SDK configuration (typically `session.config`).
756
819
  * @param axiosInstances - Optional per-API `axios` instances; see {@link Session#createClient}.
@@ -765,6 +828,7 @@ var Client = class extends HttpClient {
765
828
  this._events = new EventResource(this);
766
829
  this._webhooks = new WebhookResource(this);
767
830
  this._quotas = new QuotaResource(this);
831
+ this._mccEvaluation = new MccEvaluationResource(this);
768
832
  }
769
833
  /**
770
834
  * Tenant API surface (credentials verification).
@@ -824,6 +888,14 @@ var Client = class extends HttpClient {
824
888
  get quotas() {
825
889
  return this._quotas;
826
890
  }
891
+ /**
892
+ * MCC evaluation trace queries.
893
+ *
894
+ * @returns {@link MccResource} for the Query API.
895
+ */
896
+ get mccEvaluation() {
897
+ return this._mccEvaluation;
898
+ }
827
899
  /**
828
900
  * Flushes the event ingestion buffer (best-effort), then shuts down the batch scheduler.
829
901
  * Call this on process shutdown so queued events are not lost.
@@ -864,6 +936,33 @@ var Session = class {
864
936
  return new Client(this._config, httpClients ?? {});
865
937
  }
866
938
  };
939
+
940
+ // src/shared/types/webhook.ts
941
+ var WebhookEvent = {
942
+ TRUST_STATE_TIER_ESCALATED: "trust_state.tier_escalated",
943
+ ADVISORY_CREATED: "advisory.created",
944
+ MCC_EVALUATION_COMPLETED: "mcc.evaluation.completed"
945
+ };
946
+
947
+ // src/shared/types/anomaly-type.ts
948
+ var ANOMALY_TYPES = [
949
+ "DEVICE_UNVERIFIED",
950
+ "NEW_DEVICE",
951
+ "RAPID_PROMPTING",
952
+ "HIGH_VOLUME_SESSION",
953
+ "ABNORMAL_RETRY_PATTERN",
954
+ "SUSPICIOUS_CADENCE",
955
+ "POLICY_ABUSE_PATTERN"
956
+ ];
957
+
958
+ // src/shared/types/device-trust-state.ts
959
+ var DEVICE_TRUST_STATES = [
960
+ "TRUSTED",
961
+ "RECOGNIZED",
962
+ "NEW",
963
+ "UNVERIFIED",
964
+ "UNKNOWN"
965
+ ];
867
966
  var fraction01 = () => zod.z.number().min(0).max(1);
868
967
  var fraction01Nullable = () => fraction01().nullable().optional();
869
968
  var nonEmptyString = () => zod.z.string().min(1);
@@ -881,6 +980,7 @@ var SIGNAL_TYPES = [
881
980
  "PROMPT_INPUT",
882
981
  "CONTEXT_INTEGRITY",
883
982
  "TOOL_CALL",
983
+ "TOOL_CALL_PROPOSED",
884
984
  "RAG_RETRIEVAL",
885
985
  "POLICY_EVENT",
886
986
  "USER_FEEDBACK",
@@ -942,7 +1042,57 @@ var RawEventRequestSchema = zod.z.object({
942
1042
 
943
1043
  // src/v1/schemas/anomaly-flag.ts
944
1044
  var AnomalyFlagSignalPayloadSchema = zod.z.object({
945
- severity: fraction01()
1045
+ severity: fraction01().describe(
1046
+ "Normalized 0\u20131 anomaly severity. Sourcing: existing detector output or rule-derived severity."
1047
+ ),
1048
+ anomaly_type: zod.z.enum(ANOMALY_TYPES).describe(
1049
+ "Semantic anomaly class (DEVICE_UNVERIFIED, NEW_DEVICE, RAPID_PROMPTING, HIGH_VOLUME_SESSION, ABNORMAL_RETRY_PATTERN, SUSPICIOUS_CADENCE, or POLICY_ABUSE_PATTERN). Sourcing: set by the detector or rule that fired."
1050
+ ),
1051
+ metric_name: zod.z.string().nullable().optional().describe(
1052
+ "Name of the measured quantity that triggered the anomaly (e.g. prompt_rate_per_min, new_device_seen). Sourcing: detector/rule output."
1053
+ ),
1054
+ metric_value: zod.z.number().nullable().optional().describe(
1055
+ "Observed value of the measured quantity. Sourcing: computed from session, device, or user events."
1056
+ ),
1057
+ threshold: zod.z.number().nullable().optional().describe(
1058
+ "Configured threshold that the metric exceeded or violated. Sourcing: engine configuration value."
1059
+ ),
1060
+ window_seconds: zod.z.number().int().min(1).nullable().optional().describe(
1061
+ "Time window over which the metric was measured. Sourcing: detector rolling-window configuration."
1062
+ ),
1063
+ device_trust_state: zod.z.enum(DEVICE_TRUST_STATES).nullable().optional().describe(
1064
+ "Device trust classification (TRUSTED, RECOGNIZED, NEW, UNVERIFIED, or UNKNOWN). Sourcing: device fingerprint or attestation service."
1065
+ ),
1066
+ device_verified: zod.z.boolean().nullable().optional().describe(
1067
+ "Whether the device has been verified. Sourcing: device attestation or registration service."
1068
+ ),
1069
+ device_id: zod.z.string().nullable().optional().describe(
1070
+ "Stable device identifier when available. Sourcing: client device registry or fingerprint service."
1071
+ ),
1072
+ device_fingerprint_hash: zod.z.string().nullable().optional().describe(
1073
+ "Hash of device fingerprint attributes. Sourcing: stable_hash of normalized device fingerprint payload."
1074
+ ),
1075
+ cadence_deviation: zod.z.number().min(0).max(1).nullable().optional().describe(
1076
+ "0\u20131 normalized faster-than-baseline deviation of message cadence. Sourcing: min(1, max(0, (baseline_interval_ms - current_interval_ms) / baseline_interval_ms)) when current < baseline, else 0."
1077
+ ),
1078
+ inter_message_interval_ms: zod.z.number().nonnegative().nullable().optional().describe(
1079
+ "Milliseconds between the current user message and the previous user message in the same session. Sourcing: current_ts \u2212 previous_ts; omit if no prior user message."
1080
+ ),
1081
+ event_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1082
+ "Count of events that triggered the anomaly in the current window. Sourcing: rolling-window event counter."
1083
+ ),
1084
+ baseline_event_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1085
+ "Expected event count in the baseline window. Sourcing: historical baseline or policy-configured value."
1086
+ ),
1087
+ request_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1088
+ "Count of requests that triggered the anomaly in the current window. Sourcing: rolling-window request counter."
1089
+ ),
1090
+ baseline_request_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1091
+ "Expected request count in the baseline window. Sourcing: historical baseline or policy-configured value."
1092
+ ),
1093
+ volume_ratio: zod.z.number().nonnegative().nullable().optional().describe(
1094
+ "Ratio of request count to baseline request count. Sourcing: request_count / max(baseline_request_count, 1) when not precomputed; omit if counts unavailable."
1095
+ )
946
1096
  });
947
1097
  BaseEventSchema.extend({
948
1098
  signal_payload: AnomalyFlagSignalPayloadSchema
@@ -996,9 +1146,7 @@ var ApiCallSignalPayloadSchema = zod.z.object({
996
1146
  authorized: zod.z.boolean().nullable().describe(
997
1147
  "Whether the call was authorized; null means authorization is unknown."
998
1148
  ),
999
- authentication_present: zod.z.boolean().nullable().optional().describe(
1000
- "Whether authentication credentials were present when known."
1001
- ),
1149
+ authentication_present: zod.z.boolean().nullable().optional().describe("Whether authentication credentials were present when known."),
1002
1150
  rate_limited: zod.z.boolean().nullable().optional().describe("Whether the call was rate limited when known."),
1003
1151
  external_side_effect: zod.z.boolean().nullable().optional().describe(
1004
1152
  "Whether the call modifies state outside the caller context when known."
@@ -1040,8 +1188,40 @@ var createAuthEvent = (event) => {
1040
1188
  const signalPayload = AuthSignalPayloadSchema.parse(event.signal_payload);
1041
1189
  return buildRawEventRequest(event, signalPayload, "AUTH");
1042
1190
  };
1191
+
1192
+ // src/shared/types/behavior-type.ts
1193
+ var BEHAVIOR_TYPES = [
1194
+ "chat_cadence",
1195
+ "repeated_retries",
1196
+ "session_hopping",
1197
+ "policy_challenge_pattern",
1198
+ "recursive_loop",
1199
+ "abnormal_usage_pattern"
1200
+ ];
1201
+
1202
+ // src/v1/schemas/behavior.ts
1043
1203
  var BehaviorSignalPayloadSchema = zod.z.object({
1044
- deviation_score: fraction01()
1204
+ behavior_type: zod.z.enum(BEHAVIOR_TYPES).describe(
1205
+ "Semantic behavior class (chat_cadence, repeated_retries, session_hopping, policy_challenge_pattern, recursive_loop, or abnormal_usage_pattern). Sourcing: behavioral pattern detector or rolling-window analyzer."
1206
+ ),
1207
+ deviation_score: fraction01().describe(
1208
+ "0\u20131 normalized deviation from expected baseline behavior. Sourcing: computed as min(1, max(0, (current - baseline) / max(baseline, 1)))."
1209
+ ),
1210
+ current_value: zod.z.number().nullable().optional().describe(
1211
+ "Observed behavioral metric in the current window. Sourcing: rolling-window counter or rate from session/user events."
1212
+ ),
1213
+ baseline_value: zod.z.number().nullable().optional().describe(
1214
+ "Expected baseline behavioral metric. Sourcing: historical baseline or policy-configured expected value."
1215
+ ),
1216
+ unit: zod.z.string().nullable().optional().describe(
1217
+ "Unit for current_value and baseline_value (e.g. messages_per_minute). Sourcing: detector metadata."
1218
+ ),
1219
+ baseline_window_seconds: zod.z.number().int().min(1).nullable().optional().describe(
1220
+ "Duration in seconds of the baseline measurement window. Sourcing: baseline configuration."
1221
+ ),
1222
+ current_window_seconds: zod.z.number().int().min(1).nullable().optional().describe(
1223
+ "Duration in seconds of the current measurement window. Sourcing: detector rolling-window configuration."
1224
+ )
1045
1225
  });
1046
1226
  BaseEventSchema.extend({
1047
1227
  signal_payload: BehaviorSignalPayloadSchema
@@ -1069,9 +1249,7 @@ var ContextIntegritySignalPayloadSchema = zod.z.object({
1069
1249
  "Origin of the evaluated context: CONVERSATION_HISTORY, RETRIEVED_DOCUMENT, TOOL_OUTPUT, SYSTEM, DEVELOPER, or USER."
1070
1250
  ),
1071
1251
  instruction_conflict_detected: zod.z.boolean().describe("Whether conflicting instructions were detected in context."),
1072
- untrusted_instruction_detected: zod.z.boolean().describe(
1073
- "Whether an untrusted source contains instruction-like text."
1074
- ),
1252
+ untrusted_instruction_detected: zod.z.boolean().describe("Whether an untrusted source contains instruction-like text."),
1075
1253
  context_priority_violation: zod.z.boolean().describe(
1076
1254
  "Whether lower-priority context attempts to override higher-priority context."
1077
1255
  ),
@@ -1108,6 +1286,12 @@ var ContextIntegritySignalPayloadSchema = zod.z.object({
1108
1286
  contains_instruction_override: zod.z.boolean().optional().default(false).describe("Whether the context contains an instruction override."),
1109
1287
  context_injection_score: fraction01Nullable().describe(
1110
1288
  "0\u20131 context injection score when available; omit if unknown."
1289
+ ),
1290
+ retrieved_context_hash: zod.z.string().nullable().optional().describe(
1291
+ "Hash of retrieved or assembled context when available. Sourcing: stable_hash of the canonicalized context bundle for audit/explainability."
1292
+ ),
1293
+ context_source_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1294
+ "Number of context sources evaluated in this context window. Sourcing: count of distinct sources in the assembled context."
1111
1295
  )
1112
1296
  });
1113
1297
  BaseEventSchema.extend({
@@ -1121,6 +1305,17 @@ var createContextIntegrityEvent = (event) => {
1121
1305
  );
1122
1306
  return buildRawEventRequest(event, signalPayload, "CONTEXT_INTEGRITY");
1123
1307
  };
1308
+
1309
+ // src/shared/types/finish-reason.ts
1310
+ var FINISH_REASONS = [
1311
+ "STOP",
1312
+ "LENGTH",
1313
+ "CONTENT_FILTER",
1314
+ "TOOL_CALLS",
1315
+ "ERROR"
1316
+ ];
1317
+
1318
+ // src/v1/schemas/model-output.ts
1124
1319
  var ModelOutputSignalPayloadSchema = zod.z.object({
1125
1320
  missing_citations_rate: fraction01Nullable(),
1126
1321
  citation_rate: fraction01Nullable(),
@@ -1146,6 +1341,9 @@ var ModelOutputSignalPayloadSchema = zod.z.object({
1146
1341
  ),
1147
1342
  contains_unsupported_claims: zod.z.boolean().optional().default(false).describe(
1148
1343
  "Whether the output contains unsupported claims; confirm with clients."
1344
+ ),
1345
+ finish_reason: zod.z.enum(FINISH_REASONS).nullable().optional().describe(
1346
+ "Model API finish reason when available (stop, length, content_filter, tool_calls, or error). Sourcing: model API response finish_reason field."
1149
1347
  )
1150
1348
  });
1151
1349
  BaseEventSchema.extend({
@@ -1160,14 +1358,27 @@ var createModelOutputEvent = (event) => {
1160
1358
  return buildRawEventRequest(event, signalPayload, "MODEL_OUTPUT");
1161
1359
  };
1162
1360
  var NetworkSignalPayloadSchema = zod.z.object({
1163
- ip: zod.z.string().nullable().optional(),
1164
- asn: zod.z.string().nullable().optional(),
1165
- reputation_score: fraction01Nullable(),
1166
- threat_score: fraction01Nullable(),
1167
- is_datacenter: zod.z.boolean().nullable().optional(),
1168
- is_untrusted_segment: zod.z.boolean().optional().default(false).describe("Traffic originated from an untrusted network segment"),
1361
+ ip: zod.z.string().nullable().optional().describe(
1362
+ "Client IP address. Sourcing: request IP from API gateway or reverse proxy."
1363
+ ),
1364
+ asn: zod.z.number().int().nullable().optional().describe("Autonomous System Number. Sourcing: GeoIP/ASN lookup service."),
1365
+ country: zod.z.string().nullable().optional().describe(
1366
+ "ISO 3166-1 alpha-2 country code. Sourcing: GeoIP lookup; optional when location is unavailable."
1367
+ ),
1368
+ reputation_score: fraction01Nullable().describe(
1369
+ "IP reputation score (0\u20131, higher is more trusted). Sourcing: IP reputation provider, internal risk service, or safe default 0.5."
1370
+ ),
1371
+ threat_score: fraction01Nullable().describe(
1372
+ "Threat intelligence score (0\u20131). Sourcing: threat intel provider or internal risk model; safe default 0.0."
1373
+ ),
1374
+ is_datacenter: zod.z.boolean().nullable().optional().describe(
1375
+ "Whether the origin IP is a datacenter/proxy/VPN. Sourcing: GeoIP/proxy provider; safe default False."
1376
+ ),
1377
+ is_untrusted_segment: zod.z.boolean().nullable().optional().describe(
1378
+ "Whether traffic originated from an untrusted network segment. Sourcing: internal network segmentation policy; safe default False."
1379
+ ),
1169
1380
  asn_reputation: fraction01Nullable().describe(
1170
- "Reputation score for the origin ASN (0\u20131, higher is more trusted)"
1381
+ "Reputation score for the origin ASN (0\u20131, higher is more trusted). Sourcing: internal reputation map or external provider; safe default 0.5."
1171
1382
  )
1172
1383
  });
1173
1384
  BaseEventSchema.extend({
@@ -1241,7 +1452,22 @@ var PromptInputSignalPayloadSchema = zod.z.object({
1241
1452
  complexity_score: fraction01Nullable().describe(
1242
1453
  "0\u20131 prompt complexity or ambiguity score; omit or null to treat as 0.0."
1243
1454
  ),
1244
- prompt_hash: promptHashSchema
1455
+ prompt_hash: promptHashSchema,
1456
+ inter_message_interval_ms: zod.z.number().nonnegative().nullable().optional().describe(
1457
+ "Milliseconds between the current user message and the previous user message in the same session. Sourcing: current_ts \u2212 previous_ts; omit if no prior user message."
1458
+ ),
1459
+ cadence_deviation: zod.z.number().min(0).max(1).nullable().optional().describe(
1460
+ "0\u20131 normalized faster-than-baseline deviation of message cadence. Sourcing: min(1, max(0, (baseline_interval_ms - current_interval_ms) / baseline_interval_ms)) when current < baseline, else 0."
1461
+ ),
1462
+ previous_prompt_delta_ms: zod.z.number().nonnegative().nullable().optional().describe(
1463
+ "Milliseconds between the current prompt and the previous prompt. Sourcing: current_prompt_ts \u2212 previous_prompt_ts; omit if no prior prompt."
1464
+ ),
1465
+ prompt_sequence_index: zod.z.number().int().nonnegative().nullable().optional().describe(
1466
+ "Index of the prompt in the session prompt sequence. Sourcing: monotonic session prompt counter starting at 0."
1467
+ ),
1468
+ rapid_repeat: zod.z.boolean().optional().default(false).describe(
1469
+ "Whether the prompt is a rapid repeat of the previous prompt. Sourcing: compare current prompt hash/timestamp to previous prompt within configured repeat window."
1470
+ )
1245
1471
  });
1246
1472
  BaseEventSchema.extend({
1247
1473
  signal_payload: PromptInputSignalPayloadSchema
@@ -1270,10 +1496,14 @@ var RagRetrievalSignalPayloadSchema = zod.z.object({
1270
1496
  ),
1271
1497
  untrusted_source_count: zod.z.number().int().nonnegative().optional().default(0).describe("Count of low-trust or untrusted retrieved sources."),
1272
1498
  retrieved_context_tokens: zod.z.number().int().nonnegative().optional().default(0).describe("Total retrieved context token count when available."),
1273
- context_injection_score: fraction01().optional().default(0).describe(
1274
- "0\u20131 context injection risk score; use 0.0 when unavailable."
1499
+ context_injection_score: fraction01().optional().default(0).describe("0\u20131 context injection risk score; use 0.0 when unavailable."),
1500
+ document_ids: zod.z.array(zod.z.string()).optional().default([]).describe("Identifiers for retrieved documents when available."),
1501
+ contains_sensitive_data: zod.z.boolean().optional().default(false).describe(
1502
+ "Whether retrieved context contains sensitive data. Sourcing: PII/sensitive data classifier on retrieved bundle."
1275
1503
  ),
1276
- document_ids: zod.z.array(zod.z.string()).optional().default([]).describe("Identifiers for retrieved documents when available.")
1504
+ retrieval_hash: zod.z.string().nullable().optional().describe(
1505
+ "Hash of the assembled retrieval context bundle when available. Sourcing: stable_hash of the canonicalized retrieval bundle."
1506
+ )
1277
1507
  });
1278
1508
  BaseEventSchema.extend({
1279
1509
  signal_payload: RagRetrievalSignalPayloadSchema
@@ -1309,7 +1539,22 @@ var SessionSignalPayloadSchema = zod.z.object({
1309
1539
  session_timeout: zod.z.boolean().optional().default(false).describe("Whether the session ended due to a timeout."),
1310
1540
  abandoned: zod.z.boolean().optional().default(false).describe("Whether the session ended abruptly without a clean close."),
1311
1541
  conversation_id: zod.z.string().nullable().optional().describe("Related conversation identifier when available."),
1312
- user_id: zod.z.string().nullable().optional().describe("Related user identifier when available.")
1542
+ user_id: zod.z.string().nullable().optional().describe("Related user identifier when available."),
1543
+ inter_message_interval_ms: zod.z.number().nonnegative().nullable().optional().describe(
1544
+ "Milliseconds between the current user message and the previous user message in the same session. Sourcing: current_ts \u2212 previous_ts; omit if no prior user message."
1545
+ ),
1546
+ cadence_deviation: zod.z.number().min(0).max(1).nullable().optional().describe(
1547
+ "0\u20131 normalized faster-than-baseline deviation of message cadence. Sourcing: min(1, max(0, (baseline_interval_ms - current_interval_ms) / baseline_interval_ms)) when current < baseline, else 0."
1548
+ ),
1549
+ message_count: zod.z.number().int().nonnegative().nullable().optional().describe(
1550
+ "Count of messages in the session. Sourcing: session message counter over the measurement window."
1551
+ ),
1552
+ window_seconds: zod.z.number().int().nonnegative().nullable().optional().describe(
1553
+ "Time window over which message_count was measured. Sourcing: rolling-window configuration or session analytics window."
1554
+ ),
1555
+ session_duration_seconds: zod.z.number().nonnegative().nullable().optional().describe(
1556
+ "Duration of the session in seconds. Sourcing: session start/end timestamps or session_age_seconds at event emission time."
1557
+ )
1313
1558
  });
1314
1559
  BaseEventSchema.extend({
1315
1560
  signal_payload: SessionSignalPayloadSchema
@@ -1375,9 +1620,7 @@ var ToolCallSignalPayloadSchema = zod.z.object({
1375
1620
  "Whether policy allowed the tool call; null means authorization is unknown."
1376
1621
  ),
1377
1622
  safety_critical: zod.z.boolean().describe("Whether the call can create serious consequences."),
1378
- external_side_effect: zod.z.boolean().describe(
1379
- "Whether the action changes state outside the model context."
1380
- ),
1623
+ external_side_effect: zod.z.boolean().describe("Whether the action changes state outside the model context."),
1381
1624
  tool_call_success: zod.z.boolean().nullable().optional().describe("Whether the tool call succeeded when known."),
1382
1625
  latency_ms: zod.z.number().nonnegative().nullable().optional().describe("Tool latency in milliseconds when available."),
1383
1626
  error_code: zod.z.string().nullable().optional().describe("Error code when the tool call failed."),
@@ -1391,12 +1634,8 @@ var ToolCallSignalPayloadSchema = zod.z.object({
1391
1634
  "Risk category for the attempted action (e.g. SECURITY, CODE, FINANCIAL, ADMIN) when available."
1392
1635
  ),
1393
1636
  method: zod.z.string().nullable().optional().describe("HTTP or RPC method for the tool call when applicable."),
1394
- sensitive_data_involved: zod.z.boolean().optional().default(false).describe(
1395
- "Whether sensitive data was involved in the request or result."
1396
- ),
1397
- contains_phi: zod.z.boolean().optional().default(false).describe(
1398
- "Whether protected health information was returned or touched."
1399
- ),
1637
+ sensitive_data_involved: zod.z.boolean().optional().default(false).describe("Whether sensitive data was involved in the request or result."),
1638
+ contains_phi: zod.z.boolean().optional().default(false).describe("Whether protected health information was returned or touched."),
1400
1639
  sensitive_domain: zod.z.boolean().optional().default(false).describe("Whether the tool call applies to a sensitive domain.")
1401
1640
  });
1402
1641
  BaseEventSchema.extend({
@@ -1408,6 +1647,139 @@ var createToolCallEvent = (event) => {
1408
1647
  const signalPayload = ToolCallSignalPayloadSchema.parse(event.signal_payload);
1409
1648
  return buildRawEventRequest(event, signalPayload, "TOOL_CALL");
1410
1649
  };
1650
+
1651
+ // src/shared/types/action-scope.ts
1652
+ var ACTION_SCOPES = [
1653
+ "LOCAL",
1654
+ "ACCOUNT",
1655
+ "ORGANIZATION",
1656
+ "EXTERNAL"
1657
+ ];
1658
+
1659
+ // src/shared/types/approval-type.ts
1660
+ var APPROVAL_TYPES = [
1661
+ "HUMAN",
1662
+ "ADMIN",
1663
+ "POLICY",
1664
+ "DUAL_CONTROL",
1665
+ "MANAGER",
1666
+ "SECURITY_REVIEW"
1667
+ ];
1668
+
1669
+ // src/shared/types/data-scope.ts
1670
+ var DATA_SCOPES = [
1671
+ "NONE",
1672
+ "SELF",
1673
+ "SINGLE_USER",
1674
+ "MULTI_USER",
1675
+ "ORGANIZATION",
1676
+ "EXTERNAL"
1677
+ ];
1678
+
1679
+ // src/v1/schemas/tool-call-proposed.ts
1680
+ var ToolCallProposedSignalPayloadSchema = zod.z.object({
1681
+ tool_name: nonEmptyString().describe(
1682
+ "Name of the proposed tool. Sourcing: tool registry or agent planner."
1683
+ ),
1684
+ tool_category: zod.z.enum(TOOL_CATEGORIES).describe(
1685
+ "Category of the proposed tool (e.g. DATABASE, FILE, EMAIL, API, PAYMENT, SUPPORT, SEARCH, OTHER). Sourcing: tool registry metadata."
1686
+ ),
1687
+ action: nonEmptyString().describe(
1688
+ "Sanitized or normalized proposed action. Sourcing: agent planner or tool-call argument normalizer."
1689
+ ),
1690
+ action_hash: nonEmptyString().describe(
1691
+ "Hash of the raw action when sensitive. Sourcing: stable_hash of the canonicalized action string."
1692
+ ),
1693
+ authorized: zod.z.boolean().describe(
1694
+ "Whether the proposed action is authorized by policy. Sourcing: policy engine authorization check."
1695
+ ),
1696
+ authorization_token_present: zod.z.boolean().optional().default(false).describe(
1697
+ "Whether an authorization token is present for the proposed action. Sourcing: request context or policy token validator."
1698
+ ),
1699
+ safety_critical: zod.z.boolean().optional().default(false).describe(
1700
+ "Whether the proposed action is safety or security critical. Sourcing: tool registry risk classification."
1701
+ ),
1702
+ external_side_effect: zod.z.boolean().optional().default(false).describe(
1703
+ "Whether the proposed action changes state outside the model context. Sourcing: tool registry side-effect metadata."
1704
+ ),
1705
+ execution_pending: zod.z.boolean().optional().default(true).describe(
1706
+ "Whether execution is still pending (pre-execution gate). Sourcing: agent runtime state; True at proposal time."
1707
+ ),
1708
+ argument_risk_score: fraction01().optional().default(0).describe(
1709
+ "0\u20131 risk score for proposed tool arguments. Sourcing: argument risk classifier or policy evaluator."
1710
+ ),
1711
+ argument_risk_reasons: zod.z.array(zod.z.string()).optional().default([]).describe(
1712
+ "Human-readable reasons for argument risk. Sourcing: argument risk classifier output."
1713
+ ),
1714
+ requested_records: zod.z.number().int().nonnegative().nullable().optional().describe(
1715
+ "Number of records requested by the proposed action. Sourcing: parsed tool-call arguments or query planner."
1716
+ ),
1717
+ baseline_records: zod.z.number().int().nonnegative().nullable().optional().describe(
1718
+ "Policy or historical baseline record count for comparison. Sourcing: policy configuration or user/session baseline."
1719
+ ),
1720
+ contains_sensitive_data: zod.z.boolean().optional().default(false).describe(
1721
+ "Whether the proposed action touches sensitive data. Sourcing: data sensitivity classifier or policy check."
1722
+ ),
1723
+ sensitive_domain: zod.z.boolean().optional().default(false).describe(
1724
+ "Whether the proposed action applies to a sensitive domain. Sourcing: domain classifier or tool registry metadata."
1725
+ ),
1726
+ approval_missing: zod.z.boolean().nullable().optional().describe(
1727
+ "Whether required approval is missing. Sourcing: policy engine check when approval_required is true and no valid approval is present."
1728
+ ),
1729
+ approval_required: zod.z.boolean().nullable().optional().describe(
1730
+ "Whether the proposed action requires approval under policy, workflow, role, or sensitivity rules. Sourcing: policy engine approval rules."
1731
+ ),
1732
+ approval_type: zod.z.enum(APPROVAL_TYPES).nullable().optional().describe(
1733
+ "Type of approval required for the proposed action. Sourcing: policy engine approval type."
1734
+ ),
1735
+ approval_reason: zod.z.string().nullable().optional().describe(
1736
+ "Reason approval is required for the proposed action. Sourcing: policy engine approval reason."
1737
+ ),
1738
+ approval_id: zod.z.string().nullable().optional().describe(
1739
+ "Identifier of the approval record when present. Sourcing: approval workflow or policy engine."
1740
+ ),
1741
+ reversible: zod.z.boolean().nullable().optional().describe(
1742
+ "Whether the proposed action is reversible. Sourcing: tool registry metadata or action definition."
1743
+ ),
1744
+ rollback_available: zod.z.boolean().optional().default(false).describe(
1745
+ "Whether a rollback path exists for the proposed action. Sourcing: workflow engine metadata or action definition."
1746
+ ),
1747
+ rollback_plan_id: zod.z.string().nullable().optional().describe(
1748
+ "Rollback plan identifier when available. Sourcing: workflow engine compensation/rollback configuration."
1749
+ ),
1750
+ financially_material: zod.z.boolean().optional().default(false).describe(
1751
+ "Whether the proposed action is financially material. Sourcing: tool registry metadata or action definition."
1752
+ ),
1753
+ financial_amount: zod.z.number().nullable().optional().describe(
1754
+ "Financial amount of the proposed action. Sourcing: parsed tool-call arguments or billing estimate."
1755
+ ),
1756
+ financial_currency: zod.z.string().nullable().optional().describe(
1757
+ "Currency of the financial amount. Sourcing: ISO 4217 code from tool-call arguments or billing system."
1758
+ ),
1759
+ security_sensitive: zod.z.boolean().optional().default(false).describe(
1760
+ "Whether the proposed action is security sensitive. Sourcing: tool registry risk classification or policy check."
1761
+ ),
1762
+ affects_user_data: zod.z.boolean().optional().default(false).describe(
1763
+ "Whether the proposed action affects user data. Sourcing: data scope classifier or policy check."
1764
+ ),
1765
+ data_scope: zod.z.enum(DATA_SCOPES).nullable().optional().describe(
1766
+ "Scope of data affected by the proposed action. Sourcing: data scope classifier or policy engine."
1767
+ ),
1768
+ action_scope: zod.z.enum(ACTION_SCOPES).nullable().optional().describe(
1769
+ "Scope of the proposed action (LOCAL, ACCOUNT, ORGANIZATION, or EXTERNAL). Sourcing: tool registry metadata or policy engine."
1770
+ )
1771
+ });
1772
+ BaseEventSchema.extend({
1773
+ signal_payload: ToolCallProposedSignalPayloadSchema
1774
+ });
1775
+
1776
+ // src/v1/builders/tool-call-proposed-builder.ts
1777
+ var createToolCallProposedEvent = (event) => {
1778
+ const signalPayload = ToolCallProposedSignalPayloadSchema.parse(
1779
+ event.signal_payload
1780
+ );
1781
+ return buildRawEventRequest(event, signalPayload, "TOOL_CALL_PROPOSED");
1782
+ };
1411
1783
  var TransactionSignalPayloadSchema = zod.z.object({
1412
1784
  amount: zod.z.number().nonnegative().default(0).describe("Transaction amount in base currency"),
1413
1785
  amount_minor: zod.z.number().int().nonnegative().nullable().optional().describe("Transaction amount in minor units (e.g. cents)"),
@@ -1476,7 +1848,10 @@ var UserFeedbackSignalPayloadSchema = zod.z.object({
1476
1848
  "0\u20131 user-reported severity when available."
1477
1849
  ),
1478
1850
  response_id: zod.z.string().nullable().optional().describe("Identifier of the response being evaluated."),
1479
- user_comment_hash: zod.z.string().nullable().optional().describe("Hash of optional user comment when available.")
1851
+ user_comment_hash: zod.z.string().nullable().optional().describe("Hash of optional user comment when available."),
1852
+ conversation_id: zod.z.string().nullable().optional().describe(
1853
+ "Related conversation identifier when available. Sourcing: conversation or session ID from the feedback UI context."
1854
+ )
1480
1855
  });
1481
1856
  BaseEventSchema.extend({
1482
1857
  signal_payload: UserFeedbackSignalPayloadSchema
@@ -1511,6 +1886,7 @@ var WORKFLOW_ACTOR_TYPES = ["USER", "AI_AGENT", "SYSTEM"];
1511
1886
 
1512
1887
  // src/v1/schemas/workflow-action.ts
1513
1888
  var WorkflowActionSignalPayloadSchema = zod.z.object({
1889
+ workflow_name: nonEmptyString().describe("Workflow name."),
1514
1890
  workflow_id: nonEmptyString().describe("Workflow identifier."),
1515
1891
  workflow_type: nonEmptyString().describe("Type of workflow."),
1516
1892
  action_name: nonEmptyString().describe("Workflow action attempted."),
@@ -1532,7 +1908,52 @@ var WorkflowActionSignalPayloadSchema = zod.z.object({
1532
1908
  new_counterparty: zod.z.boolean().optional().default(false).describe("Whether a new vendor, customer, or recipient is involved."),
1533
1909
  is_new_vendor: zod.z.boolean().optional().default(false).describe("Whether the action involves a new vendor."),
1534
1910
  is_new_recipient: zod.z.boolean().optional().default(false).describe("Whether the action involves a new recipient."),
1535
- is_new_endpoint: zod.z.boolean().optional().default(false).describe("Whether the action targets a new endpoint.")
1911
+ is_new_endpoint: zod.z.boolean().optional().default(false).describe("Whether the action targets a new endpoint."),
1912
+ step_id: zod.z.string().nullable().optional().describe(
1913
+ "Workflow step identifier when available. Sourcing: workflow engine step ID."
1914
+ ),
1915
+ reversible: zod.z.boolean().nullable().optional().describe(
1916
+ "Whether the action can be rolled back or compensated. Sourcing: workflow engine metadata or action definition."
1917
+ ),
1918
+ rollback_plan_id: zod.z.string().nullable().optional().describe(
1919
+ "Rollback plan identifier when available. Sourcing: workflow engine compensation/rollback configuration."
1920
+ ),
1921
+ approval_required: zod.z.boolean().nullable().optional().describe(
1922
+ "Whether the proposed action requires approval under policy, workflow, role, or sensitivity rules. Sourcing: policy engine approval rules."
1923
+ ),
1924
+ approval_missing: zod.z.boolean().nullable().optional().describe(
1925
+ "Whether required approval is missing. Sourcing: policy engine check when approval_required is true and no valid approval is present."
1926
+ ),
1927
+ approval_type: zod.z.enum(APPROVAL_TYPES).nullable().optional().describe(
1928
+ "Type of approval required for the proposed action. Sourcing: policy engine approval type."
1929
+ ),
1930
+ rollback_available: zod.z.boolean().optional().default(false).describe(
1931
+ "Whether a rollback path exists for the proposed action. Sourcing: workflow engine metadata or action definition."
1932
+ ),
1933
+ financially_material: zod.z.boolean().optional().default(false).describe(
1934
+ "Whether the proposed action is financially material. Sourcing: workflow action definition or billing estimate."
1935
+ ),
1936
+ financial_amount: zod.z.number().nullable().optional().describe(
1937
+ "Financial amount of the proposed action. Sourcing: workflow action arguments or billing system."
1938
+ ),
1939
+ financial_currency: zod.z.string().nullable().optional().describe(
1940
+ "Currency of the financial amount. Sourcing: ISO 4217 code from workflow action or billing system."
1941
+ ),
1942
+ security_sensitive: zod.z.boolean().optional().default(false).describe(
1943
+ "Whether the proposed action is security sensitive. Sourcing: workflow action risk classification or policy check."
1944
+ ),
1945
+ contains_sensitive_data: zod.z.boolean().optional().default(false).describe(
1946
+ "Whether the proposed action touches sensitive data. Sourcing: data sensitivity classifier or policy check."
1947
+ ),
1948
+ affects_user_data: zod.z.boolean().optional().default(false).describe(
1949
+ "Whether the proposed action affects user data. Sourcing: data scope classifier or policy check."
1950
+ ),
1951
+ data_scope: zod.z.enum(DATA_SCOPES).nullable().optional().describe(
1952
+ "Scope of data affected by the proposed action. Sourcing: data scope classifier or policy engine."
1953
+ ),
1954
+ action_scope: zod.z.enum(ACTION_SCOPES).nullable().optional().describe(
1955
+ "Scope of the proposed action (LOCAL, ACCOUNT, ORGANIZATION, or EXTERNAL). Sourcing: workflow engine metadata or policy engine."
1956
+ )
1536
1957
  });
1537
1958
  BaseEventSchema.extend({
1538
1959
  signal_payload: WorkflowActionSignalPayloadSchema
@@ -1545,8 +1966,15 @@ var createWorkflowActionEvent = (event) => {
1545
1966
  );
1546
1967
  return buildRawEventRequest(event, signalPayload, "WORKFLOW_ACTION");
1547
1968
  };
1969
+ var stableHash = (value) => {
1970
+ if (!value || !value.trim()) return;
1971
+ const normalized = value.normalize("NFC").trim().toLowerCase();
1972
+ const hashed = crypto.createHash("sha256").update(normalized, "utf8").digest("hex");
1973
+ return `sha256:${hashed}`;
1974
+ };
1548
1975
 
1549
1976
  exports.API_REGISTRY = API_REGISTRY;
1977
+ exports.MccEvaluationResource = MccEvaluationResource;
1550
1978
  exports.QatiAPIError = QatiAPIError;
1551
1979
  exports.QatiAuthError = QatiAuthError;
1552
1980
  exports.QatiConfigError = QatiConfigError;
@@ -1556,6 +1984,7 @@ exports.QatiSDKError = QatiSDKError;
1556
1984
  exports.QatiServerError = QatiServerError;
1557
1985
  exports.RawEventRequestSchema = RawEventRequestSchema;
1558
1986
  exports.Session = Session;
1987
+ exports.WebhookEvent = WebhookEvent;
1559
1988
  exports.baseUrlFor = baseUrlFor;
1560
1989
  exports.createAnomalyFlagEvent = createAnomalyFlagEvent;
1561
1990
  exports.createApiCallEvent = createApiCallEvent;
@@ -1570,10 +1999,12 @@ exports.createRagRetrievalEvent = createRagRetrievalEvent;
1570
1999
  exports.createSessionEvent = createSessionEvent;
1571
2000
  exports.createSystemTelemetryEvent = createSystemTelemetryEvent;
1572
2001
  exports.createToolCallEvent = createToolCallEvent;
2002
+ exports.createToolCallProposedEvent = createToolCallProposedEvent;
1573
2003
  exports.createTransactionEvent = createTransactionEvent;
1574
2004
  exports.createUserFeedbackEvent = createUserFeedbackEvent;
1575
2005
  exports.createWorkflowActionEvent = createWorkflowActionEvent;
1576
2006
  exports.parseQatiConfig = parseQatiConfig;
1577
2007
  exports.resolveQatiConfig = resolveQatiConfig;
2008
+ exports.stableHash = stableHash;
1578
2009
  //# sourceMappingURL=index.cjs.map
1579
2010
  //# sourceMappingURL=index.cjs.map