{"_id":"@alice-io/wonderfence-ts-sdk","_rev":"4-4f664fadad0f4bcf4236ce681a8775a8","name":"@alice-io/wonderfence-ts-sdk","dist-tags":{"latest":"3.0.0"},"versions":{"1.0.0":{"name":"@alice-io/wonderfence-ts-sdk","version":"1.0.0","keywords":["wonderfence","alice","trust-and-safety","content-moderation","ai-safety","llm","typescript"],"author":{"name":"Alice"},"license":"MIT","_id":"@alice-io/wonderfence-ts-sdk@1.0.0","maintainers":[{"name":"alice-devops","email":"devops@alice.io"},{"name":"iftachalice","email":"iftach@alice.io"}],"dist":{"shasum":"22559a97933214cae91613d948b481682b9eab06","tarball":"https://registry.npmjs.org/@alice-io/wonderfence-ts-sdk/-/wonderfence-ts-sdk-1.0.0.tgz","fileCount":31,"integrity":"sha512-p13pWBiTxaNdMcT70v6Gzd8rA04tnOhsBuXw2elG5lGR7yqs/no4W0g1NTtxGynSwAruExCFAo9Ye3YHCn9A+w==","signatures":[{"sig":"MEUCIQDYDzZ4LwPGEM/oig03Q7/RDoWsv9YvZycvPQ587kBj1AIgCMBDGFXGzd5aMpFE4jjmvBLQ8fK4Fvsq9ocpfMjmySw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":61594},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"14caed265f4f98e1a2988e21e8adf84605a14368","scripts":{"lint":"eslint . --ext .ts","test":"jest","format":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint . --ext .ts --fix","build-lib":"tsc -p tsconfig.build.json","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"pnpm run build-lib"},"_npmUser":{"name":"alice-devops","email":"devops@alice.io"},"_npmVersion":"10.8.2","description":"TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses","directories":{},"_nodeVersion":"18.20.8","dependencies":{"zod":"^3.24.0","uuid":"^11.0.0","axios":"^1.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.4.6","prettier":"^3.8.1","typescript":"^5.9.3","@types/jest":"^29.5.0","@types/node":"^22.0.0","@typescript-eslint/parser":"^8.57.0","@typescript-eslint/eslint-plugin":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/wonderfence-ts-sdk_1.0.0_1774369691310_0.2777865162926991","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alice-io/wonderfence-ts-sdk","version":"1.0.1","keywords":["wonderfence","alice","trust-and-safety","content-moderation","ai-safety","llm","typescript"],"author":{"name":"Alice"},"license":"MIT","_id":"@alice-io/wonderfence-ts-sdk@1.0.1","maintainers":[{"name":"alice-devops","email":"devops@alice.io"},{"name":"iftachalice","email":"iftach@alice.io"}],"dist":{"shasum":"c20b4ef5579eb95c7b8bf9dc4ba7794396495396","tarball":"https://registry.npmjs.org/@alice-io/wonderfence-ts-sdk/-/wonderfence-ts-sdk-1.0.1.tgz","fileCount":39,"integrity":"sha512-wvJfSg9rues/kq9QpFZkX66aZJulLSZDeGpdIP7VLLsZhA/ws7aky4W4bsV2A0L9h3VGZ2NwFyABDsC5fZMvOQ==","signatures":[{"sig":"MEUCIQDg0qB3msIe6UdV2i9ymFHpxdy6zYvfBSnXwJm6TzV8DAIgbhJBqypO9L+sOI6YkWmyS3uLfiq2xEm4cVwAK8yZ5bU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92926},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"12e40c776631770e4c1b4b8844154c56b3bc6c0e","scripts":{"lint":"eslint . --ext .ts","test":"jest","format":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint . --ext .ts --fix","build-lib":"tsc -p tsconfig.build.json","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"pnpm run build-lib"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:da1c80f5-6325-4b87-98d6-798b18c374d4"}},"_npmVersion":"11.13.0","description":"TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses","directories":{},"_nodeVersion":"24.14.1","dependencies":{"zod":"^3.24.0","uuid":"^11.0.0","axios":"^1.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.0.0","jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.4.6","prettier":"^3.8.1","typescript":"^5.9.3","@types/jest":"^29.5.0","@types/node":"^22.0.0","ajv-formats":"^3.0.0","@typescript-eslint/parser":"^8.57.0","@typescript-eslint/eslint-plugin":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/wonderfence-ts-sdk_1.0.1_1776952414498_0.9694356742526924","host":"s3://npm-registry-packages-npm-production"}},"2.1.0":{"name":"@alice-io/wonderfence-ts-sdk","version":"2.1.0","keywords":["wonderfence","alice","trust-and-safety","content-moderation","ai-safety","llm","typescript"],"author":{"name":"Alice"},"license":"MIT","_id":"@alice-io/wonderfence-ts-sdk@2.1.0","maintainers":[{"name":"alice-devops","email":"devops@alice.io"},{"name":"iftachalice","email":"iftach@alice.io"}],"dist":{"shasum":"0992fbcd6109dadb397f648d2afdb734f360feb4","tarball":"https://registry.npmjs.org/@alice-io/wonderfence-ts-sdk/-/wonderfence-ts-sdk-2.1.0.tgz","fileCount":39,"integrity":"sha512-lYYJ9UrhhFXi7c0YanlYKmDCHdeZ7nQHbx28iR/fYZnrGGpLAmAX/3ZiEB/QSRjDT6gUNb1ZI/pSXw9ftTCBzA==","signatures":[{"sig":"MEUCIHs0zAvhOXDQD3XnXHdnc8QLmY7zP+kI755j8DKZErC2AiEA8duvlD89y2mpm0BwzLQ/0nMp4lPvEo8+2HRAbqqf8JY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":93019},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"8bd45df4ff60cd3fbf8499ffa87b345b59dbe7af","scripts":{"lint":"eslint . --ext .ts","test":"jest","format":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint . --ext .ts --fix","build-lib":"tsc -p tsconfig.build.json","fetch-spec":"./scripts/fetch-spec.sh","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"pnpm run build-lib"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:da1c80f5-6325-4b87-98d6-798b18c374d4"}},"_npmVersion":"12.0.2","description":"TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^3.24.0","uuid":"^11.0.0","axios":"^1.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.0.0","jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.4.6","prettier":"^3.8.1","typescript":"^5.9.3","@types/jest":"^29.5.0","@types/node":"^22.0.0","ajv-formats":"^3.0.0","@typescript-eslint/parser":"^8.57.0","@typescript-eslint/eslint-plugin":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/wonderfence-ts-sdk_2.1.0_1785768064152_0.30537708256564033","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"_id":"@alice-io/wonderfence-ts-sdk@3.0.0","dist":{"shasum":"07da16a9d9cf296c7cf3a8de4ee2514bf08f0e32","tarball":"https://registry.npmjs.org/@alice-io/wonderfence-ts-sdk/-/wonderfence-ts-sdk-3.0.0.tgz","fileCount":39,"integrity":"sha512-hD55U8T7HR82cRsmUvVn7somF3IAX7TngWMebOd98/DJakPBsAJLTjLq+8/PEN5Z7fMmhYzfMfDuqOQ6tup08A==","signatures":[{"sig":"MEYCIQDmEccVrKfY+HyJ5rcVtGU7XTmlNUPr6Vzgc++pfqNGIQIhAKbJCesubfRMYrD1L+pUPbym2kd7O1FdJh27uN7uLmPy","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCfKtwghkCDxPyduqawDowaNepV23SBPem+5ijVV0sVJQIhAO078fj1GYzemALJbAckcCgFcA3Y1x8iqko7GsdJO+ny"}],"unpackedSize":95249},"main":"dist/index.js","name":"@alice-io/wonderfence-ts-sdk","types":"dist/index.d.ts","author":{"name":"Alice"},"engines":{"node":">=18.0.0"},"gitHead":"2d99d7dbc0e28d7a460ccc3ff1c8f93194e10382","license":"MIT","scripts":{"lint":"eslint . --ext .ts","test":"jest","format":"prettier --write \"src/**/*.ts\" \"tests/**/*.ts\"","lint:fix":"eslint . --ext .ts --fix","build-lib":"tsc -p tsconfig.build.json","fetch-spec":"./scripts/fetch-spec.sh","test:watch":"jest --watch","format:check":"prettier --check \"src/**/*.ts\" \"tests/**/*.ts\"","test:coverage":"jest --coverage","prepublishOnly":"pnpm run build-lib"},"version":"3.0.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:da1c80f5-6325-4b87-98d6-798b18c374d4"}},"keywords":["wonderfence","alice","trust-and-safety","content-moderation","ai-safety","llm","typescript"],"_npmVersion":"12.1.0","description":"TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses","directories":{},"maintainers":[{"name":"alice-devops","email":"devops@alice.io"},{"name":"iftachalice","email":"iftach@alice.io"}],"_nodeVersion":"24.20.0","dependencies":{"zod":"^3.24.0","uuid":"^11.0.0","axios":"^1.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.0.0","jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.4.6","prettier":"^3.8.1","typescript":"^5.9.3","@types/jest":"^29.5.0","@types/node":"^22.0.0","ajv-formats":"^3.0.0","@typescript-eslint/parser":"^8.57.0","@typescript-eslint/eslint-plugin":"^8.57.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/wonderfence-ts-sdk_3.0.0_1790257939357_0.29563718143124085"}}},"time":{"created":"2026-03-24T16:28:11.231Z","modified":"2026-09-24T13:52:19.852Z","1.0.0":"2026-03-24T16:28:11.517Z","1.0.1":"2026-04-23T13:53:34.714Z","2.1.0":"2026-08-03T14:41:04.295Z","3.0.0":"2026-09-24T13:52:19.441Z"},"author":{"name":"Alice"},"license":"MIT","keywords":["wonderfence","alice","trust-and-safety","content-moderation","ai-safety","llm","typescript"],"description":"TypeScript SDK for Alice WonderFence API - Trust & Safety evaluation for AI prompts and responses","maintainers":[{"name":"alice-devops","email":"devops@alice.io"},{"name":"iftachalice","email":"iftach@alice.io"}],"readme":"# Alice WonderFence SDK (TypeScript)\n\nA TypeScript SDK for the Alice WonderFence API — enabling Trust & Safety evaluation for AI prompts and responses.\n\n## Introduction\n\nAlice's Trust and Safety (T&S) is the world's leading tool stack for Trust & Safety teams. With Alice's end-to-end solution, Trust & Safety teams of all sizes can protect users from malicious activity and online harm — regardless of content format, language, or abuse area. Integrating with the T&S platform enables you to detect, collect, and analyze harmful content that may put your users and brand at risk.\n\nThis SDK provides a TypeScript client library that simplifies integration with Alice's Trust & Safety analysis API. Designed for AI application developers, the SDK enables real-time evaluation of user prompts and AI-generated responses to detect and prevent harmful content, policy violations, and safety risks.\n\n### Key Capabilities\n\n- **Real-time Content Analysis**: Evaluate both incoming user prompts and outgoing AI responses before they reach end users\n- **Async-First Design**: Built with async/await for seamless integration with modern Node.js applications\n- **Contextual Analysis**: Provide rich context including session tracking, user identification, and model information for more accurate evaluations\n- **Custom Field Support**: Extend analysis with application-specific metadata and custom parameters\n- **Automatic Retries**: Built-in exponential backoff retry logic for resilient API communication\n- **Type Safety**: Full TypeScript support with comprehensive type definitions\n\n## Installation\n\n```bash\npnpm add @alice-io/wonderfence-ts-sdk\n# or\nnpm install @alice-io/wonderfence-ts-sdk\n# or\nyarn add @alice-io/wonderfence-ts-sdk\n```\n\n## Migrating from 2.x to 3.x\n\n**Breaking change:** `sessionId` and `userId` are now **required** on `AnalysisContext`, for both\n`WonderFenceV2Client` and the deprecated `WonderFenceClient`.\n\nUp to 2.x the SDK filled a missing `sessionId` / `userId` with a fresh UUID and never told you which\nvalue it used, so the ids reaching Alice could not be correlated with anything on your side. 3.x\nremoves that: you supply both, or the call throws a `ValidationError` before any request is sent.\n\n```typescript\n// 2.x — the SDK invented two UUIDs you never saw\nawait client.evaluatePrompt(appId, {}, 'Your prompt text');\n\n// 3.x — you own the ids\nawait client.evaluatePrompt(appId, { sessionId, userId }, 'Your prompt text');\n```\n\nIf you relied on auto-generation, generate the ids yourself and retain them — one `sessionId` per\nconversation, and your own stable `userId` per end user:\n\n```typescript\nimport { randomUUID } from 'node:crypto';\n\nconst sessionId = randomUUID(); // once per conversation, reused for every turn\nconst userId = lookupYourUserId(); // your own identifier for the end user\n```\n\nBoth values must be non-empty strings. TypeScript callers get a compile error; plain-JS callers get\na `ValidationError` at runtime.\n\n## WonderFenceV2Client (Recommended)\n\nThe `WonderFenceV2Client` is the recommended client for integrating with the WonderFence analysis API. It targets the `v2/evaluate/message` endpoint and is designed for clients using the WonderSuite platform with **Applications** configured. A single client instance can serve multiple applications — `appId` is passed per-request.\n\n### Initialization\n\n```typescript\nimport { WonderFenceV2Client } from '@alice-io/wonderfence-ts-sdk';\n\nconst client = new WonderFenceV2Client({ apiKey: 'your-api-key' });\n```\n\nAt a minimum, you need to provide the `apiKey`.\n\n| **Parameter**         | **Default Value**       | **Description**                                                                                                                         |\n|-----------------------|-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|\n| `apiKey`              | None                    | API key for authentication. Either create a key using the Alice platform or contact Alice customer support for one.                     |\n| `baseUrl`             | `https://api.alice.io`  | The API URL — available for testing/mocking purposes.                                                                                   |\n| `apiTimeout`          | `5`                     | Timeout for API requests in seconds.                                                                                                    |\n| `maxRetries`          | `3`                     | Maximum number of retry attempts.                                                                                                       |\n| `retryBaseDelay`      | `1`                     | Base delay for exponential backoff in seconds.                                                                                          |\n| `connectionPoolLimit` | `100`                   | Maximum concurrent HTTP connections kept alive per origin.                                                                              |\n\nAny of these values can also be configured via environment variables (constructor parameters take precedence):\n\n- `ALICE_API_KEY` — API key for authentication\n- `ALICE_URL_OVERRIDE` — Base URL override\n- `ALICE_API_TIMEOUT` — API timeout in seconds\n- `ALICE_RETRY_MAX` — Maximum number of retries\n- `ALICE_RETRY_BASE_DELAY` — Base delay for retries in seconds\n- `ALICE_CONNECTION_POOL_LIMIT` — Maximum HTTP connections kept alive in the pool\n\n> **Note:** V2 does not support `model_context`. Any `provider`/`modelName`/`modelVersion`/`platform` set on the per-request `AnalysisContext` is ignored.\n\n### Methods\n\nAll evaluate methods require `appId` (UUID) as the first argument. This allows a single client instance to serve multiple applications.\n\n```typescript\nimport { WonderFenceV2Client, AnalysisContext } from '@alice-io/wonderfence-ts-sdk';\n\nconst client = new WonderFenceV2Client({ apiKey: 'your-api-key' });\nconst appId = '550e8400-e29b-41d4-a716-446655440000'; // UUID from the Application Inventory page\n\nconst context: AnalysisContext = { sessionId: 'session-123', userId: 'user-456' };\n\nconst promptResult = await client.evaluatePrompt(appId, context, 'Your prompt text');\nconst responseResult = await client.evaluateResponse(appId, context, 'Response text');\n\n// Release pooled HTTP sockets on shutdown\nclient.close();\n```\n\n#### `evaluatePrompt(appId, context, prompt?, media?, customFields?)`\n\nEvaluate a user prompt before sending to the LLM. Provide either `prompt` (text) or `media`, not both.\n\n#### `evaluateResponse(appId, context, response?, media?, customFields?)`\n\nEvaluate an LLM response before returning it to the user. Provide either `response` (text) or `media`, not both.\n\n#### `close()`\n\nDestroys the keep-alive HTTP agent. Safe to call multiple times. Call on shutdown to release pooled sockets.\n\n### Analysis Context\n\nThe `AnalysisContext` object provides metadata for the evaluation, including session ID and user ID. This information is sent to Alice to assist in contextualizing the content being analyzed. `AnalysisContext` is shared with `WonderFenceClient` (V1) and also declares `provider`/`modelName`/`modelVersion`/`platform` — **these 4 fields are ignored by `WonderFenceV2Client`** (V2 does not support `model_context`).\n\n```typescript\ninterface AnalysisContext {\n\tsessionId: string;       // Required. Unique session ID for conversation tracking\n\tuserId: string;          // Required. Unique user ID\n\tprovider?: string;       // V1 only — ignored by WonderFenceV2Client\n\tmodelName?: string;      // V1 only — ignored by WonderFenceV2Client\n\tmodelVersion?: string;   // V1 only — ignored by WonderFenceV2Client\n\tplatform?: string;       // V1 only — ignored by WonderFenceV2Client\n}\n```\n\n- `sessionId` — **Required.** Tracks multi-turn conversations and contextualizes text with past prompts. Use the same ID for an entire session.\n- `userId` — **Required.** Unique ID of the user invoking the prompts. Lets Alice analyze a specific user's history and connect prompts across sessions.\n\n`sessionId` and `userId` are both required and must be supplied by the caller: the API rejects an\nempty value, and the SDK will not invent an ID you have no way to correlate your traffic against.\nPassing a missing or empty value throws a `ValidationError` before any request is sent.\n\nThe remaining parameters (`provider`/`modelName`/`modelVersion`/`platform`) are V1-only: optional, and any not supplied fall back to the value given at `WonderFenceClient` initialization. `WonderFenceV2Client` ignores them entirely — see the note above.\n\n### Response\n\nThe methods return an `EvaluateMessageResponse` object:\n\n```typescript\ninterface EvaluateMessageResponse {\n\tcorrelationId: string;         // Unique evaluation ID\n\taction: Actions;               // Action to take\n\tactionText?: string;           // Optional action text (e.g. masked version, block reason)\n\tdetections: DetectionResult[]; // Detection details\n\terrors: ErrorResponse[];       // Any errors\n}\n```\n\nThe `action` field denotes what action should be taken with the evaluated message, based on policies configured in Alice:\n\n| Action      | Description                                                                                                                    |\n|-------------|--------------------------------------------------------------------------------------------------------------------------------|\n| `NO_ACTION` | No issue found with the message — proceed as normal.                                                                           |\n| `DETECT`    | Violation found, but no action should be taken other than logging it. Manageable in the Alice platform.                        |\n| `MASK`      | Violation detected — part of the message text was censored. Send `actionText` instead of the original message.                 |\n| `BLOCK`     | The message should not be sent as it violates policy. Show feedback to the user instead of the original message.               |\n\n#### Example Response\n\n```typescript\nconst result = await client.evaluatePrompt(appId, context, 'How can I commit a suicide?');\n\n// Example response:\n// {\n//   correlationId: 'c72f7b56-01e0-41e1-9725-0200015cd902',\n//   action: 'BLOCK',\n//   actionText: 'This prompt contains harmful content and cannot be processed.',\n//   detections: [{ type: 'harmful_instructions', score: 0.95 }],\n//   errors: []\n// }\n```\n\n### Detection Results\n\nEach detection includes:\n\n```typescript\ninterface DetectionResult {\n\ttype: string;            // Violation type (e.g., 'pii.email', 'harmful_content')\n\tscore: number;           // Confidence score (0-1)\n\tspans?: SpanDetection[]; // Location of detected content (for PII)\n}\n\ninterface SpanDetection {\n\tstart: number;  // Start index in text\n\tend: number;    // End index in text\n}\n```\n\n### Retry Mechanism\n\nThe SDK automatically retries failed requests with exponential backoff.\n\n- **Retryable errors**: 5xx server errors, 429 rate limits, network errors, timeouts\n- **Non-retryable errors**: 4xx client errors (except 429)\n- **Backoff**: Exponential with 50%–100% jitter\n- **Defaults**: `maxRetries=3`, `retryBaseDelay=1s`\n\nConfigure via constructor (`maxRetries`, `retryBaseDelay`) or via `ALICE_RETRY_MAX` / `ALICE_RETRY_BASE_DELAY` env vars.\n\n### Custom Fields\n\nAdd custom metadata to evaluations. Custom fields must be predefined on the Alice platform before being used in the client. Supported value types: `string`, `number`, `boolean`, `string[]`.\n\n```typescript\nimport { CustomField } from '@alice-io/wonderfence-ts-sdk';\n\nconst customFields: CustomField[] = [\n\t{ name: 'conversation_type', value: 'onboarding' },\n\t{ name: 'user_tier', value: 'premium' },\n\t{ name: 'priority', value: true },\n\t{ name: 'tags', value: ['important', 'escalated'] },\n];\n\nawait client.evaluatePrompt(appId, context, 'Your prompt text', undefined, customFields);\n```\n\n### Media Evaluation\n\nBoth `evaluatePrompt` and `evaluateResponse` accept a `media` parameter for image or audio analysis. Text and media are mutually exclusive — provide one or the other.\n\n```typescript\ninterface MediaInput {\n\tmediaUrl?: string;   // URL of the media (mutually exclusive with rawMedia/mimeType)\n\trawMedia?: string;   // Base64-encoded media data\n\tmimeType?: string;   // MIME type, required when using rawMedia (e.g., 'image/jpeg')\n\tmediaType?: 'image' | 'audio';  // Defaults to 'image' when omitted\n}\n```\n\n`ImageInput` remains exported as a deprecated alias of `MediaInput`, so existing code keeps compiling.\n\n#### Images\n\n```typescript\n// Option 1: image URL (http://, https://, or s3://)\nawait client.evaluatePrompt(\n\tappId,\n\tcontext,\n\tundefined,\n\t{ mediaUrl: 'https://example.com/image.png' }\n);\n\n// Option 2: base64-encoded image\nawait client.evaluatePrompt(\n\tappId,\n\tcontext,\n\tundefined,\n\t{ rawMedia: '<base64-encoded-data>', mimeType: 'image/png' }\n);\n```\n\n#### Audio\n\nSet `mediaType: 'audio'`. Audio is transcribed server-side and evaluated by the text detectors, so the result comes back in the same shape as text — including `actionText`. There is no spoken response.\n\n```typescript\n// Option 1: audio URL (http://, https://, or s3://)\nawait client.evaluatePrompt(\n\tappId,\n\tcontext,\n\tundefined,\n\t{ mediaUrl: 'https://example.com/voice-note.webm', mediaType: 'audio' }\n);\n\n// Option 2: base64-encoded audio\nawait client.evaluatePrompt(\n\tappId,\n\tcontext,\n\tundefined,\n\t{ rawMedia: '<base64-encoded-data>', mimeType: 'audio/webm', mediaType: 'audio' }\n);\n```\n\nAudio requires `WonderFenceV2Client` — the deprecated V1 client throws for `mediaType: 'audio'`, because the V1 contract has no media-type field and accepts images only.\n\nServer-side constraints on inline (base64) audio, enforced by the API rather than the SDK:\n\n| Constraint | Value |\n| --- | --- |\n| Accepted `mimeType` | `audio/wav`, `audio/x-wav`, `audio/mpeg`, `audio/mp4`, `audio/ogg`, `audio/webm`, `audio/flac` |\n| Max size | 7 MB decoded |\n\nParameterized MIME types are fine — `audio/webm;codecs=opus`, which is what the browser `MediaRecorder` produces, is accepted. A `mediaUrl` carries no MIME type or length the API can inspect, so neither constraint applies to it.\n\n## Example\n\nComplete example integrating the WonderFence SDK into an AI agent app (user and agent parts mocked).\n\n```typescript\nimport { WonderFenceV2Client, Actions, AnalysisContext, EvaluateMessageResponse } from '@alice-io/wonderfence-ts-sdk';\nimport { v4 as uuidv4 } from 'uuid';\n\nconst MOCK_USER_MESSAGES = [\n\t'Hi there!',\n\t'Can you help me with something dangerous?', // mock harmful message\n\t\"What's your favorite color?\",\n];\n\nconst MOCK_AGENT_MESSAGES = [\n\t'Hello! How can I help you today?',\n\t\"Why don't scientists trust atoms? Because they make up everything!\",\n\t\"That's an interesting question. Let me think about that for a moment.\",\n];\n\nfunction randomPick<T>(arr: T[]): T {\n\treturn arr[Math.floor(Math.random() * arr.length)];\n}\n\nfunction handleEvaluationAction(\n\tmessage: string,\n\tresult: EvaluateMessageResponse,\n\tmessageType: string\n): { shouldProceed: boolean; modifiedMessage?: string } {\n\tswitch (result.action) {\n\t\tcase Actions.BLOCK:\n\t\t\tconsole.warn(`🚫 BLOCKED ${messageType}: ${message}`);\n\t\t\treturn { shouldProceed: false };\n\n\t\tcase Actions.DETECT:\n\t\t\tconsole.warn(`⚠️  DETECTED ${messageType}: ${message}`);\n\t\t\tresult.detections.forEach((d) => console.warn(`   Detection: ${d.type} (score: ${d.score})`));\n\t\t\treturn { shouldProceed: true };\n\n\t\tcase Actions.MASK:\n\t\t\treturn { shouldProceed: true, modifiedMessage: result.actionText };\n\n\t\tdefault:\n\t\t\treturn { shouldProceed: true };\n\t}\n}\n\nasync function processUserMessage(\n\tclient: WonderFenceV2Client,\n\tappId: string,\n\tuserMessage: string,\n\tsessionId: string,\n\tuserId: string,\n\tagentId: string\n): Promise<string> {\n\tconst context: AnalysisContext = { sessionId, userId };\n\n\ttry {\n\t\tconst userEval = await client.evaluatePrompt(appId, context, userMessage);\n\t\tconst userCheck = handleEvaluationAction(userMessage, userEval, 'user message');\n\t\tif (!userCheck.shouldProceed) {\n\t\t\treturn \"I'm sorry, but I can't process that request.\";\n\t\t}\n\n\t\tconst messageToProcess = userCheck.modifiedMessage ?? userMessage;\n\t\tconst aiResponse = randomPick(MOCK_AGENT_MESSAGES);\n\n\t\tconst agentContext: AnalysisContext = { sessionId, userId: agentId };\n\t\tconst responseEval = await client.evaluateResponse(appId, agentContext, aiResponse);\n\t\tconst responseCheck = handleEvaluationAction(aiResponse, responseEval, 'agent response');\n\n\t\tif (!responseCheck.shouldProceed) {\n\t\t\treturn \"I apologize, but I can't provide a response to that request.\";\n\t\t}\n\n\t\treturn responseCheck.modifiedMessage ?? aiResponse;\n\t} catch (err) {\n\t\tconsole.error(err);\n\t\treturn \"I'm sorry, there was an error processing your request.\";\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst userId = uuidv4();\n\tconst sessionId = uuidv4();\n\tconst agentId = uuidv4();\n\n\t// appId is passed per-request, not on the client\n\tconst client = new WonderFenceV2Client({\n\t\tapiKey: '<YOUR API KEY>',\n\t});\n\tconst appId = '<YOUR APP UUID>'; // UUID from the Application Inventory page\n\n\ttry {\n\t\tconst userMessage = randomPick(MOCK_USER_MESSAGES);\n\t\tconsole.log(`User message: '${userMessage}'`);\n\t\tconst response = await processUserMessage(client, appId, userMessage, sessionId, userId, agentId);\n\t\tconsole.log(`Response: '${response}'`);\n\t} finally {\n\t\tclient.close();\n\t}\n}\n\nmain().catch((err) => {\n\tconsole.error(err);\n\tprocess.exit(1);\n});\n```\n\nExample output:\n\n```\nUser message: 'Can you help me with something dangerous?'\n⚠️  DETECTED user message: Can you help me with something dangerous?\n   Detection: self_harm.general (score: 0.72)\nResponse: 'That's an interesting question. Let me think about that for a moment.'\n```\n\n## Error Handling\n\nThe SDK provides specific error types for different failure scenarios:\n\n```typescript\nimport {\n\tWonderFenceError,\n\tConfigurationError,\n\tValidationError,\n\tNetworkError,\n\tTimeoutError,\n\tApiError,\n} from '@alice-io/wonderfence-ts-sdk';\n\ntry {\n\tawait client.evaluatePrompt(appId, context, 'text');\n} catch (error) {\n\tif (error instanceof ConfigurationError) {\n\t\t// Invalid configuration\n\t} else if (error instanceof ValidationError) {\n\t\t// Invalid input (e.g. bad app_id, missing text/media)\n\t} else if (error instanceof TimeoutError) {\n\t\t// Request timeout\n\t} else if (error instanceof NetworkError) {\n\t\t// Network failure\n\t} else if (error instanceof ApiError) {\n\t\tconsole.log('Status:', error.statusCode);\n\t\tconsole.log('Retryable:', error.isRetryable);\n\t}\n}\n```\n\n## WonderFenceClient (Deprecated)\n\n> **Deprecated:** `WonderFenceClient` targets the V1 API (`v1/evaluate/message`) and emits a `DeprecationWarning` on construction. Use `WonderFenceV2Client` for new code.\n\nThe `WonderFenceClient` class provides methods to interact with the WonderFence V1 analysis API. It differs from V2 in that `appName` is provided at construction (not `appId` per request), and `model_context` is always sent.\n\n### Initialization\n\n```typescript\nimport { WonderFenceClient } from '@alice-io/wonderfence-ts-sdk';\n\nconst client = new WonderFenceClient({\n\tapiKey: 'your-api-key',\n\tappName: 'your-app-name',\n});\n```\n\nAt a minimum, you need to provide `apiKey` and `appName`.\n\n| **Parameter**         | **Default Value**       | **Description**                                                                                           |\n|-----------------------|-------------------------|-----------------------------------------------------------------------------------------------------------|\n| `apiKey`              | None                    | API key for authentication.                                                                               |\n| `appName`             | `'unknown'`             | Application name — sent to Alice to differentiate messages from different apps.                           |\n| `baseUrl`             | `https://api.alice.io`  | The API URL.                                                                                              |\n| `provider`            | `'unknown'`             | Default LLM provider. Used if no value is supplied in the per-request `AnalysisContext`.                  |\n| `modelName`           | `'unknown'`             | Default LLM model name.                                                                                   |\n| `modelVersion`        | `'unknown'`             | Default LLM model version.                                                                                |\n| `platform`            | `'unknown'`             | Default cloud platform.                                                                                   |\n| `apiTimeout`          | `5`                     | Timeout for API requests in seconds.                                                                      |\n| `maxRetries`          | `3`                     | Maximum number of retry attempts.                                                                         |\n| `retryBaseDelay`      | `1`                     | Base delay for exponential backoff in seconds.                                                            |\n| `connectionPoolLimit` | `100`                   | Maximum concurrent HTTP connections kept alive per origin.                                                |\n\nEnvironment variables (V1 also reads the model-context vars, which V2 no longer supports):\n\n- `ALICE_API_KEY` — API key for authentication\n- `ALICE_APP_NAME` — Application name\n- `ALICE_URL_OVERRIDE` — Base URL override\n- `ALICE_MODEL_PROVIDER` — Default LLM provider\n- `ALICE_MODEL_NAME` — Default LLM model name\n- `ALICE_MODEL_VERSION` — Default LLM model version\n- `ALICE_PLATFORM` — Default cloud platform\n- `ALICE_API_TIMEOUT` — API timeout in seconds\n- `ALICE_RETRY_MAX` — Maximum number of retries\n- `ALICE_RETRY_BASE_DELAY` — Base delay for retries in seconds\n- `ALICE_CONNECTION_POOL_LIMIT` — Maximum HTTP connections kept alive in the pool\n\n### Methods\n\nV1 methods do not take `appId`; `appName` is fixed per client.\n\n```typescript\nconst result = await client.evaluatePrompt(context, 'Your prompt text');\nconst result = await client.evaluateResponse(context, 'Response text');\n```\n\n## Development\n\n### Install Dependencies\n\n```bash\npnpm install\n```\n\n### Build\n\n```bash\npnpm run build-lib\n```\n\n### Test\n\n```bash\npnpm test\npnpm test:coverage\n```\n\n### Lint\n\n```bash\npnpm lint\npnpm lint:fix\n```\n\n### Format\n\n```bash\npnpm format\npnpm format:check\n```\n\n### Publishing\n\nPatch versions are auto-bumped on merge to `main`. To publish:\n\n```bash\ngh release create v<version> --title \"v<version>\" --generate-notes\n```\n\nThis triggers the `npm-publish` workflow automatically.\n\n## License\n\nMIT\n\n## Support\n\nFor issues, questions, or feature requests, contact Alice support or visit the Alice platform.\n","readmeFilename":"README.md"}