@adversarylabs/sdk 0.1.16 → 0.1.17

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.
@@ -31,10 +31,29 @@ export interface PermissionsManifest {
31
31
  export interface FindingsManifest {
32
32
  format?: "adversary.review.v1";
33
33
  }
34
+ /**
35
+ * One composition member declared under adversary.yaml `uses`.
36
+ * Exactly one of `name` or `path` is required (enforced by schema).
37
+ * The CLI expands `uses` transitively at run time; this package only models
38
+ * and validates the field.
39
+ */
40
+ export interface UseManifest {
41
+ /** Registry / short adversary name (e.g. go/concurrency). */
42
+ name?: string;
43
+ /** Exact tag for `name` (ranges are not resolved yet). */
44
+ version?: string;
45
+ /** Local package directory relative to this package (or absolute). */
46
+ path?: string;
47
+ }
34
48
  export interface AdversaryManifest {
35
49
  name: string;
36
50
  version?: string;
37
51
  description?: string;
52
+ /**
53
+ * Other adversaries to run when this package is selected (composition).
54
+ * Expanded by the CLI; GitHub comment voice stays on the CLI entry package.
55
+ */
56
+ uses?: UseManifest[];
38
57
  triggers?: TriggerManifest;
39
58
  detection?: DetectionManifest;
40
59
  runtime: RuntimeManifest;
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,4BAA4B,mBAAmB,CAAC;AAC7D,eAAO,MAAM,4BAA4B,QAAU,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,8BAA8B,CAAC;IAC7C,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACvC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAMD,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO;CAKnD;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,iBAAiB,CAiCrF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAO3E"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,4BAA4B,mBAAmB,CAAC;AAC7D,eAAO,MAAM,4BAA4B,QAAU,CAAC;AAEpD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,6BAA6B;IAC5C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,6BAA6B,CAAC;IAC3C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,8BAA8B,CAAC;IAC7C,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACvC;AAMD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,OAAO,EAAE,eAAe,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAMD,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO;CAKnD;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,iBAAiB,CAiCrF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAO3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAA2C,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAEzC,MAAM,CAAC,MAAM,4BAA4B,GAAG,gBAAgB,CAAC;AAC7D,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,IAAI,EAAE,CAAC;AA2DpD,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACvC,MAAM,CAAW;IAE1B,YAAY,OAAe,EAAE,SAAmB,EAAE;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,IAAI,iBAAwE,CAAC;AAE7E,MAAM,UAAU,sBAAsB,CAAC,MAA2B;IAChE,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC7C,IAAI,IAAI,GAAG,4BAA4B,EAAE,CAAC;QACxC,MAAM,IAAI,uBAAuB,CAC/B,gCAAgC,IAAI,kBAAkB,4BAA4B,QAAQ,CAC3F,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,EAAE;QACxC,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IACH,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,uBAAuB,CAAC,iDAAiD,CAAC,CAAC;IACvF,CAAC;IACD,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,IAAI,uBAAuB,CAAC,yBAAyB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1F,CAAC;IAED,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrE,MAAM,IAAI,uBAAuB,CAAC,yBAAyB,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,OAAO,yBAAyB,CAAC,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACtD,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;IACzC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/D,MAAM,IAAI,uBAAuB,CAAC,+BAA+B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,0BAA0B,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB;IAC3B,IAAI,iBAAiB,KAAK,SAAS;QAAE,OAAO,iBAAiB,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CACvB,YAAY,CAAC,IAAI,GAAG,CAAC,8CAA8C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC/F,CAAC;IACF,iBAAiB,GAAG,IAAI,OAAO,CAAC;QAC9B,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb,CAAC,CAAC,OAAO,CAA0B,MAAM,CAAC,CAAC;IAC5C,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAkB;IAC3C,MAAM,IAAI,GAAG,WAAW,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;IAClE,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,KAAK,qCAAqC,EAAE,CAAC;QAC9F,OAAO,GAAG,IAAI,2CAA2C,CAAC;IAC5D,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,sBAAsB,EAAE,CAAC;QAC7C,OAAO,GAAG,IAAI,2BAA2B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjC,OAAO,GAAG,IAAI,8BAA8B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,EAAE,CAAC;IAC7F,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,KAAK,CAAC,OAAO,IAAI,UAAU,KAAK,CAAC,OAAO,aAAa,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,0BAA0B,CAAC,QAAiC;IACnE,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAC7D,MAAM,EAAE,GAAG,EAAE,GAAG,WAAW,EAAE,GAAG,QAAQ,CAAC,WAAW,CAAC;IACrD,OAAO;QACL,GAAG,QAAQ;QACX,WAAW,EAAE;YACX,GAAG,WAAW;YACd,WAAW,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;SAC5B;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { Ajv2020, type ErrorObject, type ValidateFunction } from \"ajv/dist/2020.js\";\nimport { parseAllDocuments } from \"yaml\";\n\nexport const ADVERSARY_MANIFEST_FILE_NAME = \"adversary.yaml\";\nexport const ADVERSARY_MANIFEST_MAX_BYTES = 1 << 20;\n\nexport interface DetectionManifest {\n files?: string[];\n entrypoint?: string;\n}\n\nexport interface TriggerManifest {\n manual?: boolean;\n files_changed?: string[];\n}\n\nexport interface RuntimeManifest {\n name?: \"node\" | \"process\";\n image?: string;\n version?: string;\n command: string[];\n}\n\nexport interface FilesystemPermissionsManifest {\n read?: string[];\n write?: string[];\n}\n\nexport interface EnvironmentPermissionsManifest {\n allow?: string[];\n}\n\nexport interface PermissionsManifest {\n filesystem?: FilesystemPermissionsManifest;\n network?: boolean;\n model?: boolean;\n environment?: EnvironmentPermissionsManifest;\n enforcement?: \"advisory\" | \"required\";\n}\n\ninterface LegacyPermissionsManifest extends PermissionsManifest {\n env?: string[];\n}\n\nexport interface FindingsManifest {\n format?: \"adversary.review.v1\";\n}\n\nexport interface AdversaryManifest {\n name: string;\n version?: string;\n description?: string;\n triggers?: TriggerManifest;\n detection?: DetectionManifest;\n runtime: RuntimeManifest;\n permissions?: PermissionsManifest;\n findings?: FindingsManifest;\n}\n\ninterface ParsedAdversaryManifest extends Omit<AdversaryManifest, \"permissions\"> {\n permissions?: LegacyPermissionsManifest;\n}\n\nexport class ManifestValidationError extends Error {\n readonly issues: string[];\n\n constructor(message: string, issues: string[] = []) {\n super(message);\n this.name = \"ManifestValidationError\";\n this.issues = issues;\n }\n}\n\nlet manifestValidator: ValidateFunction<ParsedAdversaryManifest> | undefined;\n\nexport function parseAdversaryManifest(source: string | Uint8Array): AdversaryManifest {\n const text = typeof source === \"string\" ? source : new TextDecoder().decode(source);\n const size = Buffer.byteLength(text, \"utf8\");\n if (size > ADVERSARY_MANIFEST_MAX_BYTES) {\n throw new ManifestValidationError(\n `adversary.yaml is too large: ${size} bytes exceeds ${ADVERSARY_MANIFEST_MAX_BYTES} bytes`,\n );\n }\n\n const documents = parseAllDocuments(text, {\n prettyErrors: true,\n uniqueKeys: true,\n });\n if (documents.length !== 1) {\n throw new ManifestValidationError(\"manifest must contain exactly one YAML document\");\n }\n const document = documents[0];\n if (document === undefined || document.contents === null) {\n throw new ManifestValidationError(\"manifest is empty\");\n }\n if (document.errors.length > 0) {\n const issues = document.errors.map((error) => error.message);\n throw new ManifestValidationError(`decode manifest YAML: ${issues.join(\"; \")}`, issues);\n }\n\n let value: unknown;\n try {\n value = document.toJS({ maxAliasCount: 0 });\n } catch (error) {\n const issue = error instanceof Error ? error.message : String(error);\n throw new ManifestValidationError(`decode manifest YAML: ${issue}`, [issue]);\n }\n return validateAdversaryManifest(value);\n}\n\nexport function validateAdversaryManifest(value: unknown): AdversaryManifest {\n const validator = getManifestValidator();\n if (!validator(value)) {\n const issues = (validator.errors ?? []).map(formatSchemaError);\n throw new ManifestValidationError(`invalid adversary manifest: ${issues.join(\"; \")}`, issues);\n }\n return normalizeLegacyPermissions(value);\n}\n\nfunction getManifestValidator(): ValidateFunction<ParsedAdversaryManifest> {\n if (manifestValidator !== undefined) return manifestValidator;\n const schema = JSON.parse(\n readFileSync(new URL(\"../schemas/adversary.manifest.v1.schema.json\", import.meta.url), \"utf8\"),\n );\n manifestValidator = new Ajv2020({\n allErrors: true,\n strict: true,\n }).compile<ParsedAdversaryManifest>(schema);\n return manifestValidator;\n}\n\nfunction formatSchemaError(error: ErrorObject): string {\n const path = `manifest${error.instancePath.replaceAll(\"/\", \".\")}`;\n if (error.keyword === \"pattern\" && error.schemaPath === \"#/$defs/portableProjectPath/pattern\") {\n return `${path} must be a portable project-relative path`;\n }\n if (error.keyword === \"additionalProperties\") {\n return `${path} contains unknown field ${JSON.stringify(error.params.additionalProperty)}`;\n }\n if (error.keyword === \"required\") {\n return `${path} is missing required field ${JSON.stringify(error.params.missingProperty)}`;\n }\n return `${path} ${error.message ?? `failed ${error.keyword} validation`}`;\n}\n\nfunction normalizeLegacyPermissions(manifest: ParsedAdversaryManifest): AdversaryManifest {\n if (manifest.permissions?.env === undefined) return manifest;\n const { env, ...permissions } = manifest.permissions;\n return {\n ...manifest,\n permissions: {\n ...permissions,\n environment: { allow: env },\n },\n };\n}\n"]}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { Ajv2020, type ErrorObject, type ValidateFunction } from \"ajv/dist/2020.js\";\nimport { parseAllDocuments } from \"yaml\";\n\nexport const ADVERSARY_MANIFEST_FILE_NAME = \"adversary.yaml\";\nexport const ADVERSARY_MANIFEST_MAX_BYTES = 1 << 20;\n\nexport interface DetectionManifest {\n files?: string[];\n entrypoint?: string;\n}\n\nexport interface TriggerManifest {\n manual?: boolean;\n files_changed?: string[];\n}\n\nexport interface RuntimeManifest {\n name?: \"node\" | \"process\";\n image?: string;\n version?: string;\n command: string[];\n}\n\nexport interface FilesystemPermissionsManifest {\n read?: string[];\n write?: string[];\n}\n\nexport interface EnvironmentPermissionsManifest {\n allow?: string[];\n}\n\nexport interface PermissionsManifest {\n filesystem?: FilesystemPermissionsManifest;\n network?: boolean;\n model?: boolean;\n environment?: EnvironmentPermissionsManifest;\n enforcement?: \"advisory\" | \"required\";\n}\n\ninterface LegacyPermissionsManifest extends PermissionsManifest {\n env?: string[];\n}\n\nexport interface FindingsManifest {\n format?: \"adversary.review.v1\";\n}\n\n/**\n * One composition member declared under adversary.yaml `uses`.\n * Exactly one of `name` or `path` is required (enforced by schema).\n * The CLI expands `uses` transitively at run time; this package only models\n * and validates the field.\n */\nexport interface UseManifest {\n /** Registry / short adversary name (e.g. go/concurrency). */\n name?: string;\n /** Exact tag for `name` (ranges are not resolved yet). */\n version?: string;\n /** Local package directory relative to this package (or absolute). */\n path?: string;\n}\n\nexport interface AdversaryManifest {\n name: string;\n version?: string;\n description?: string;\n /**\n * Other adversaries to run when this package is selected (composition).\n * Expanded by the CLI; GitHub comment voice stays on the CLI entry package.\n */\n uses?: UseManifest[];\n triggers?: TriggerManifest;\n detection?: DetectionManifest;\n runtime: RuntimeManifest;\n permissions?: PermissionsManifest;\n findings?: FindingsManifest;\n}\n\ninterface ParsedAdversaryManifest extends Omit<AdversaryManifest, \"permissions\"> {\n permissions?: LegacyPermissionsManifest;\n}\n\nexport class ManifestValidationError extends Error {\n readonly issues: string[];\n\n constructor(message: string, issues: string[] = []) {\n super(message);\n this.name = \"ManifestValidationError\";\n this.issues = issues;\n }\n}\n\nlet manifestValidator: ValidateFunction<ParsedAdversaryManifest> | undefined;\n\nexport function parseAdversaryManifest(source: string | Uint8Array): AdversaryManifest {\n const text = typeof source === \"string\" ? source : new TextDecoder().decode(source);\n const size = Buffer.byteLength(text, \"utf8\");\n if (size > ADVERSARY_MANIFEST_MAX_BYTES) {\n throw new ManifestValidationError(\n `adversary.yaml is too large: ${size} bytes exceeds ${ADVERSARY_MANIFEST_MAX_BYTES} bytes`,\n );\n }\n\n const documents = parseAllDocuments(text, {\n prettyErrors: true,\n uniqueKeys: true,\n });\n if (documents.length !== 1) {\n throw new ManifestValidationError(\"manifest must contain exactly one YAML document\");\n }\n const document = documents[0];\n if (document === undefined || document.contents === null) {\n throw new ManifestValidationError(\"manifest is empty\");\n }\n if (document.errors.length > 0) {\n const issues = document.errors.map((error) => error.message);\n throw new ManifestValidationError(`decode manifest YAML: ${issues.join(\"; \")}`, issues);\n }\n\n let value: unknown;\n try {\n value = document.toJS({ maxAliasCount: 0 });\n } catch (error) {\n const issue = error instanceof Error ? error.message : String(error);\n throw new ManifestValidationError(`decode manifest YAML: ${issue}`, [issue]);\n }\n return validateAdversaryManifest(value);\n}\n\nexport function validateAdversaryManifest(value: unknown): AdversaryManifest {\n const validator = getManifestValidator();\n if (!validator(value)) {\n const issues = (validator.errors ?? []).map(formatSchemaError);\n throw new ManifestValidationError(`invalid adversary manifest: ${issues.join(\"; \")}`, issues);\n }\n return normalizeLegacyPermissions(value);\n}\n\nfunction getManifestValidator(): ValidateFunction<ParsedAdversaryManifest> {\n if (manifestValidator !== undefined) return manifestValidator;\n const schema = JSON.parse(\n readFileSync(new URL(\"../schemas/adversary.manifest.v1.schema.json\", import.meta.url), \"utf8\"),\n );\n manifestValidator = new Ajv2020({\n allErrors: true,\n strict: true,\n }).compile<ParsedAdversaryManifest>(schema);\n return manifestValidator;\n}\n\nfunction formatSchemaError(error: ErrorObject): string {\n const path = `manifest${error.instancePath.replaceAll(\"/\", \".\")}`;\n if (error.keyword === \"pattern\" && error.schemaPath === \"#/$defs/portableProjectPath/pattern\") {\n return `${path} must be a portable project-relative path`;\n }\n if (error.keyword === \"additionalProperties\") {\n return `${path} contains unknown field ${JSON.stringify(error.params.additionalProperty)}`;\n }\n if (error.keyword === \"required\") {\n return `${path} is missing required field ${JSON.stringify(error.params.missingProperty)}`;\n }\n return `${path} ${error.message ?? `failed ${error.keyword} validation`}`;\n}\n\nfunction normalizeLegacyPermissions(manifest: ParsedAdversaryManifest): AdversaryManifest {\n if (manifest.permissions?.env === undefined) return manifest;\n const { env, ...permissions } = manifest.permissions;\n return {\n ...manifest,\n permissions: {\n ...permissions,\n environment: { allow: env },\n },\n };\n}\n"]}
package/dist/model.d.ts CHANGED
@@ -30,6 +30,11 @@ export interface ModelReviewResult<T = unknown> {
30
30
  export interface ReviewModel {
31
31
  review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>>;
32
32
  }
33
+ export interface BrokerReviewModelOptions {
34
+ maximumAttempts?: number;
35
+ initialRetryDelayMs?: number;
36
+ random?: () => number;
37
+ }
33
38
  /**
34
39
  * Request a short noun-phrase concern suitable after "I would address …".
35
40
  * Implemented by the SDK via {@link ReviewModel.review} (CLI broker pass-through).
@@ -74,7 +79,7 @@ export declare function unavailableModel(): ReviewModel;
74
79
  export declare class BrokerReviewModel implements ReviewModel {
75
80
  #private;
76
81
  readonly endpoint: string;
77
- constructor(endpoint: string, token: string);
82
+ constructor(endpoint: string, token: string, options?: BrokerReviewModelOptions);
78
83
  review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>>;
79
84
  }
80
85
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/model.js CHANGED
@@ -10,6 +10,9 @@ const MAX_PROMPT_BYTES = 256 << 10;
10
10
  const MAX_INPUT_BYTES = 4 << 20;
11
11
  const MAX_SCHEMA_BYTES = 512 << 10;
12
12
  const MAX_RESPONSE_BYTES = 4 << 20;
13
+ const DEFAULT_BROKER_MAXIMUM_ATTEMPTS = 3;
14
+ const DEFAULT_BROKER_RETRY_DELAY_MS = 250;
15
+ const MAX_BROKER_RETRY_DELAY_MS = 5_000;
13
16
  export class ModelUnavailableError extends Error {
14
17
  constructor(message = "Model review is unavailable for this adversary execution.") {
15
18
  super(message);
@@ -44,7 +47,10 @@ export function unavailableModel() {
44
47
  export class BrokerReviewModel {
45
48
  endpoint;
46
49
  #token;
47
- constructor(endpoint, token) {
50
+ #maximumAttempts;
51
+ #initialRetryDelayMs;
52
+ #random;
53
+ constructor(endpoint, token, options = {}) {
48
54
  const parsed = new URL(endpoint);
49
55
  if (parsed.protocol !== "http:" ||
50
56
  (parsed.hostname !== "127.0.0.1" &&
@@ -60,6 +66,13 @@ export class BrokerReviewModel {
60
66
  }
61
67
  this.endpoint = parsed.toString();
62
68
  this.#token = token;
69
+ const maximumAttempts = options.maximumAttempts ?? DEFAULT_BROKER_MAXIMUM_ATTEMPTS;
70
+ const initialRetryDelayMs = options.initialRetryDelayMs ?? DEFAULT_BROKER_RETRY_DELAY_MS;
71
+ requireIntegerRange(maximumAttempts, "maximumAttempts", 1, 5);
72
+ requireIntegerRange(initialRetryDelayMs, "initialRetryDelayMs", 0, MAX_BROKER_RETRY_DELAY_MS);
73
+ this.#maximumAttempts = maximumAttempts;
74
+ this.#initialRetryDelayMs = initialRetryDelayMs;
75
+ this.#random = options.random ?? Math.random;
63
76
  }
64
77
  async review(request) {
65
78
  if (request.tools?.repository !== undefined) {
@@ -69,71 +82,109 @@ export class BrokerReviewModel {
69
82
  const controller = new AbortController();
70
83
  const timeout = setTimeout(() => controller.abort(), normalized.budget.timeoutMs);
71
84
  try {
72
- let response;
73
- try {
74
- response = await fetch(this.endpoint, {
75
- method: "POST",
76
- headers: {
77
- accept: "application/json",
78
- authorization: `Bearer ${this.#token}`,
79
- "content-type": "application/json",
80
- "x-adversary-model-protocol": String(ADVERSARY_MODEL_PROTOCOL_VERSION),
81
- },
82
- body: JSON.stringify({
83
- protocolVersion: ADVERSARY_MODEL_PROTOCOL_VERSION,
84
- prompt: normalized.prompt,
85
- input: normalized.input,
86
- schema: normalized.schema,
87
- budget: normalized.budget,
88
- }),
89
- signal: controller.signal,
90
- });
91
- }
92
- catch (error) {
93
- if (controller.signal.aborted) {
94
- throw modelTimeoutError(normalized.budget.timeoutMs);
85
+ for (let attempt = 1; attempt <= this.#maximumAttempts; attempt += 1) {
86
+ try {
87
+ return await this.#reviewOnce(normalized, controller.signal);
95
88
  }
96
- throw new ModelReviewError(`Model broker request failed: ${error instanceof Error ? error.message : String(error)}`, { code: "broker_unavailable", retryable: true });
97
- }
98
- let body;
99
- try {
100
- body = await readBoundedResponse(response);
101
- }
102
- catch (error) {
103
- if (controller.signal.aborted) {
104
- throw modelTimeoutError(normalized.budget.timeoutMs);
89
+ catch (error) {
90
+ if (!(error instanceof ModelReviewError) ||
91
+ !error.retryable ||
92
+ controller.signal.aborted ||
93
+ attempt === this.#maximumAttempts) {
94
+ throw error;
95
+ }
96
+ const exponential = Math.min(MAX_BROKER_RETRY_DELAY_MS, this.#initialRetryDelayMs * 2 ** (attempt - 1));
97
+ const jittered = Math.round(exponential * (0.75 + 0.5 * this.#random()));
98
+ await waitForRetry(jittered, controller.signal, normalized.budget.timeoutMs);
105
99
  }
106
- throw error;
107
- }
108
- let decoded;
109
- try {
110
- decoded = JSON.parse(body);
111
100
  }
112
- catch {
113
- throw new ModelReviewError("Model broker returned malformed JSON.", {
114
- code: "invalid_broker_response",
115
- });
116
- }
117
- if (!response.ok) {
118
- const failure = decoded;
119
- throw new ModelReviewError(failure.error?.message ?? `Model broker returned HTTP ${response.status}.`, {
120
- code: failure.error?.code ?? "model_review_failed",
121
- retryable: failure.error?.retryable ?? response.status >= 500,
122
- });
123
- }
124
- const envelope = requireBrokerResponse(decoded);
125
- validateModelOutput(normalized.schema, envelope.output);
126
- return {
127
- output: envelope.output,
128
- provider: envelope.provider,
129
- model: envelope.model,
130
- ...(envelope.usage === undefined ? {} : { usage: envelope.usage }),
131
- };
101
+ throw new ModelReviewError("Model broker retry loop exhausted unexpectedly.", {
102
+ code: "broker_unavailable",
103
+ retryable: true,
104
+ });
132
105
  }
133
106
  finally {
134
107
  clearTimeout(timeout);
135
108
  }
136
109
  }
110
+ async #reviewOnce(normalized, signal) {
111
+ let response;
112
+ try {
113
+ response = await fetch(this.endpoint, {
114
+ method: "POST",
115
+ headers: {
116
+ accept: "application/json",
117
+ authorization: `Bearer ${this.#token}`,
118
+ "content-type": "application/json",
119
+ "x-adversary-model-protocol": String(ADVERSARY_MODEL_PROTOCOL_VERSION),
120
+ },
121
+ body: JSON.stringify({
122
+ protocolVersion: ADVERSARY_MODEL_PROTOCOL_VERSION,
123
+ prompt: normalized.prompt,
124
+ input: normalized.input,
125
+ schema: normalized.schema,
126
+ budget: normalized.budget,
127
+ }),
128
+ signal,
129
+ });
130
+ }
131
+ catch (error) {
132
+ if (signal.aborted) {
133
+ throw modelTimeoutError(normalized.budget.timeoutMs);
134
+ }
135
+ throw new ModelReviewError(`Model broker request failed: ${error instanceof Error ? error.message : String(error)}`, { code: "broker_unavailable", retryable: true });
136
+ }
137
+ let body;
138
+ try {
139
+ body = await readBoundedResponse(response);
140
+ }
141
+ catch (error) {
142
+ if (signal.aborted) {
143
+ throw modelTimeoutError(normalized.budget.timeoutMs);
144
+ }
145
+ throw error;
146
+ }
147
+ let decoded;
148
+ try {
149
+ decoded = JSON.parse(body);
150
+ }
151
+ catch {
152
+ throw new ModelReviewError("Model broker returned malformed JSON.", {
153
+ code: "invalid_broker_response",
154
+ });
155
+ }
156
+ if (!response.ok) {
157
+ const failure = decoded;
158
+ throw new ModelReviewError(failure.error?.message ?? `Model broker returned HTTP ${response.status}.`, {
159
+ code: failure.error?.code ?? "model_review_failed",
160
+ retryable: failure.error?.retryable ?? response.status >= 500,
161
+ });
162
+ }
163
+ const envelope = requireBrokerResponse(decoded);
164
+ validateModelOutput(normalized.schema, envelope.output);
165
+ return {
166
+ output: envelope.output,
167
+ provider: envelope.provider,
168
+ model: envelope.model,
169
+ ...(envelope.usage === undefined ? {} : { usage: envelope.usage }),
170
+ };
171
+ }
172
+ }
173
+ async function waitForRetry(delayMs, signal, timeoutMs) {
174
+ if (signal.aborted) {
175
+ throw modelTimeoutError(timeoutMs);
176
+ }
177
+ await new Promise((resolve, reject) => {
178
+ const onAbort = () => {
179
+ clearTimeout(timer);
180
+ reject(modelTimeoutError(timeoutMs));
181
+ };
182
+ const timer = setTimeout(() => {
183
+ signal.removeEventListener("abort", onAbort);
184
+ resolve();
185
+ }, delayMs);
186
+ signal.addEventListener("abort", onAbort, { once: true });
187
+ });
137
188
  }
138
189
  function modelTimeoutError(timeoutMs) {
139
190
  return new ModelReviewError(`Model review exceeded its ${timeoutMs}ms timeout.`, {
package/dist/model.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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","sourcesContent":["import { Ajv2020 } from \"ajv/dist/2020.js\";\nimport type {\n ModelRepositoryCitation,\n ModelRepositoryRetrieval,\n ModelRepositoryToolOptions,\n} from \"./repository-model.js\";\n\nexport const ADVERSARY_MODEL_PROTOCOL_VERSION = 1;\nexport const ADVERSARY_MODEL_ENDPOINT_ENV = \"ADVERSARY_MODEL_ENDPOINT\";\nexport const ADVERSARY_MODEL_TOKEN_ENV = \"ADVERSARY_MODEL_TOKEN\";\n\nconst DEFAULT_MODEL_TIMEOUT_MS = 120_000;\nconst MAX_MODEL_TIMEOUT_MS = 600_000;\nconst DEFAULT_MAXIMUM_OUTPUT_TOKENS = 8_192;\nconst MAX_MAXIMUM_OUTPUT_TOKENS = 65_536;\nconst MAX_PROMPT_BYTES = 256 << 10;\nconst MAX_INPUT_BYTES = 4 << 20;\nconst MAX_SCHEMA_BYTES = 512 << 10;\nconst MAX_RESPONSE_BYTES = 4 << 20;\n\nexport interface ModelReviewBudget {\n maximumOutputTokens?: number;\n timeoutMs?: number;\n}\n\nexport interface ModelReviewRequest {\n prompt: string;\n input: unknown;\n schema: Record<string, unknown>;\n budget?: ModelReviewBudget;\n tools?: {\n repository: ModelRepositoryToolOptions;\n };\n}\n\nexport interface ModelReviewUsage {\n inputTokens?: number;\n outputTokens?: number;\n}\n\nexport interface ModelReviewResult<T = unknown> {\n output: T;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n citations?: readonly ModelRepositoryCitation[];\n retrieval?: ModelRepositoryRetrieval;\n}\n\nexport interface ReviewModel {\n review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>>;\n}\n\n/**\n * Request a short noun-phrase concern suitable after \"I would address …\".\n * Implemented by the SDK via {@link ReviewModel.review} (CLI broker pass-through).\n */\nexport interface ModelConcernRequest {\n /** Free-form title, clause, or draft concern to rewrite. */\n text: string;\n budget?: ModelReviewBudget;\n /**\n * Extra attempts when the model returns a phrase that fails noun-phrase validation.\n * Defaults to 1 retry (2 total attempts).\n */\n maxAttempts?: number;\n}\n\nexport interface ModelConcernResult {\n /** Validated noun phrase (see requireOpinionConcern). */\n concern: string;\n /** False when `text` was already a valid noun phrase (no broker call). */\n rewritten: boolean;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n}\n\n/** Rule-context model: broker review plus opinion-concern rewrite. */\nexport type ContextualReviewModel = ReviewModel & {\n concern(request: ModelConcernRequest): Promise<ModelConcernResult>;\n};\n\nexport type ModelEnvironment = Readonly<Record<string, string | undefined>>;\n\ninterface ModelBrokerRequest extends ModelReviewRequest {\n protocolVersion: typeof ADVERSARY_MODEL_PROTOCOL_VERSION;\n}\n\ninterface ModelBrokerResponse {\n protocolVersion: typeof ADVERSARY_MODEL_PROTOCOL_VERSION;\n output: unknown;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n}\n\ninterface ModelBrokerErrorResponse {\n error?: {\n code?: string;\n message?: string;\n retryable?: boolean;\n };\n}\n\ntype NormalizedModelReviewRequest = Omit<ModelReviewRequest, \"budget\"> & {\n budget: Required<ModelReviewBudget>;\n};\n\nexport class ModelUnavailableError extends Error {\n constructor(message = \"Model review is unavailable for this adversary execution.\") {\n super(message);\n this.name = \"ModelUnavailableError\";\n }\n}\n\nexport class ModelReviewError extends Error {\n readonly code?: string;\n readonly retryable: boolean;\n\n constructor(message: string, options: { code?: string; retryable?: boolean } = {}) {\n super(message);\n this.name = \"ModelReviewError\";\n this.code = options.code;\n this.retryable = options.retryable ?? false;\n }\n}\n\nexport function createModelFromEnvironment(\n environment: ModelEnvironment = process.env,\n): ReviewModel {\n const endpoint = environment[ADVERSARY_MODEL_ENDPOINT_ENV]?.trim();\n const token = environment[ADVERSARY_MODEL_TOKEN_ENV]?.trim();\n if (endpoint === undefined || endpoint === \"\" || token === undefined || token === \"\") {\n return unavailableModel();\n }\n return new BrokerReviewModel(endpoint, token);\n}\n\nexport function unavailableModel(): ReviewModel {\n return Object.freeze({\n async review(): Promise<never> {\n throw new ModelUnavailableError();\n },\n });\n}\n\nexport class BrokerReviewModel implements ReviewModel {\n readonly endpoint: string;\n readonly #token: string;\n\n constructor(endpoint: string, token: string) {\n const parsed = new URL(endpoint);\n if (\n parsed.protocol !== \"http:\" ||\n (parsed.hostname !== \"127.0.0.1\" &&\n parsed.hostname !== \"::1\" &&\n parsed.hostname !== \"[::1]\" &&\n parsed.hostname !== \"localhost\")\n ) {\n throw new ModelReviewError(\n \"The model broker endpoint must use HTTP on the local loopback interface.\",\n { code: \"invalid_broker_endpoint\" },\n );\n }\n if (token.trim() === \"\") {\n throw new ModelReviewError(\"The model broker token must not be empty.\", {\n code: \"invalid_broker_token\",\n });\n }\n this.endpoint = parsed.toString();\n this.#token = token;\n }\n\n async review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>> {\n if (request.tools?.repository !== undefined) {\n throw new ModelReviewError(\n \"Repository model tools require ctx.model so the SDK can enforce the repository boundary.\",\n { code: \"invalid_model_request\" },\n );\n }\n const normalized = normalizeRequest(request);\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), normalized.budget.timeoutMs);\n try {\n let response: Response;\n try {\n response = await fetch(this.endpoint, {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n authorization: `Bearer ${this.#token}`,\n \"content-type\": \"application/json\",\n \"x-adversary-model-protocol\": String(ADVERSARY_MODEL_PROTOCOL_VERSION),\n },\n body: JSON.stringify({\n protocolVersion: ADVERSARY_MODEL_PROTOCOL_VERSION,\n prompt: normalized.prompt,\n input: normalized.input,\n schema: normalized.schema,\n budget: normalized.budget,\n } satisfies ModelBrokerRequest),\n signal: controller.signal,\n });\n } catch (error) {\n if (controller.signal.aborted) {\n throw modelTimeoutError(normalized.budget.timeoutMs);\n }\n throw new ModelReviewError(\n `Model broker request failed: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"broker_unavailable\", retryable: true },\n );\n }\n\n let body: string;\n try {\n body = await readBoundedResponse(response);\n } catch (error) {\n if (controller.signal.aborted) {\n throw modelTimeoutError(normalized.budget.timeoutMs);\n }\n throw error;\n }\n let decoded: unknown;\n try {\n decoded = JSON.parse(body);\n } catch {\n throw new ModelReviewError(\"Model broker returned malformed JSON.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (!response.ok) {\n const failure = decoded as ModelBrokerErrorResponse;\n throw new ModelReviewError(\n failure.error?.message ?? `Model broker returned HTTP ${response.status}.`,\n {\n code: failure.error?.code ?? \"model_review_failed\",\n retryable: failure.error?.retryable ?? response.status >= 500,\n },\n );\n }\n\n const envelope = requireBrokerResponse(decoded);\n validateModelOutput(normalized.schema, envelope.output);\n return {\n output: envelope.output as T,\n provider: envelope.provider,\n model: envelope.model,\n ...(envelope.usage === undefined ? {} : { usage: envelope.usage }),\n };\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nfunction modelTimeoutError(timeoutMs: number): ModelReviewError {\n return new ModelReviewError(`Model review exceeded its ${timeoutMs}ms timeout.`, {\n code: \"model_timeout\",\n retryable: true,\n });\n}\n\nfunction normalizeRequest(request: ModelReviewRequest): NormalizedModelReviewRequest {\n if (typeof request !== \"object\" || request === null) {\n throw new ModelReviewError(\"Model review request must be an object.\", {\n code: \"invalid_model_request\",\n });\n }\n if (typeof request.prompt !== \"string\" || request.prompt.trim() === \"\") {\n throw new ModelReviewError(\"Model review prompt must be a non-empty string.\", {\n code: \"invalid_model_request\",\n });\n }\n const promptBytes = Buffer.byteLength(request.prompt, \"utf8\");\n if (promptBytes > MAX_PROMPT_BYTES) {\n throw new ModelReviewError(`Model review prompt exceeds ${MAX_PROMPT_BYTES} bytes.`, {\n code: \"model_request_too_large\",\n });\n }\n requireJsonSize(request.input, \"input\", MAX_INPUT_BYTES);\n if (\n typeof request.schema !== \"object\" ||\n request.schema === null ||\n Array.isArray(request.schema)\n ) {\n throw new ModelReviewError(\"Model review schema must be a JSON Schema object.\", {\n code: \"invalid_model_schema\",\n });\n }\n requireJsonSize(request.schema, \"schema\", MAX_SCHEMA_BYTES);\n\n const maximumOutputTokens = request.budget?.maximumOutputTokens ?? DEFAULT_MAXIMUM_OUTPUT_TOKENS;\n const timeoutMs = request.budget?.timeoutMs ?? DEFAULT_MODEL_TIMEOUT_MS;\n requireIntegerRange(\n maximumOutputTokens,\n \"budget.maximumOutputTokens\",\n 1,\n MAX_MAXIMUM_OUTPUT_TOKENS,\n );\n requireIntegerRange(timeoutMs, \"budget.timeoutMs\", 1, MAX_MODEL_TIMEOUT_MS);\n return {\n prompt: request.prompt,\n input: request.input,\n schema: request.schema,\n budget: { maximumOutputTokens, timeoutMs },\n };\n}\n\nfunction requireJsonSize(value: unknown, name: string, maximum: number): void {\n let encoded: string | undefined;\n try {\n encoded = JSON.stringify(value);\n } catch (error) {\n throw new ModelReviewError(\n `Model review ${name} must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"invalid_model_request\" },\n );\n }\n if (encoded === undefined) {\n throw new ModelReviewError(`Model review ${name} must be JSON-serializable.`, {\n code: \"invalid_model_request\",\n });\n }\n if (Buffer.byteLength(encoded, \"utf8\") > maximum) {\n throw new ModelReviewError(`Model review ${name} exceeds ${maximum} bytes.`, {\n code: \"model_request_too_large\",\n });\n }\n}\n\nfunction requireIntegerRange(value: number, name: string, minimum: number, maximum: number): void {\n if (!Number.isInteger(value) || value < minimum || value > maximum) {\n throw new ModelReviewError(`${name} must be an integer from ${minimum} through ${maximum}.`, {\n code: \"invalid_model_budget\",\n });\n }\n}\n\nasync function readBoundedResponse(response: Response): Promise<string> {\n const declared = response.headers.get(\"content-length\");\n if (declared !== null && Number(declared) > MAX_RESPONSE_BYTES) {\n throw new ModelReviewError(`Model broker response exceeds ${MAX_RESPONSE_BYTES} bytes.`, {\n code: \"model_response_too_large\",\n });\n }\n if (response.body === null) {\n return \"\";\n }\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n size += value.byteLength;\n if (size > MAX_RESPONSE_BYTES) {\n await reader.cancel();\n throw new ModelReviewError(`Model broker response exceeds ${MAX_RESPONSE_BYTES} bytes.`, {\n code: \"model_response_too_large\",\n });\n }\n chunks.push(value);\n }\n const joined = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n joined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(joined);\n}\n\nfunction requireBrokerResponse(value: unknown): ModelBrokerResponse {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ModelReviewError(\"Model broker response must be an object.\", {\n code: \"invalid_broker_response\",\n });\n }\n const response = value as Partial<ModelBrokerResponse>;\n if (response.protocolVersion !== ADVERSARY_MODEL_PROTOCOL_VERSION) {\n throw new ModelReviewError(\n `Model broker protocol version must be ${ADVERSARY_MODEL_PROTOCOL_VERSION}.`,\n { code: \"unsupported_model_protocol\" },\n );\n }\n if (typeof response.provider !== \"string\" || response.provider.trim() === \"\") {\n throw new ModelReviewError(\"Model broker response provider must be a non-empty string.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (typeof response.model !== \"string\" || response.model.trim() === \"\") {\n throw new ModelReviewError(\"Model broker response model must be a non-empty string.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (!Object.hasOwn(response, \"output\")) {\n throw new ModelReviewError(\"Model broker response is missing output.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (response.usage !== undefined) {\n validateUsage(response.usage);\n }\n return response as ModelBrokerResponse;\n}\n\nfunction validateUsage(value: unknown): asserts value is ModelReviewUsage {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ModelReviewError(\"Model broker response usage must be an object.\", {\n code: \"invalid_broker_response\",\n });\n }\n for (const field of [\"inputTokens\", \"outputTokens\"] as const) {\n const count = (value as ModelReviewUsage)[field];\n if (count !== undefined && (!Number.isInteger(count) || count < 0)) {\n throw new ModelReviewError(\n `Model broker response usage.${field} must be a non-negative integer.`,\n {\n code: \"invalid_broker_response\",\n },\n );\n }\n }\n}\n\nfunction validateModelOutput(schema: Record<string, unknown>, output: unknown): void {\n const ajv = new Ajv2020({ allErrors: true, strict: true });\n let validate: ReturnType<Ajv2020[\"compile\"]>;\n try {\n validate = ajv.compile(schema);\n } catch (error) {\n throw new ModelReviewError(\n `Model review schema is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"invalid_model_schema\" },\n );\n }\n if (!validate(output)) {\n const detail = ajv.errorsText(validate.errors, { separator: \"; \" });\n throw new ModelReviewError(`Model output does not match the requested schema: ${detail}`, {\n code: \"invalid_model_output\",\n });\n }\n}\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAO3C,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,4BAA4B,GAAG,0BAA0B,CAAC;AACvE,MAAM,CAAC,MAAM,yBAAyB,GAAG,uBAAuB,CAAC;AAEjE,MAAM,wBAAwB,GAAG,OAAO,CAAC;AACzC,MAAM,oBAAoB,GAAG,OAAO,CAAC;AACrC,MAAM,6BAA6B,GAAG,KAAK,CAAC;AAC5C,MAAM,yBAAyB,GAAG,MAAM,CAAC;AACzC,MAAM,gBAAgB,GAAG,GAAG,IAAI,EAAE,CAAC;AACnC,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,CAAC;AAChC,MAAM,gBAAgB,GAAG,GAAG,IAAI,EAAE,CAAC;AACnC,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,CAAC;AACnC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AAC1C,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAC1C,MAAM,yBAAyB,GAAG,KAAK,CAAC;AAiGxC,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,OAAO,GAAG,2DAA2D;QAC/E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAU;IACd,SAAS,CAAU;IAE5B,YAAY,OAAe,EAAE,UAAkD,EAAE;QAC/E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC9C,CAAC;CACF;AAED,MAAM,UAAU,0BAA0B,CACxC,cAAgC,OAAO,CAAC,GAAG;IAE3C,MAAM,QAAQ,GAAG,WAAW,CAAC,4BAA4B,CAAC,EAAE,IAAI,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,WAAW,CAAC,yBAAyB,CAAC,EAAE,IAAI,EAAE,CAAC;IAC7D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QACrF,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,KAAK,CAAC,MAAM;YACV,MAAM,IAAI,qBAAqB,EAAE,CAAC;QACpC,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,OAAO,iBAAiB;IACnB,QAAQ,CAAS;IACjB,MAAM,CAAS;IACf,gBAAgB,CAAS;IACzB,oBAAoB,CAAS;IAC7B,OAAO,CAAe;IAE/B,YAAY,QAAgB,EAAE,KAAa,EAAE,UAAoC,EAAE;QACjF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;QACjC,IACE,MAAM,CAAC,QAAQ,KAAK,OAAO;YAC3B,CAAC,MAAM,CAAC,QAAQ,KAAK,WAAW;gBAC9B,MAAM,CAAC,QAAQ,KAAK,KAAK;gBACzB,MAAM,CAAC,QAAQ,KAAK,OAAO;gBAC3B,MAAM,CAAC,QAAQ,KAAK,WAAW,CAAC,EAClC,CAAC;YACD,MAAM,IAAI,gBAAgB,CACxB,0EAA0E,EAC1E,EAAE,IAAI,EAAE,yBAAyB,EAAE,CACpC,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,gBAAgB,CAAC,2CAA2C,EAAE;gBACtE,IAAI,EAAE,sBAAsB;aAC7B,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,+BAA+B,CAAC;QACnF,MAAM,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,IAAI,6BAA6B,CAAC;QACzF,mBAAmB,CAAC,eAAe,EAAE,iBAAiB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9D,mBAAmB,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,CAAC,EAAE,yBAAyB,CAAC,CAAC;QAC9F,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,MAAM,CAAc,OAA2B;QACnD,IAAI,OAAO,CAAC,KAAK,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;YAC5C,MAAM,IAAI,gBAAgB,CACxB,0FAA0F,EAC1F,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAClC,CAAC;QACJ,CAAC;QACD,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAClF,IAAI,CAAC;YACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;gBACrE,IAAI,CAAC;oBACH,OAAO,MAAM,IAAI,CAAC,WAAW,CAAI,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;gBAClE,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IACE,CAAC,CAAC,KAAK,YAAY,gBAAgB,CAAC;wBACpC,CAAC,KAAK,CAAC,SAAS;wBAChB,UAAU,CAAC,MAAM,CAAC,OAAO;wBACzB,OAAO,KAAK,IAAI,CAAC,gBAAgB,EACjC,CAAC;wBACD,MAAM,KAAK,CAAC;oBACd,CAAC;oBACD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,yBAAyB,EACzB,IAAI,CAAC,oBAAoB,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAC/C,CAAC;oBACF,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBACzE,MAAM,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAC/E,CAAC;YACH,CAAC;YACD,MAAM,IAAI,gBAAgB,CAAC,iDAAiD,EAAE;gBAC5E,IAAI,EAAE,oBAAoB;gBAC1B,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC;QACL,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CACf,UAAwC,EACxC,MAAmB;QAEnB,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE;gBACpC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,MAAM,EAAE,kBAAkB;oBAC1B,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;oBACtC,cAAc,EAAE,kBAAkB;oBAClC,4BAA4B,EAAE,MAAM,CAAC,gCAAgC,CAAC;iBACvE;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,eAAe,EAAE,gCAAgC;oBACjD,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,KAAK,EAAE,UAAU,CAAC,KAAK;oBACvB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;iBACG,CAAC;gBAC/B,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,iBAAiB,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,IAAI,gBAAgB,CACxB,gCAAgC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACxF,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,IAAI,EAAE,CAChD,CAAC;QACJ,CAAC;QAED,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,MAAM,iBAAiB,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACvD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,gBAAgB,CAAC,uCAAuC,EAAE;gBAClE,IAAI,EAAE,yBAAyB;aAChC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,OAAmC,CAAC;YACpD,MAAM,IAAI,gBAAgB,CACxB,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,8BAA8B,QAAQ,CAAC,MAAM,GAAG,EAC1E;gBACE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,IAAI,qBAAqB;gBAClD,SAAS,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG;aAC9D,CACF,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAChD,mBAAmB,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO;YACL,MAAM,EAAE,QAAQ,CAAC,MAAW;YAC5B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;SACnE,CAAC;IACJ,CAAC;CACF;AAED,KAAK,UAAU,YAAY,CACzB,OAAe,EACf,MAAmB,EACnB,SAAiB;IAEjB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,OAAO,EAAE,CAAC;QACZ,CAAC,EAAE,OAAO,CAAC,CAAC;QACZ,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB;IAC1C,OAAO,IAAI,gBAAgB,CAAC,6BAA6B,SAAS,aAAa,EAAE;QAC/E,IAAI,EAAE,eAAe;QACrB,SAAS,EAAE,IAAI;KAChB,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,OAA2B;IACnD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,IAAI,gBAAgB,CAAC,yCAAyC,EAAE;YACpE,IAAI,EAAE,uBAAuB;SAC9B,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACvE,MAAM,IAAI,gBAAgB,CAAC,iDAAiD,EAAE;YAC5E,IAAI,EAAE,uBAAuB;SAC9B,CAAC,CAAC;IACL,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,IAAI,WAAW,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,IAAI,gBAAgB,CAAC,+BAA+B,gBAAgB,SAAS,EAAE;YACnF,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,eAAe,CAAC,CAAC;IACzD,IACE,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ;QAClC,OAAO,CAAC,MAAM,KAAK,IAAI;QACvB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAC7B,CAAC;QACD,MAAM,IAAI,gBAAgB,CAAC,mDAAmD,EAAE;YAC9E,IAAI,EAAE,sBAAsB;SAC7B,CAAC,CAAC;IACL,CAAC;IACD,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAE5D,MAAM,mBAAmB,GAAG,OAAO,CAAC,MAAM,EAAE,mBAAmB,IAAI,6BAA6B,CAAC;IACjG,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,wBAAwB,CAAC;IACxE,mBAAmB,CACjB,mBAAmB,EACnB,4BAA4B,EAC5B,CAAC,EACD,yBAAyB,CAC1B,CAAC;IACF,mBAAmB,CAAC,SAAS,EAAE,kBAAkB,EAAE,CAAC,EAAE,oBAAoB,CAAC,CAAC;IAC5E,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,EAAE,mBAAmB,EAAE,SAAS,EAAE;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAc,EAAE,IAAY,EAAE,OAAe;IACpE,IAAI,OAA2B,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,gBAAgB,CACxB,gBAAgB,IAAI,+BAA+B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC3G,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAClC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,IAAI,6BAA6B,EAAE;YAC5E,IAAI,EAAE,uBAAuB;SAC9B,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,IAAI,YAAY,OAAO,SAAS,EAAE;YAC3E,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,IAAY,EAAE,OAAe,EAAE,OAAe;IACxF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,OAAO,IAAI,KAAK,GAAG,OAAO,EAAE,CAAC;QACnE,MAAM,IAAI,gBAAgB,CAAC,GAAG,IAAI,4BAA4B,OAAO,YAAY,OAAO,GAAG,EAAE;YAC3F,IAAI,EAAE,sBAAsB;SAC7B,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,QAAkB;IACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACxD,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,kBAAkB,EAAE,CAAC;QAC/D,MAAM,IAAI,gBAAgB,CAAC,iCAAiC,kBAAkB,SAAS,EAAE;YACvF,IAAI,EAAE,0BAA0B;SACjC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,SAAS,CAAC;QACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI,EAAE,CAAC;YACT,MAAM;QACR,CAAC;QACD,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;QACzB,IAAI,IAAI,GAAG,kBAAkB,EAAE,CAAC;YAC9B,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACtB,MAAM,IAAI,gBAAgB,CAAC,iCAAiC,kBAAkB,SAAS,EAAE;gBACvF,IAAI,EAAE,0BAA0B;aACjC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,gBAAgB,CAAC,0CAA0C,EAAE;YACrE,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,MAAM,QAAQ,GAAG,KAAqC,CAAC;IACvD,IAAI,QAAQ,CAAC,eAAe,KAAK,gCAAgC,EAAE,CAAC;QAClE,MAAM,IAAI,gBAAgB,CACxB,yCAAyC,gCAAgC,GAAG,EAC5E,EAAE,IAAI,EAAE,4BAA4B,EAAE,CACvC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7E,MAAM,IAAI,gBAAgB,CAAC,4DAA4D,EAAE;YACvF,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,QAAQ,CAAC,KAAK,KAAK,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACvE,MAAM,IAAI,gBAAgB,CAAC,yDAAyD,EAAE;YACpF,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;QACvC,MAAM,IAAI,gBAAgB,CAAC,0CAA0C,EAAE;YACrE,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACjC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,QAA+B,CAAC;AACzC,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,IAAI,gBAAgB,CAAC,gDAAgD,EAAE;YAC3E,IAAI,EAAE,yBAAyB;SAChC,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,aAAa,EAAE,cAAc,CAAU,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAI,KAA0B,CAAC,KAAK,CAAC,CAAC;QACjD,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;YACnE,MAAM,IAAI,gBAAgB,CACxB,+BAA+B,KAAK,kCAAkC,EACtE;gBACE,IAAI,EAAE,yBAAyB;aAChC,CACF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,MAA+B,EAAE,MAAe;IAC3E,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,IAAI,QAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,gBAAgB,CACxB,mCAAmC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC3F,EAAE,IAAI,EAAE,sBAAsB,EAAE,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,IAAI,gBAAgB,CAAC,qDAAqD,MAAM,EAAE,EAAE;YACxF,IAAI,EAAE,sBAAsB;SAC7B,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["import { Ajv2020 } from \"ajv/dist/2020.js\";\nimport type {\n ModelRepositoryCitation,\n ModelRepositoryRetrieval,\n ModelRepositoryToolOptions,\n} from \"./repository-model.js\";\n\nexport const ADVERSARY_MODEL_PROTOCOL_VERSION = 1;\nexport const ADVERSARY_MODEL_ENDPOINT_ENV = \"ADVERSARY_MODEL_ENDPOINT\";\nexport const ADVERSARY_MODEL_TOKEN_ENV = \"ADVERSARY_MODEL_TOKEN\";\n\nconst DEFAULT_MODEL_TIMEOUT_MS = 120_000;\nconst MAX_MODEL_TIMEOUT_MS = 600_000;\nconst DEFAULT_MAXIMUM_OUTPUT_TOKENS = 8_192;\nconst MAX_MAXIMUM_OUTPUT_TOKENS = 65_536;\nconst MAX_PROMPT_BYTES = 256 << 10;\nconst MAX_INPUT_BYTES = 4 << 20;\nconst MAX_SCHEMA_BYTES = 512 << 10;\nconst MAX_RESPONSE_BYTES = 4 << 20;\nconst DEFAULT_BROKER_MAXIMUM_ATTEMPTS = 3;\nconst DEFAULT_BROKER_RETRY_DELAY_MS = 250;\nconst MAX_BROKER_RETRY_DELAY_MS = 5_000;\n\nexport interface ModelReviewBudget {\n maximumOutputTokens?: number;\n timeoutMs?: number;\n}\n\nexport interface ModelReviewRequest {\n prompt: string;\n input: unknown;\n schema: Record<string, unknown>;\n budget?: ModelReviewBudget;\n tools?: {\n repository: ModelRepositoryToolOptions;\n };\n}\n\nexport interface ModelReviewUsage {\n inputTokens?: number;\n outputTokens?: number;\n}\n\nexport interface ModelReviewResult<T = unknown> {\n output: T;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n citations?: readonly ModelRepositoryCitation[];\n retrieval?: ModelRepositoryRetrieval;\n}\n\nexport interface ReviewModel {\n review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>>;\n}\n\nexport interface BrokerReviewModelOptions {\n maximumAttempts?: number;\n initialRetryDelayMs?: number;\n random?: () => number;\n}\n\n/**\n * Request a short noun-phrase concern suitable after \"I would address …\".\n * Implemented by the SDK via {@link ReviewModel.review} (CLI broker pass-through).\n */\nexport interface ModelConcernRequest {\n /** Free-form title, clause, or draft concern to rewrite. */\n text: string;\n budget?: ModelReviewBudget;\n /**\n * Extra attempts when the model returns a phrase that fails noun-phrase validation.\n * Defaults to 1 retry (2 total attempts).\n */\n maxAttempts?: number;\n}\n\nexport interface ModelConcernResult {\n /** Validated noun phrase (see requireOpinionConcern). */\n concern: string;\n /** False when `text` was already a valid noun phrase (no broker call). */\n rewritten: boolean;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n}\n\n/** Rule-context model: broker review plus opinion-concern rewrite. */\nexport type ContextualReviewModel = ReviewModel & {\n concern(request: ModelConcernRequest): Promise<ModelConcernResult>;\n};\n\nexport type ModelEnvironment = Readonly<Record<string, string | undefined>>;\n\ninterface ModelBrokerRequest extends ModelReviewRequest {\n protocolVersion: typeof ADVERSARY_MODEL_PROTOCOL_VERSION;\n}\n\ninterface ModelBrokerResponse {\n protocolVersion: typeof ADVERSARY_MODEL_PROTOCOL_VERSION;\n output: unknown;\n provider: string;\n model: string;\n usage?: ModelReviewUsage;\n}\n\ninterface ModelBrokerErrorResponse {\n error?: {\n code?: string;\n message?: string;\n retryable?: boolean;\n };\n}\n\ntype NormalizedModelReviewRequest = Omit<ModelReviewRequest, \"budget\"> & {\n budget: Required<ModelReviewBudget>;\n};\n\nexport class ModelUnavailableError extends Error {\n constructor(message = \"Model review is unavailable for this adversary execution.\") {\n super(message);\n this.name = \"ModelUnavailableError\";\n }\n}\n\nexport class ModelReviewError extends Error {\n readonly code?: string;\n readonly retryable: boolean;\n\n constructor(message: string, options: { code?: string; retryable?: boolean } = {}) {\n super(message);\n this.name = \"ModelReviewError\";\n this.code = options.code;\n this.retryable = options.retryable ?? false;\n }\n}\n\nexport function createModelFromEnvironment(\n environment: ModelEnvironment = process.env,\n): ReviewModel {\n const endpoint = environment[ADVERSARY_MODEL_ENDPOINT_ENV]?.trim();\n const token = environment[ADVERSARY_MODEL_TOKEN_ENV]?.trim();\n if (endpoint === undefined || endpoint === \"\" || token === undefined || token === \"\") {\n return unavailableModel();\n }\n return new BrokerReviewModel(endpoint, token);\n}\n\nexport function unavailableModel(): ReviewModel {\n return Object.freeze({\n async review(): Promise<never> {\n throw new ModelUnavailableError();\n },\n });\n}\n\nexport class BrokerReviewModel implements ReviewModel {\n readonly endpoint: string;\n readonly #token: string;\n readonly #maximumAttempts: number;\n readonly #initialRetryDelayMs: number;\n readonly #random: () => number;\n\n constructor(endpoint: string, token: string, options: BrokerReviewModelOptions = {}) {\n const parsed = new URL(endpoint);\n if (\n parsed.protocol !== \"http:\" ||\n (parsed.hostname !== \"127.0.0.1\" &&\n parsed.hostname !== \"::1\" &&\n parsed.hostname !== \"[::1]\" &&\n parsed.hostname !== \"localhost\")\n ) {\n throw new ModelReviewError(\n \"The model broker endpoint must use HTTP on the local loopback interface.\",\n { code: \"invalid_broker_endpoint\" },\n );\n }\n if (token.trim() === \"\") {\n throw new ModelReviewError(\"The model broker token must not be empty.\", {\n code: \"invalid_broker_token\",\n });\n }\n this.endpoint = parsed.toString();\n this.#token = token;\n const maximumAttempts = options.maximumAttempts ?? DEFAULT_BROKER_MAXIMUM_ATTEMPTS;\n const initialRetryDelayMs = options.initialRetryDelayMs ?? DEFAULT_BROKER_RETRY_DELAY_MS;\n requireIntegerRange(maximumAttempts, \"maximumAttempts\", 1, 5);\n requireIntegerRange(initialRetryDelayMs, \"initialRetryDelayMs\", 0, MAX_BROKER_RETRY_DELAY_MS);\n this.#maximumAttempts = maximumAttempts;\n this.#initialRetryDelayMs = initialRetryDelayMs;\n this.#random = options.random ?? Math.random;\n }\n\n async review<T = unknown>(request: ModelReviewRequest): Promise<ModelReviewResult<T>> {\n if (request.tools?.repository !== undefined) {\n throw new ModelReviewError(\n \"Repository model tools require ctx.model so the SDK can enforce the repository boundary.\",\n { code: \"invalid_model_request\" },\n );\n }\n const normalized = normalizeRequest(request);\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), normalized.budget.timeoutMs);\n try {\n for (let attempt = 1; attempt <= this.#maximumAttempts; attempt += 1) {\n try {\n return await this.#reviewOnce<T>(normalized, controller.signal);\n } catch (error) {\n if (\n !(error instanceof ModelReviewError) ||\n !error.retryable ||\n controller.signal.aborted ||\n attempt === this.#maximumAttempts\n ) {\n throw error;\n }\n const exponential = Math.min(\n MAX_BROKER_RETRY_DELAY_MS,\n this.#initialRetryDelayMs * 2 ** (attempt - 1),\n );\n const jittered = Math.round(exponential * (0.75 + 0.5 * this.#random()));\n await waitForRetry(jittered, controller.signal, normalized.budget.timeoutMs);\n }\n }\n throw new ModelReviewError(\"Model broker retry loop exhausted unexpectedly.\", {\n code: \"broker_unavailable\",\n retryable: true,\n });\n } finally {\n clearTimeout(timeout);\n }\n }\n\n async #reviewOnce<T>(\n normalized: NormalizedModelReviewRequest,\n signal: AbortSignal,\n ): Promise<ModelReviewResult<T>> {\n let response: Response;\n try {\n response = await fetch(this.endpoint, {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n authorization: `Bearer ${this.#token}`,\n \"content-type\": \"application/json\",\n \"x-adversary-model-protocol\": String(ADVERSARY_MODEL_PROTOCOL_VERSION),\n },\n body: JSON.stringify({\n protocolVersion: ADVERSARY_MODEL_PROTOCOL_VERSION,\n prompt: normalized.prompt,\n input: normalized.input,\n schema: normalized.schema,\n budget: normalized.budget,\n } satisfies ModelBrokerRequest),\n signal,\n });\n } catch (error) {\n if (signal.aborted) {\n throw modelTimeoutError(normalized.budget.timeoutMs);\n }\n throw new ModelReviewError(\n `Model broker request failed: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"broker_unavailable\", retryable: true },\n );\n }\n\n let body: string;\n try {\n body = await readBoundedResponse(response);\n } catch (error) {\n if (signal.aborted) {\n throw modelTimeoutError(normalized.budget.timeoutMs);\n }\n throw error;\n }\n let decoded: unknown;\n try {\n decoded = JSON.parse(body);\n } catch {\n throw new ModelReviewError(\"Model broker returned malformed JSON.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (!response.ok) {\n const failure = decoded as ModelBrokerErrorResponse;\n throw new ModelReviewError(\n failure.error?.message ?? `Model broker returned HTTP ${response.status}.`,\n {\n code: failure.error?.code ?? \"model_review_failed\",\n retryable: failure.error?.retryable ?? response.status >= 500,\n },\n );\n }\n\n const envelope = requireBrokerResponse(decoded);\n validateModelOutput(normalized.schema, envelope.output);\n return {\n output: envelope.output as T,\n provider: envelope.provider,\n model: envelope.model,\n ...(envelope.usage === undefined ? {} : { usage: envelope.usage }),\n };\n }\n}\n\nasync function waitForRetry(\n delayMs: number,\n signal: AbortSignal,\n timeoutMs: number,\n): Promise<void> {\n if (signal.aborted) {\n throw modelTimeoutError(timeoutMs);\n }\n await new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(modelTimeoutError(timeoutMs));\n };\n const timer = setTimeout(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n }, delayMs);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction modelTimeoutError(timeoutMs: number): ModelReviewError {\n return new ModelReviewError(`Model review exceeded its ${timeoutMs}ms timeout.`, {\n code: \"model_timeout\",\n retryable: true,\n });\n}\n\nfunction normalizeRequest(request: ModelReviewRequest): NormalizedModelReviewRequest {\n if (typeof request !== \"object\" || request === null) {\n throw new ModelReviewError(\"Model review request must be an object.\", {\n code: \"invalid_model_request\",\n });\n }\n if (typeof request.prompt !== \"string\" || request.prompt.trim() === \"\") {\n throw new ModelReviewError(\"Model review prompt must be a non-empty string.\", {\n code: \"invalid_model_request\",\n });\n }\n const promptBytes = Buffer.byteLength(request.prompt, \"utf8\");\n if (promptBytes > MAX_PROMPT_BYTES) {\n throw new ModelReviewError(`Model review prompt exceeds ${MAX_PROMPT_BYTES} bytes.`, {\n code: \"model_request_too_large\",\n });\n }\n requireJsonSize(request.input, \"input\", MAX_INPUT_BYTES);\n if (\n typeof request.schema !== \"object\" ||\n request.schema === null ||\n Array.isArray(request.schema)\n ) {\n throw new ModelReviewError(\"Model review schema must be a JSON Schema object.\", {\n code: \"invalid_model_schema\",\n });\n }\n requireJsonSize(request.schema, \"schema\", MAX_SCHEMA_BYTES);\n\n const maximumOutputTokens = request.budget?.maximumOutputTokens ?? DEFAULT_MAXIMUM_OUTPUT_TOKENS;\n const timeoutMs = request.budget?.timeoutMs ?? DEFAULT_MODEL_TIMEOUT_MS;\n requireIntegerRange(\n maximumOutputTokens,\n \"budget.maximumOutputTokens\",\n 1,\n MAX_MAXIMUM_OUTPUT_TOKENS,\n );\n requireIntegerRange(timeoutMs, \"budget.timeoutMs\", 1, MAX_MODEL_TIMEOUT_MS);\n return {\n prompt: request.prompt,\n input: request.input,\n schema: request.schema,\n budget: { maximumOutputTokens, timeoutMs },\n };\n}\n\nfunction requireJsonSize(value: unknown, name: string, maximum: number): void {\n let encoded: string | undefined;\n try {\n encoded = JSON.stringify(value);\n } catch (error) {\n throw new ModelReviewError(\n `Model review ${name} must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"invalid_model_request\" },\n );\n }\n if (encoded === undefined) {\n throw new ModelReviewError(`Model review ${name} must be JSON-serializable.`, {\n code: \"invalid_model_request\",\n });\n }\n if (Buffer.byteLength(encoded, \"utf8\") > maximum) {\n throw new ModelReviewError(`Model review ${name} exceeds ${maximum} bytes.`, {\n code: \"model_request_too_large\",\n });\n }\n}\n\nfunction requireIntegerRange(value: number, name: string, minimum: number, maximum: number): void {\n if (!Number.isInteger(value) || value < minimum || value > maximum) {\n throw new ModelReviewError(`${name} must be an integer from ${minimum} through ${maximum}.`, {\n code: \"invalid_model_budget\",\n });\n }\n}\n\nasync function readBoundedResponse(response: Response): Promise<string> {\n const declared = response.headers.get(\"content-length\");\n if (declared !== null && Number(declared) > MAX_RESPONSE_BYTES) {\n throw new ModelReviewError(`Model broker response exceeds ${MAX_RESPONSE_BYTES} bytes.`, {\n code: \"model_response_too_large\",\n });\n }\n if (response.body === null) {\n return \"\";\n }\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let size = 0;\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n size += value.byteLength;\n if (size > MAX_RESPONSE_BYTES) {\n await reader.cancel();\n throw new ModelReviewError(`Model broker response exceeds ${MAX_RESPONSE_BYTES} bytes.`, {\n code: \"model_response_too_large\",\n });\n }\n chunks.push(value);\n }\n const joined = new Uint8Array(size);\n let offset = 0;\n for (const chunk of chunks) {\n joined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(joined);\n}\n\nfunction requireBrokerResponse(value: unknown): ModelBrokerResponse {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ModelReviewError(\"Model broker response must be an object.\", {\n code: \"invalid_broker_response\",\n });\n }\n const response = value as Partial<ModelBrokerResponse>;\n if (response.protocolVersion !== ADVERSARY_MODEL_PROTOCOL_VERSION) {\n throw new ModelReviewError(\n `Model broker protocol version must be ${ADVERSARY_MODEL_PROTOCOL_VERSION}.`,\n { code: \"unsupported_model_protocol\" },\n );\n }\n if (typeof response.provider !== \"string\" || response.provider.trim() === \"\") {\n throw new ModelReviewError(\"Model broker response provider must be a non-empty string.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (typeof response.model !== \"string\" || response.model.trim() === \"\") {\n throw new ModelReviewError(\"Model broker response model must be a non-empty string.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (!Object.hasOwn(response, \"output\")) {\n throw new ModelReviewError(\"Model broker response is missing output.\", {\n code: \"invalid_broker_response\",\n });\n }\n if (response.usage !== undefined) {\n validateUsage(response.usage);\n }\n return response as ModelBrokerResponse;\n}\n\nfunction validateUsage(value: unknown): asserts value is ModelReviewUsage {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ModelReviewError(\"Model broker response usage must be an object.\", {\n code: \"invalid_broker_response\",\n });\n }\n for (const field of [\"inputTokens\", \"outputTokens\"] as const) {\n const count = (value as ModelReviewUsage)[field];\n if (count !== undefined && (!Number.isInteger(count) || count < 0)) {\n throw new ModelReviewError(\n `Model broker response usage.${field} must be a non-negative integer.`,\n {\n code: \"invalid_broker_response\",\n },\n );\n }\n }\n}\n\nfunction validateModelOutput(schema: Record<string, unknown>, output: unknown): void {\n const ajv = new Ajv2020({ allErrors: true, strict: true });\n let validate: ReturnType<Ajv2020[\"compile\"]>;\n try {\n validate = ajv.compile(schema);\n } catch (error) {\n throw new ModelReviewError(\n `Model review schema is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { code: \"invalid_model_schema\" },\n );\n }\n if (!validate(output)) {\n const detail = ajv.errorsText(validate.errors, { separator: \"; \" });\n throw new ModelReviewError(`Model output does not match the requested schema: ${detail}`, {\n code: \"invalid_model_output\",\n });\n }\n}\n"]}
@@ -0,0 +1,114 @@
1
+ export declare const ADVERSARY_REPO_GRAPH_ENV = "ADVERSARY_REPO_GRAPH";
2
+ export declare const REPO_GRAPH_SCHEMA_VERSION = "v2";
3
+ export declare const REPO_GRAPH_ADAPTER_REVISION = "go-ast-v1+ts-syntax-v1";
4
+ export interface RepoGraphMeta {
5
+ schemaVersion: string;
6
+ adapterRevision: string;
7
+ fingerprint: string;
8
+ repoPath: string;
9
+ builtAt: string;
10
+ durationMs: number;
11
+ fileCount: number;
12
+ symbolCount: number;
13
+ edgeCount: number;
14
+ testLinkCount: number;
15
+ parseFailures?: readonly RepoGraphDiagnostic[];
16
+ }
17
+ export interface RepoGraphDiagnostic {
18
+ path: string;
19
+ adapter: string;
20
+ message: string;
21
+ }
22
+ export interface RepoGraphFile {
23
+ id: number;
24
+ path: string;
25
+ language: string;
26
+ size: number;
27
+ hash: string;
28
+ module?: string;
29
+ }
30
+ export interface RepoGraphSymbol {
31
+ id: number;
32
+ name: string;
33
+ kind: string;
34
+ path: string;
35
+ startLine: number;
36
+ startColumn: number;
37
+ endLine: number;
38
+ endColumn: number;
39
+ containerId?: number;
40
+ exported: boolean;
41
+ language: string;
42
+ metadata?: string;
43
+ }
44
+ export interface RepoGraphEdge {
45
+ id: number;
46
+ fromPath: string;
47
+ fromSymbolId?: number;
48
+ toPath?: string;
49
+ toSymbolId?: number;
50
+ unresolvedTarget?: string;
51
+ kind: string;
52
+ line: number;
53
+ column: number;
54
+ confidence: number;
55
+ adapter: string;
56
+ }
57
+ export interface RepoGraphTestLink {
58
+ sourcePath: string;
59
+ sourceSymbolId?: number;
60
+ testPath: string;
61
+ testSymbolId?: number;
62
+ confidence: number;
63
+ reason: string;
64
+ }
65
+ export interface RepoGraphPage<T> {
66
+ items: readonly T[];
67
+ nextCursor?: string;
68
+ }
69
+ export interface RepoGraphFileQuery {
70
+ language?: string;
71
+ glob?: string;
72
+ cursor?: string;
73
+ limit?: number;
74
+ }
75
+ export interface RepoGraphSymbolQuery {
76
+ path?: string;
77
+ name?: string;
78
+ kind?: string;
79
+ cursor?: string;
80
+ limit?: number;
81
+ }
82
+ export interface RepoGraphRelationQuery {
83
+ symbolId: number;
84
+ cursor?: string;
85
+ limit?: number;
86
+ }
87
+ export interface RepoGraph {
88
+ readonly dir: string;
89
+ readonly meta: RepoGraphMeta;
90
+ files(query?: RepoGraphFileQuery): RepoGraphPage<RepoGraphFile>;
91
+ symbolAt(path: string, line: number, column?: number): RepoGraphSymbol | undefined;
92
+ symbols(query?: RepoGraphSymbolQuery): RepoGraphPage<RepoGraphSymbol>;
93
+ definitions(query: RepoGraphSymbolQuery): RepoGraphPage<RepoGraphSymbol>;
94
+ references(query: RepoGraphRelationQuery): RepoGraphPage<RepoGraphEdge>;
95
+ callers(query: RepoGraphRelationQuery): RepoGraphPage<RepoGraphEdge>;
96
+ callees(query: RepoGraphRelationQuery): RepoGraphPage<RepoGraphEdge>;
97
+ implementations(query: RepoGraphRelationQuery): RepoGraphPage<RepoGraphEdge>;
98
+ importsOf(path: string, cursor?: string, limit?: number): RepoGraphPage<RepoGraphEdge>;
99
+ importersOf(path: string, cursor?: string, limit?: number): RepoGraphPage<RepoGraphEdge>;
100
+ relatedTests(options: {
101
+ path?: string;
102
+ symbolId?: number;
103
+ cursor?: string;
104
+ limit?: number;
105
+ }): RepoGraphPage<RepoGraphTestLink>;
106
+ close(): void;
107
+ }
108
+ export declare class RepoGraphUnavailableError extends Error {
109
+ readonly code = "repo_graph_unavailable";
110
+ constructor(message: string);
111
+ }
112
+ export declare function openRepoGraph(dir: string): Promise<RepoGraph>;
113
+ export declare function repoGraphFromEnvironment(env?: Record<string, string | undefined>): Promise<RepoGraph | null>;
114
+ //# sourceMappingURL=repo-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-graph.d.ts","sourceRoot":"","sources":["../src/repo-graph.ts"],"names":[],"mappings":"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"}