@cdot65/prisma-airs-cli 7.1.2 → 7.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli/index.js +146 -57
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -6111,6 +6111,138 @@ async function fetchJobAttackRecords(client, jobId, options = {}) {
6111
6111
  // src/redteam/judge/ingest.ts
6112
6112
  import { createHash } from "crypto";
6113
6113
 
6114
+ // src/redteam/judge/envelope.ts
6115
+ function pythonLiteral(source) {
6116
+ let i = 0;
6117
+ let nodes = 0;
6118
+ const fail2 = () => {
6119
+ throw new Error("Unsupported exported literal");
6120
+ };
6121
+ const space = () => {
6122
+ while (/\s/.test(source[i] ?? "") && i < source.length) i++;
6123
+ };
6124
+ function string() {
6125
+ const quote = source[i++];
6126
+ let result2 = "";
6127
+ while (i < source.length) {
6128
+ const ch = source[i++];
6129
+ if (ch === quote) return result2;
6130
+ if (ch === "\n" || ch === "\r") fail2();
6131
+ if (ch !== "\\") {
6132
+ result2 += ch;
6133
+ continue;
6134
+ }
6135
+ const esc = source[i++];
6136
+ const simple = {
6137
+ a: "\x07",
6138
+ b: "\b",
6139
+ f: "\f",
6140
+ n: "\n",
6141
+ r: "\r",
6142
+ t: " ",
6143
+ v: "\v",
6144
+ "\\": "\\",
6145
+ "'": "'",
6146
+ '"': '"'
6147
+ };
6148
+ if (Object.hasOwn(simple, esc)) {
6149
+ result2 += simple[esc];
6150
+ continue;
6151
+ }
6152
+ const width = esc === "x" ? 2 : esc === "u" ? 4 : esc === "U" ? 8 : 0;
6153
+ if (width) {
6154
+ const digits = source.slice(i, i + width);
6155
+ if (digits.length !== width || !/^[\da-f]+$/i.test(digits)) fail2();
6156
+ const code = Number.parseInt(digits, 16);
6157
+ if (code > 1114111) fail2();
6158
+ result2 += String.fromCodePoint(code);
6159
+ i += width;
6160
+ continue;
6161
+ }
6162
+ if (/[0-7]/.test(esc ?? "")) {
6163
+ let digits = esc;
6164
+ while (digits.length < 3 && /[0-7]/.test(source[i] ?? "")) digits += source[i++];
6165
+ result2 += String.fromCodePoint(Number.parseInt(digits, 8));
6166
+ continue;
6167
+ }
6168
+ if (esc === void 0) fail2();
6169
+ result2 += `\\${esc}`;
6170
+ }
6171
+ return fail2();
6172
+ }
6173
+ function value(depth) {
6174
+ if (++nodes > 5e4 || depth > 64) fail2();
6175
+ space();
6176
+ const ch = source[i];
6177
+ if (ch === "'" || ch === '"') return string();
6178
+ if (ch === "{" || ch === "[") {
6179
+ i++;
6180
+ const object4 = /* @__PURE__ */ Object.create(null);
6181
+ const list = [];
6182
+ const end = ch === "{" ? "}" : "]";
6183
+ space();
6184
+ while (source[i] !== end) {
6185
+ if (ch === "{") {
6186
+ if (source[i] !== "'" && source[i] !== '"') fail2();
6187
+ const key = string();
6188
+ space();
6189
+ if (source[i++] !== ":" || Object.hasOwn(object4, key)) fail2();
6190
+ object4[key] = value(depth + 1);
6191
+ } else list.push(value(depth + 1));
6192
+ space();
6193
+ if (source[i] === end) break;
6194
+ if (source[i++] !== ",") fail2();
6195
+ space();
6196
+ }
6197
+ i++;
6198
+ return ch === "{" ? object4 : list;
6199
+ }
6200
+ for (const [token, literal] of [
6201
+ ["True", true],
6202
+ ["False", false],
6203
+ ["None", null]
6204
+ ]) {
6205
+ if (source.startsWith(token, i)) {
6206
+ i += token.length;
6207
+ return literal;
6208
+ }
6209
+ }
6210
+ const match = source.slice(i).match(/^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/);
6211
+ if (!match) return fail2();
6212
+ i += match[0].length;
6213
+ const number = Number(match[0]);
6214
+ if (!Number.isFinite(number)) fail2();
6215
+ return number;
6216
+ }
6217
+ const result = value(0);
6218
+ space();
6219
+ if (i !== source.length) fail2();
6220
+ return result;
6221
+ }
6222
+ function decodeContainer(raw) {
6223
+ if (raw.length > 1e6) return [raw, "plain"];
6224
+ try {
6225
+ return [JSON.parse(raw), "json"];
6226
+ } catch {
6227
+ }
6228
+ try {
6229
+ return [pythonLiteral(raw), "python_literal"];
6230
+ } catch {
6231
+ return [raw, "plain"];
6232
+ }
6233
+ }
6234
+ function messageText(value) {
6235
+ if (!value || typeof value !== "object" || Array.isArray(value)) return null;
6236
+ const message = value;
6237
+ if (message.kind !== "message" || !Object.hasOwn(message, "parts")) return null;
6238
+ const parts = message.parts;
6239
+ if (!Array.isArray(parts) || parts.some(
6240
+ (part) => !part || typeof part !== "object" || part.kind !== "text" || typeof part.text !== "string"
6241
+ ))
6242
+ return ["", "a2a_unsupported_parts"];
6243
+ return [parts.map((part) => part.text).join("\n"), "a2a_text"];
6244
+ }
6245
+
6114
6246
  // src/redteam/judge/questions.ts
6115
6247
  var SCHEMA_VERSION = 1;
6116
6248
  var DEFAULT_TYPESAFE_MODEL = "jev-latest";
@@ -6157,63 +6289,10 @@ function isDict(value) {
6157
6289
  function digest(text2) {
6158
6290
  return createHash("sha256").update(text2, "utf8").digest("hex").slice(0, 16);
6159
6291
  }
6160
- function pythonJson(value) {
6161
- if (Array.isArray(value)) return `[${value.map(pythonJson).join(", ")}]`;
6162
- if (isDict(value))
6163
- return `{${Object.entries(value).filter(([, v]) => v !== void 0).map(([k, v]) => `${JSON.stringify(k)}: ${pythonJson(v)}`).join(", ")}}`;
6164
- return JSON.stringify(value ?? null);
6165
- }
6166
- function textFromContentList(content) {
6167
- if (!Array.isArray(content)) return null;
6168
- const parts = content.filter((c) => isDict(c) && typeof c.text === "string").map((c) => c.text);
6169
- return parts.length ? parts.join("\n") : null;
6170
- }
6171
6292
  function extractResponseText(raw) {
6172
6293
  if (raw === null || raw === void 0) return ["", "empty"];
6173
- let value = raw;
6174
- let method = "plain";
6175
- if (typeof raw === "string") {
6176
- const stripped = raw.trim();
6177
- if (!stripped) return ["", "empty"];
6178
- if (stripped[0] !== "{" && stripped[0] !== "[") return [raw, "plain"];
6179
- try {
6180
- value = JSON.parse(stripped);
6181
- method = "json";
6182
- } catch {
6183
- return [raw, "plain"];
6184
- }
6185
- }
6186
- if (isDict(value)) {
6187
- const outputs = value.output;
6188
- if (Array.isArray(outputs)) {
6189
- const texts = outputs.map((item) => isDict(item) ? textFromContentList(item.content) : null).filter((text2) => Boolean(text2));
6190
- if (texts.length) return [texts.join("\n"), "responses_api"];
6191
- }
6192
- const choices = value.choices;
6193
- if (Array.isArray(choices) && choices.length && isDict(choices[0])) {
6194
- const message = choices[0].message;
6195
- if (isDict(message) && typeof message.content === "string")
6196
- return [message.content, "chat_completions"];
6197
- }
6198
- for (const key of ["output_text", "response", "text", "content", "message", "answer"]) {
6199
- if (typeof value[key] === "string") return [value[key], `json.${key}`];
6200
- }
6201
- const turns = value.messages || value.turns || value.conversation;
6202
- if (Array.isArray(turns) && turns.length) {
6203
- const last = turns[turns.length - 1];
6204
- if (isDict(last)) {
6205
- const text2 = typeof last.content === "string" ? last.content : textFromContentList(last.content);
6206
- if (text2) return [text2, "multi_turn_last"];
6207
- }
6208
- }
6209
- return [pythonJson(value), `${method}_unparsed`];
6210
- }
6211
- if (Array.isArray(value)) {
6212
- const texts = value.filter((item) => typeof item === "string");
6213
- if (texts.length) return [texts.join("\n"), "list_of_strings"];
6214
- return [pythonJson(value), `${method}_unparsed`];
6215
- }
6216
- return [String(value), "coerced"];
6294
+ if (typeof raw !== "string") throw new Error("Expected output to be a string");
6295
+ return [raw, raw.trim() ? "plain" : "empty"];
6217
6296
  }
6218
6297
  function recordsFromDocument(document) {
6219
6298
  if (Array.isArray(document)) return [document.filter(isDict), "array"];
@@ -6250,11 +6329,21 @@ function normalizeScan(document, options = {}) {
6250
6329
  };
6251
6330
  const limit = options.limit;
6252
6331
  for (const [index, record] of records.entries()) {
6253
- const prompt = record.prompt;
6254
- if (typeof prompt !== "string" || !prompt.trim()) {
6332
+ const rawPrompt = record.prompt;
6333
+ if (typeof rawPrompt !== "string" || !rawPrompt.trim()) {
6255
6334
  notes.skipped_no_prompt += 1;
6256
6335
  continue;
6257
6336
  }
6337
+ let prompt = rawPrompt;
6338
+ const promptMessage = prompt.trimStart().startsWith("{") ? messageText(decodeContainer(prompt.trim())[0]) : null;
6339
+ if (promptMessage !== null) {
6340
+ prompt = promptMessage[0];
6341
+ if (!prompt.trim()) {
6342
+ notes.skipped_no_prompt += 1;
6343
+ continue;
6344
+ }
6345
+ notes.normalized_prompt_envelopes = (notes.normalized_prompt_envelopes ?? 0) + 1;
6346
+ }
6258
6347
  const attackId = label(record.uuid) || label(record.attack_id) || label(record.id) || `index-${index}`;
6259
6348
  if (attackId === `index-${index}`) notes.fallback_row_ids = (notes.fallback_row_ids ?? 0) + 1;
6260
6349
  if (!label(record.goal)) notes.objective_proxies = (notes.objective_proxies ?? 0) + 1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cdot65/prisma-airs-cli",
3
3
  "packageManager": "pnpm@10.6.5",
4
- "version": "7.1.2",
4
+ "version": "7.1.4",
5
5
  "description": "CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",