novelai-image-sdk 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -291,6 +291,16 @@ function validateSeed(seed) {
291
291
  throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);
292
292
  }
293
293
  }
294
+ function checkPromptLength(prompt, limit = 2e3) {
295
+ const length = prompt.length;
296
+ const isWarning = length > limit;
297
+ return {
298
+ isWarning,
299
+ message: isWarning ? `Prompt length (${length} chars) exceeds recommended limit of ${limit}. This may cause truncation or unexpected results.` : void 0,
300
+ length,
301
+ limit
302
+ };
303
+ }
294
304
 
295
305
  // src/builder/ImageRequestBuilder.ts
296
306
  var ImageRequestBuilder = class {
@@ -302,14 +312,17 @@ var ImageRequestBuilder = class {
302
312
  this.prompt = "";
303
313
  this.characterPrompts = [];
304
314
  this.negativePrompt = "";
315
+ this.characterNegativePrompts = [];
305
316
  this.seed = Math.floor(Math.random() * 4294967295);
306
317
  this.steps = 23;
307
318
  this.scale = 5;
319
+ this.nSamples = 1;
308
320
  this.sampler = "k_euler_ancestral" /* EulerAncestral */;
309
321
  this.ucPreset = 0 /* Heavy */;
310
322
  this.qualityToggle = true;
311
323
  this.smea = false;
312
324
  this.smeaDyn = false;
325
+ this.dynamicThresholding = false;
313
326
  this.noiseSchedule = "karras" /* Karras */;
314
327
  this.client = client;
315
328
  }
@@ -350,9 +363,21 @@ var ImageRequestBuilder = class {
350
363
  }
351
364
  /**
352
365
  * Set the negative prompt (what to avoid in generation)
366
+ * Optionally provide per-character negative prompts
367
+ */
368
+ setNegativePrompt(base, characterNegatives) {
369
+ this.negativePrompt = base;
370
+ if (characterNegatives) {
371
+ this.characterNegativePrompts = characterNegatives;
372
+ }
373
+ return this;
374
+ }
375
+ /**
376
+ * Add a per-character negative prompt
377
+ * Should correspond to character prompts added via addCharacter()
353
378
  */
354
- setNegativePrompt(negative) {
355
- this.negativePrompt = negative;
379
+ addCharacterNegative(negativePrompt) {
380
+ this.characterNegativePrompts.push(negativePrompt);
356
381
  return this;
357
382
  }
358
383
  /**
@@ -381,6 +406,18 @@ var ImageRequestBuilder = class {
381
406
  this.scale = scale;
382
407
  return this;
383
408
  }
409
+ /**
410
+ * Set the number of images to generate in a single request
411
+ * Note: Each additional sample consumes Anlas credits
412
+ * @param count - Number of images (1-4 typically supported)
413
+ */
414
+ setBatchSize(count) {
415
+ if (!Number.isInteger(count) || count < 1) {
416
+ throw new Error("Batch size must be a positive integer");
417
+ }
418
+ this.nSamples = count;
419
+ return this;
420
+ }
384
421
  /**
385
422
  * Set the sampling algorithm
386
423
  */
@@ -426,6 +463,21 @@ var ImageRequestBuilder = class {
426
463
  this.noiseSchedule = schedule;
427
464
  return this;
428
465
  }
466
+ /**
467
+ * Enable dynamic thresholding
468
+ * Enhances contrast at high CFG scales (scale > 7)
469
+ */
470
+ enableDynamicThresholding() {
471
+ this.dynamicThresholding = true;
472
+ return this;
473
+ }
474
+ /**
475
+ * Disable dynamic thresholding
476
+ */
477
+ disableDynamicThresholding() {
478
+ this.dynamicThresholding = false;
479
+ return this;
480
+ }
429
481
  /**
430
482
  * Build the V4 condition input structure for prompts
431
483
  */
@@ -460,12 +512,12 @@ var ImageRequestBuilder = class {
460
512
  scale: this.scale,
461
513
  sampler: this.sampler,
462
514
  steps: this.steps,
463
- n_samples: 1,
515
+ n_samples: this.nSamples,
464
516
  seed: this.seed,
465
517
  negative_prompt: this.negativePrompt,
466
518
  // V4-specific structured prompts
467
519
  v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),
468
- v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, []),
520
+ v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, this.characterNegativePrompts),
469
521
  // Quality and preset controls (camelCase - API requirement)
470
522
  qualityToggle: this.qualityToggle,
471
523
  ucPreset: this.ucPreset,
@@ -474,6 +526,7 @@ var ImageRequestBuilder = class {
474
526
  noise_schedule: this.noiseSchedule,
475
527
  sm: this.smea,
476
528
  sm_dyn: this.smeaDyn,
529
+ dynamic_thresholding: this.dynamicThresholding,
477
530
  prefer_brownian: true,
478
531
  deliberate_euler_ancestral_bug: true,
479
532
  legacy: false,
@@ -540,6 +593,7 @@ exports.NovelAISampler = NovelAISampler;
540
593
  exports.NovelAIServerError = NovelAIServerError;
541
594
  exports.NovelAIValidationError = NovelAIValidationError;
542
595
  exports.UCPreset = UCPreset;
596
+ exports.checkPromptLength = checkPromptLength;
543
597
  exports.toBase64 = toBase64;
544
598
  exports.toDataURL = toDataURL;
545
599
  exports.validateResolution = validateResolution;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/index.ts","../src/utils/ZipParser.ts","../src/network/APIClient.ts","../src/types/Model.ts","../src/types/Sampler.ts","../src/utils/Validators.ts","../src/builder/ImageRequestBuilder.ts","../src/client/NovelAIClient.ts"],"names":["NovelAIModel","NovelAISampler","UCPreset","NoiseSchedule"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base error class for all NovelAI SDK errors\n */\nexport class NovelAIError extends Error {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = 'NovelAIError';\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Authentication error (401/403)\n * Thrown when the API token is invalid or expired\n */\nexport class NovelAIAuthError extends NovelAIError {\n constructor(message = 'Authentication failed. Check your Persistent API Token (pst-...).') {\n super(message, 401);\n this.name = 'NovelAIAuthError';\n }\n}\n\n/**\n * Payment required error (402)\n * Thrown when the user has insufficient Anlas credits\n */\nexport class NovelAIPaymentError extends NovelAIError {\n constructor(message = 'Insufficient Anlas credits for this generation.') {\n super(message, 402);\n this.name = 'NovelAIPaymentError';\n }\n}\n\n/**\n * Validation error (400)\n * Thrown when the API rejects the payload due to schema issues\n */\nexport class NovelAIValidationError extends NovelAIError {\n public readonly details?: string;\n\n constructor(message: string, details?: string) {\n super(message, 400);\n this.name = 'NovelAIValidationError';\n this.details = details;\n }\n}\n\n/**\n * Network error\n * Thrown on timeouts, connection failures, or other network issues\n */\nexport class NovelAINetworkError extends NovelAIError {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'NovelAINetworkError';\n this.cause = cause;\n }\n}\n\n/**\n * Rate limit error (429)\n * Thrown when too many requests are made\n */\nexport class NovelAIRateLimitError extends NovelAIError {\n public readonly retryAfter?: number;\n\n constructor(message = 'Rate limit exceeded. Please wait before retrying.', retryAfter?: number) {\n super(message, 429);\n this.name = 'NovelAIRateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Server error (500+)\n * Thrown when the NovelAI server encounters an internal error\n */\nexport class NovelAIServerError extends NovelAIError {\n public readonly correlationId?: string;\n\n constructor(message = 'NovelAI server error. This may be due to payload schema issues.', correlationId?: string) {\n super(message, 500);\n this.name = 'NovelAIServerError';\n this.correlationId = correlationId;\n }\n}\n","/**\n * Isomorphic ZIP parser that works in both Node.js and browser environments\n * Extracts PNG files from NovelAI's application/x-zip-compressed response\n */\n\n/**\n * Detects if we're running in a Node.js environment\n */\nfunction isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Extract PNG files from a ZIP archive buffer\n * @param data - The raw ZIP archive data\n * @returns Array of extracted PNG file contents\n */\nexport async function extractImagesFromZip(\n data: ArrayBuffer | Uint8Array\n): Promise<Uint8Array[]> {\n const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n\n if (isNodeEnvironment()) {\n return extractWithAdmZip(buffer);\n } else {\n return extractWithFflate(buffer);\n }\n}\n\n/**\n * Node.js extraction using adm-zip\n */\nasync function extractWithAdmZip(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for Node.js environment\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(Buffer.from(buffer));\n const entries = zip.getEntries();\n const images: Uint8Array[] = [];\n\n for (const entry of entries) {\n if (entry.entryName.endsWith('.png') && !entry.isDirectory) {\n const data = entry.getData();\n images.push(new Uint8Array(data));\n }\n }\n\n return images;\n}\n\n/**\n * Browser extraction using fflate\n */\nasync function extractWithFflate(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for browser environment\n const { unzipSync } = await import('fflate');\n const unzipped = unzipSync(buffer);\n const images: Uint8Array[] = [];\n\n for (const [filename, data] of Object.entries(unzipped)) {\n if (filename.endsWith('.png')) {\n images.push(data);\n }\n }\n\n return images;\n}\n\n/**\n * Convert Uint8Array to Base64 string (useful for browser display)\n */\nexport function toBase64(data: Uint8Array): string {\n if (isNodeEnvironment()) {\n return Buffer.from(data).toString('base64');\n } else {\n // Browser environment\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Convert Uint8Array to data URL for direct use in img src\n */\nexport function toDataURL(data: Uint8Array, mimeType = 'image/png'): string {\n return `data:${mimeType};base64,${toBase64(data)}`;\n}\n","import type { GenerateImagePayload, ImageResponse, APIErrorResponse } from '../types';\nimport {\n NovelAIError,\n NovelAIAuthError,\n NovelAIPaymentError,\n NovelAIValidationError,\n NovelAINetworkError,\n NovelAIRateLimitError,\n NovelAIServerError,\n} from '../errors';\nimport { extractImagesFromZip } from '../utils/ZipParser';\n\nconst DEFAULT_BASE_URL = 'https://image.novelai.net';\nconst DEFAULT_TIMEOUT = 60000;\nconst GENERATE_ENDPOINT = '/ai/generate-image';\n\nexport interface APIClientConfig {\n token: string;\n baseUrl?: string;\n timeout?: number;\n}\n\n/**\n * Low-level HTTP client for NovelAI API\n * Handles authentication, binary response parsing, and error mapping\n */\nexport class APIClient {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: APIClientConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * Generate an image using the NovelAI API\n */\n async generateImage(payload: GenerateImagePayload): Promise<ImageResponse> {\n const url = `${this.baseUrl}${GENERATE_ENDPOINT}`;\n\n // Generate correlation ID for debugging\n const correlationId = this.generateCorrelationId();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/x-zip-compressed, application/json',\n 'x-correlation-id': correlationId,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response, correlationId);\n }\n\n // Parse the ZIP response\n const arrayBuffer = await response.arrayBuffer();\n const images = await extractImagesFromZip(arrayBuffer);\n\n return {\n images,\n metadata: {\n seed: payload.parameters.seed,\n prompt: payload.input,\n model: payload.model,\n sampler: payload.parameters.sampler as string,\n steps: payload.parameters.steps,\n scale: payload.parameters.scale,\n },\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof NovelAIError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new NovelAINetworkError(`Request timed out after ${this.timeout}ms`, error);\n }\n throw new NovelAINetworkError(`Network error: ${error.message}`, error);\n }\n\n throw new NovelAINetworkError('An unknown error occurred');\n }\n }\n\n /**\n * Handle non-2xx responses and throw appropriate errors\n */\n private async handleErrorResponse(response: Response, correlationId: string): Promise<never> {\n let errorBody: APIErrorResponse | null = null;\n\n try {\n errorBody = await response.json() as APIErrorResponse;\n } catch {\n // Response may not be JSON\n }\n\n const message = errorBody?.message ?? errorBody?.error ?? response.statusText;\n\n switch (response.status) {\n case 400:\n throw new NovelAIValidationError(\n `Bad request: ${message}`,\n JSON.stringify(errorBody)\n );\n case 401:\n case 403:\n throw new NovelAIAuthError(message);\n case 402:\n throw new NovelAIPaymentError(message);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n throw new NovelAIRateLimitError(message, retryAfter ? parseInt(retryAfter) : undefined);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n throw new NovelAIServerError(\n `Server error (${response.status}): ${message}. This may be caused by payload schema issues.`,\n correlationId\n );\n default:\n throw new NovelAIError(\n `HTTP ${response.status}: ${message}`,\n response.status\n );\n }\n }\n\n /**\n * Generate a 6-character alphanumeric correlation ID for debugging\n */\n private generateCorrelationId(): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 6; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n }\n}\n","/**\n * Supported NovelAI image generation models\n */\nexport enum NovelAIModel {\n /** V4.5 Full - Latest model with T5 encoding and multi-character support */\n V45_Full = \"nai-diffusion-4-5-full\",\n /** V4 Curated - More conservative aesthetic choices */\n V4_Curated = \"nai-diffusion-4-curated\",\n /** V4 Inpainting - For image editing and inpainting tasks */\n Inpainting = \"nai-diffusion-4-inpainting\",\n}\n","/**\n * Supported sampling algorithms for image generation\n */\nexport enum NovelAISampler {\n /** Standard Euler sampler */\n Euler = \"k_euler\",\n /** Euler Ancestral - recommended for anime-style generations */\n EulerAncestral = \"k_euler_ancestral\",\n /** DPM++ 2M - stable and aesthetic */\n DPM_2M = \"k_dpmpp_2m\",\n /** DPM++ 2S Ancestral */\n DPM_2S_Ancestral = \"k_dpmpp_2s_ancestral\",\n /** DPM++ SDE */\n DPM_SDE = \"k_dpmpp_sde\",\n /** DDIM V3 */\n DDIM = \"ddim_v3\",\n}\n\n/**\n * Preset negative prompt configurations\n */\nexport enum UCPreset {\n /** Heavy - Low Quality + Bad Anatomy */\n Heavy = 0,\n /** Light - Low Quality only */\n Light = 1,\n /** None - Use custom negative prompt only */\n None = 2,\n}\n\n/**\n * Noise schedule algorithms\n */\nexport enum NoiseSchedule {\n Native = \"native\",\n Karras = \"karras\",\n Exponential = \"exponential\",\n Polyexponential = \"polyexponential\",\n}\n","/**\n * Validation error for invalid SDK parameters\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Validates that image dimensions are multiples of 64\n * @throws ValidationError if dimensions are invalid\n */\nexport function validateResolution(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height)) {\n throw new ValidationError('Width and height must be integers');\n }\n if (width <= 0 || height <= 0) {\n throw new ValidationError('Width and height must be positive');\n }\n if (width % 64 !== 0) {\n throw new ValidationError(`Width must be a multiple of 64, got ${width}`);\n }\n if (height % 64 !== 0) {\n throw new ValidationError(`Height must be a multiple of 64, got ${height}`);\n }\n}\n\n/**\n * Validates that step count is within acceptable range\n * @throws ValidationError if steps are out of range\n */\nexport function validateSteps(steps: number): void {\n if (!Number.isInteger(steps)) {\n throw new ValidationError('Steps must be an integer');\n }\n if (steps < 1 || steps > 50) {\n throw new ValidationError(`Steps must be between 1 and 50, got ${steps}`);\n }\n}\n\n/**\n * Validates that scale (CFG) is within acceptable range\n * @throws ValidationError if scale is out of range\n */\nexport function validateScale(scale: number): void {\n if (typeof scale !== 'number' || isNaN(scale)) {\n throw new ValidationError('Scale must be a number');\n }\n if (scale < 0 || scale > 10) {\n throw new ValidationError(`Scale must be between 0 and 10, got ${scale}`);\n }\n}\n\n/**\n * Validates that seed is a valid unsigned 32-bit integer\n */\nexport function validateSeed(seed: number): void {\n if (!Number.isInteger(seed)) {\n throw new ValidationError('Seed must be an integer');\n }\n if (seed < 0 || seed > 4294967295) {\n throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);\n }\n}\n","import type { NovelAIClient } from '../client/NovelAIClient';\nimport type {\n GenerateImagePayload,\n NovelAIParameters,\n V4ConditionInput,\n ImageResponse,\n} from '../types';\nimport { NovelAIModel, NovelAISampler, UCPreset, NoiseSchedule } from '../types';\nimport { validateResolution, validateSteps, validateScale, validateSeed } from '../utils/Validators';\n\n/**\n * Fluent builder for constructing NovelAI image generation requests\n * Provides method chaining and compile-time type safety\n */\nexport class ImageRequestBuilder {\n private client: NovelAIClient;\n\n // Core parameters with sensible defaults\n private model: NovelAIModel = NovelAIModel.V45_Full;\n private width = 832;\n private height = 1216;\n private prompt = '';\n private characterPrompts: string[] = [];\n private negativePrompt = '';\n private seed: number = Math.floor(Math.random() * 4294967295);\n private steps = 23;\n private scale = 5.0;\n private sampler: NovelAISampler = NovelAISampler.EulerAncestral;\n private ucPreset: UCPreset = UCPreset.Heavy;\n private qualityToggle = true;\n private smea = false;\n private smeaDyn = false;\n private noiseSchedule: NoiseSchedule = NoiseSchedule.Karras;\n\n constructor(client: NovelAIClient) {\n this.client = client;\n }\n\n /**\n * Set the model to use for generation\n */\n setModel(model: NovelAIModel): this {\n this.model = model;\n return this;\n }\n\n /**\n * Set the output image dimensions\n * @throws ValidationError if dimensions are not multiples of 64\n */\n setSize(width: number, height: number): this {\n validateResolution(width, height);\n this.width = width;\n this.height = height;\n return this;\n }\n\n /**\n * Set the main prompt (base scene description)\n * For multi-character prompts, use the array overload\n */\n setPrompt(base: string, characters?: string[]): this {\n this.prompt = base;\n if (characters) {\n this.characterPrompts = characters;\n }\n return this;\n }\n\n /**\n * Add character prompts for multi-character scenes\n */\n addCharacter(characterPrompt: string): this {\n this.characterPrompts.push(characterPrompt);\n return this;\n }\n\n /**\n * Set the negative prompt (what to avoid in generation)\n */\n setNegativePrompt(negative: string): this {\n this.negativePrompt = negative;\n return this;\n }\n\n /**\n * Set the random seed for reproducible generations\n */\n setSeed(seed: number): this {\n validateSeed(seed);\n this.seed = seed;\n return this;\n }\n\n /**\n * Set the number of sampling steps\n * @throws ValidationError if steps are out of range (1-50)\n */\n setSteps(steps: number): this {\n validateSteps(steps);\n this.steps = steps;\n return this;\n }\n\n /**\n * Set the guidance scale (CFG)\n * @throws ValidationError if scale is out of range (0-10)\n */\n setScale(scale: number): this {\n validateScale(scale);\n this.scale = scale;\n return this;\n }\n\n /**\n * Set the sampling algorithm\n */\n setSampler(sampler: NovelAISampler): this {\n this.sampler = sampler;\n return this;\n }\n\n /**\n * Set the UC preset (predefined negative prompt configuration)\n */\n setUCPreset(preset: UCPreset): this {\n this.ucPreset = preset;\n return this;\n }\n\n /**\n * Toggle automatic quality tags insertion\n */\n setQualityToggle(enabled: boolean): this {\n this.qualityToggle = enabled;\n return this;\n }\n\n /**\n * Enable SMEA (Sinusoidal Multipass Euler Ancestral)\n * @param dynamic - If true, enables dynamic SMEA variant\n */\n enableSMEA(dynamic = false): this {\n this.smea = true;\n this.smeaDyn = dynamic;\n return this;\n }\n\n /**\n * Disable SMEA\n */\n disableSMEA(): this {\n this.smea = false;\n this.smeaDyn = false;\n return this;\n }\n\n /**\n * Set the noise schedule algorithm\n */\n setNoiseSchedule(schedule: NoiseSchedule): this {\n this.noiseSchedule = schedule;\n return this;\n }\n\n /**\n * Build the V4 condition input structure for prompts\n */\n private buildV4ConditionInput(base: string, characters: string[]): V4ConditionInput {\n return {\n caption: {\n base_caption: base,\n char_captions: characters,\n },\n use_coords: false,\n use_order: true,\n legacy_uc: false,\n };\n }\n\n /**\n * Build the formatted input string for the API\n * Combines base prompt with character prompts using pipe delimiter\n */\n private buildInputString(): string {\n if (this.characterPrompts.length === 0) {\n return this.prompt;\n }\n return [this.prompt, ...this.characterPrompts].join(' | ');\n }\n\n /**\n * Build the complete API payload\n */\n buildPayload(): GenerateImagePayload {\n const parameters: NovelAIParameters = {\n width: this.width,\n height: this.height,\n scale: this.scale,\n sampler: this.sampler,\n steps: this.steps,\n n_samples: 1,\n seed: this.seed,\n negative_prompt: this.negativePrompt,\n\n // V4-specific structured prompts\n v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),\n v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, []),\n\n // Quality and preset controls (camelCase - API requirement)\n qualityToggle: this.qualityToggle,\n ucPreset: this.ucPreset,\n\n // Technical flags (snake_case - API requirement)\n params_version: 3,\n noise_schedule: this.noiseSchedule,\n sm: this.smea,\n sm_dyn: this.smeaDyn,\n prefer_brownian: true,\n deliberate_euler_ancestral_bug: true,\n legacy: false,\n legacy_v3_extend: false,\n };\n\n return {\n input: this.buildInputString(),\n model: this.model,\n action: 'generate',\n parameters,\n };\n }\n\n /**\n * Execute the image generation request\n */\n async generate(): Promise<ImageResponse> {\n const payload = this.buildPayload();\n return this.client._execute(payload);\n }\n}\n","import type { ClientConfig, GenerateImagePayload, ImageResponse } from '../types';\nimport { APIClient } from '../network/APIClient';\nimport { ImageRequestBuilder } from '../builder/ImageRequestBuilder';\n\n/**\n * Main entry point for the NovelAI Image SDK\n * \n * @example\n * ```typescript\n * const client = new NovelAIClient({ token: process.env.NAI_TOKEN });\n * \n * const result = await client.image()\n * .setPrompt('1girl, cyberpunk, neon lights')\n * .setSize(832, 1216)\n * .generate();\n * \n * fs.writeFileSync('output.png', result.images[0]);\n * ```\n */\nexport class NovelAIClient {\n private readonly apiClient: APIClient;\n\n /**\n * Create a new NovelAI client\n * @param config - Client configuration including token and optional base URL\n */\n constructor(config: ClientConfig) {\n if (!config.token) {\n throw new Error('NovelAI API token is required');\n }\n\n this.apiClient = new APIClient({\n token: config.token,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n }\n\n /**\n * Start building an image generation request\n * @returns A new ImageRequestBuilder instance\n */\n image(): ImageRequestBuilder {\n return new ImageRequestBuilder(this);\n }\n\n /**\n * Execute a generation request (called internally by the builder)\n * @internal\n */\n async _execute(payload: GenerateImagePayload): Promise<ImageResponse> {\n return this.apiClient.generateImage(payload);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/index.ts","../src/utils/ZipParser.ts","../src/network/APIClient.ts","../src/types/Model.ts","../src/types/Sampler.ts","../src/utils/Validators.ts","../src/builder/ImageRequestBuilder.ts","../src/client/NovelAIClient.ts"],"names":["NovelAIModel","NovelAISampler","UCPreset","NoiseSchedule"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base error class for all NovelAI SDK errors\n */\nexport class NovelAIError extends Error {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = 'NovelAIError';\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Authentication error (401/403)\n * Thrown when the API token is invalid or expired\n */\nexport class NovelAIAuthError extends NovelAIError {\n constructor(message = 'Authentication failed. Check your Persistent API Token (pst-...).') {\n super(message, 401);\n this.name = 'NovelAIAuthError';\n }\n}\n\n/**\n * Payment required error (402)\n * Thrown when the user has insufficient Anlas credits\n */\nexport class NovelAIPaymentError extends NovelAIError {\n constructor(message = 'Insufficient Anlas credits for this generation.') {\n super(message, 402);\n this.name = 'NovelAIPaymentError';\n }\n}\n\n/**\n * Validation error (400)\n * Thrown when the API rejects the payload due to schema issues\n */\nexport class NovelAIValidationError extends NovelAIError {\n public readonly details?: string;\n\n constructor(message: string, details?: string) {\n super(message, 400);\n this.name = 'NovelAIValidationError';\n this.details = details;\n }\n}\n\n/**\n * Network error\n * Thrown on timeouts, connection failures, or other network issues\n */\nexport class NovelAINetworkError extends NovelAIError {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'NovelAINetworkError';\n this.cause = cause;\n }\n}\n\n/**\n * Rate limit error (429)\n * Thrown when too many requests are made\n */\nexport class NovelAIRateLimitError extends NovelAIError {\n public readonly retryAfter?: number;\n\n constructor(message = 'Rate limit exceeded. Please wait before retrying.', retryAfter?: number) {\n super(message, 429);\n this.name = 'NovelAIRateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Server error (500+)\n * Thrown when the NovelAI server encounters an internal error\n */\nexport class NovelAIServerError extends NovelAIError {\n public readonly correlationId?: string;\n\n constructor(message = 'NovelAI server error. This may be due to payload schema issues.', correlationId?: string) {\n super(message, 500);\n this.name = 'NovelAIServerError';\n this.correlationId = correlationId;\n }\n}\n","/**\n * Isomorphic ZIP parser that works in both Node.js and browser environments\n * Extracts PNG files from NovelAI's application/x-zip-compressed response\n */\n\n/**\n * Detects if we're running in a Node.js environment\n */\nfunction isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Extract PNG files from a ZIP archive buffer\n * @param data - The raw ZIP archive data\n * @returns Array of extracted PNG file contents\n */\nexport async function extractImagesFromZip(\n data: ArrayBuffer | Uint8Array\n): Promise<Uint8Array[]> {\n const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n\n if (isNodeEnvironment()) {\n return extractWithAdmZip(buffer);\n } else {\n return extractWithFflate(buffer);\n }\n}\n\n/**\n * Node.js extraction using adm-zip\n */\nasync function extractWithAdmZip(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for Node.js environment\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(Buffer.from(buffer));\n const entries = zip.getEntries();\n const images: Uint8Array[] = [];\n\n for (const entry of entries) {\n if (entry.entryName.endsWith('.png') && !entry.isDirectory) {\n const data = entry.getData();\n images.push(new Uint8Array(data));\n }\n }\n\n return images;\n}\n\n/**\n * Browser extraction using fflate\n */\nasync function extractWithFflate(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for browser environment\n const { unzipSync } = await import('fflate');\n const unzipped = unzipSync(buffer);\n const images: Uint8Array[] = [];\n\n for (const [filename, data] of Object.entries(unzipped)) {\n if (filename.endsWith('.png')) {\n images.push(data);\n }\n }\n\n return images;\n}\n\n/**\n * Convert Uint8Array to Base64 string (useful for browser display)\n */\nexport function toBase64(data: Uint8Array): string {\n if (isNodeEnvironment()) {\n return Buffer.from(data).toString('base64');\n } else {\n // Browser environment\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Convert Uint8Array to data URL for direct use in img src\n */\nexport function toDataURL(data: Uint8Array, mimeType = 'image/png'): string {\n return `data:${mimeType};base64,${toBase64(data)}`;\n}\n","import type { GenerateImagePayload, ImageResponse, APIErrorResponse } from '../types';\nimport {\n NovelAIError,\n NovelAIAuthError,\n NovelAIPaymentError,\n NovelAIValidationError,\n NovelAINetworkError,\n NovelAIRateLimitError,\n NovelAIServerError,\n} from '../errors';\nimport { extractImagesFromZip } from '../utils/ZipParser';\n\nconst DEFAULT_BASE_URL = 'https://image.novelai.net';\nconst DEFAULT_TIMEOUT = 60000;\nconst GENERATE_ENDPOINT = '/ai/generate-image';\n\nexport interface APIClientConfig {\n token: string;\n baseUrl?: string;\n timeout?: number;\n}\n\n/**\n * Low-level HTTP client for NovelAI API\n * Handles authentication, binary response parsing, and error mapping\n */\nexport class APIClient {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: APIClientConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * Generate an image using the NovelAI API\n */\n async generateImage(payload: GenerateImagePayload): Promise<ImageResponse> {\n const url = `${this.baseUrl}${GENERATE_ENDPOINT}`;\n\n // Generate correlation ID for debugging\n const correlationId = this.generateCorrelationId();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/x-zip-compressed, application/json',\n 'x-correlation-id': correlationId,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response, correlationId);\n }\n\n // Parse the ZIP response\n const arrayBuffer = await response.arrayBuffer();\n const images = await extractImagesFromZip(arrayBuffer);\n\n return {\n images,\n metadata: {\n seed: payload.parameters.seed,\n prompt: payload.input,\n model: payload.model,\n sampler: payload.parameters.sampler as string,\n steps: payload.parameters.steps,\n scale: payload.parameters.scale,\n },\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof NovelAIError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new NovelAINetworkError(`Request timed out after ${this.timeout}ms`, error);\n }\n throw new NovelAINetworkError(`Network error: ${error.message}`, error);\n }\n\n throw new NovelAINetworkError('An unknown error occurred');\n }\n }\n\n /**\n * Handle non-2xx responses and throw appropriate errors\n */\n private async handleErrorResponse(response: Response, correlationId: string): Promise<never> {\n let errorBody: APIErrorResponse | null = null;\n\n try {\n errorBody = await response.json() as APIErrorResponse;\n } catch {\n // Response may not be JSON\n }\n\n const message = errorBody?.message ?? errorBody?.error ?? response.statusText;\n\n switch (response.status) {\n case 400:\n throw new NovelAIValidationError(\n `Bad request: ${message}`,\n JSON.stringify(errorBody)\n );\n case 401:\n case 403:\n throw new NovelAIAuthError(message);\n case 402:\n throw new NovelAIPaymentError(message);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n throw new NovelAIRateLimitError(message, retryAfter ? parseInt(retryAfter) : undefined);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n throw new NovelAIServerError(\n `Server error (${response.status}): ${message}. This may be caused by payload schema issues.`,\n correlationId\n );\n default:\n throw new NovelAIError(\n `HTTP ${response.status}: ${message}`,\n response.status\n );\n }\n }\n\n /**\n * Generate a 6-character alphanumeric correlation ID for debugging\n */\n private generateCorrelationId(): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 6; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n }\n}\n","/**\n * Supported NovelAI image generation models\n */\nexport enum NovelAIModel {\n /** V4.5 Full - Latest model with T5 encoding and multi-character support */\n V45_Full = \"nai-diffusion-4-5-full\",\n /** V4 Curated - More conservative aesthetic choices */\n V4_Curated = \"nai-diffusion-4-curated\",\n /** V4 Inpainting - For image editing and inpainting tasks */\n Inpainting = \"nai-diffusion-4-inpainting\",\n}\n","/**\n * Supported sampling algorithms for image generation\n */\nexport enum NovelAISampler {\n /** Standard Euler sampler */\n Euler = \"k_euler\",\n /** Euler Ancestral - recommended for anime-style generations */\n EulerAncestral = \"k_euler_ancestral\",\n /** DPM++ 2M - stable and aesthetic */\n DPM_2M = \"k_dpmpp_2m\",\n /** DPM++ 2S Ancestral */\n DPM_2S_Ancestral = \"k_dpmpp_2s_ancestral\",\n /** DPM++ SDE */\n DPM_SDE = \"k_dpmpp_sde\",\n /** DDIM V3 */\n DDIM = \"ddim_v3\",\n}\n\n/**\n * Preset negative prompt configurations\n */\nexport enum UCPreset {\n /** Heavy - Low Quality + Bad Anatomy */\n Heavy = 0,\n /** Light - Low Quality only */\n Light = 1,\n /** None - Use custom negative prompt only */\n None = 2,\n}\n\n/**\n * Noise schedule algorithms\n */\nexport enum NoiseSchedule {\n Native = \"native\",\n Karras = \"karras\",\n Exponential = \"exponential\",\n Polyexponential = \"polyexponential\",\n}\n","/**\n * Validation error for invalid SDK parameters\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Validates that image dimensions are multiples of 64\n * @throws ValidationError if dimensions are invalid\n */\nexport function validateResolution(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height)) {\n throw new ValidationError('Width and height must be integers');\n }\n if (width <= 0 || height <= 0) {\n throw new ValidationError('Width and height must be positive');\n }\n if (width % 64 !== 0) {\n throw new ValidationError(`Width must be a multiple of 64, got ${width}`);\n }\n if (height % 64 !== 0) {\n throw new ValidationError(`Height must be a multiple of 64, got ${height}`);\n }\n}\n\n/**\n * Validates that step count is within acceptable range\n * @throws ValidationError if steps are out of range\n */\nexport function validateSteps(steps: number): void {\n if (!Number.isInteger(steps)) {\n throw new ValidationError('Steps must be an integer');\n }\n if (steps < 1 || steps > 50) {\n throw new ValidationError(`Steps must be between 1 and 50, got ${steps}`);\n }\n}\n\n/**\n * Validates that scale (CFG) is within acceptable range\n * @throws ValidationError if scale is out of range\n */\nexport function validateScale(scale: number): void {\n if (typeof scale !== 'number' || isNaN(scale)) {\n throw new ValidationError('Scale must be a number');\n }\n if (scale < 0 || scale > 10) {\n throw new ValidationError(`Scale must be between 0 and 10, got ${scale}`);\n }\n}\n\n/**\n * Validates that seed is a valid unsigned 32-bit integer\n */\nexport function validateSeed(seed: number): void {\n if (!Number.isInteger(seed)) {\n throw new ValidationError('Seed must be an integer');\n }\n if (seed < 0 || seed > 4294967295) {\n throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);\n }\n}\n\n/**\n * Warning result for prompt length check\n */\nexport interface PromptWarning {\n isWarning: boolean;\n message?: string;\n length: number;\n limit: number;\n}\n\n/**\n * Check if prompt length exceeds recommended limit\n * T5 encoder has different tokenization than CLIP, so this is a heuristic\n * @param prompt - The full prompt string\n * @param limit - Character limit (default: 2000)\n * @returns Warning object with details\n */\nexport function checkPromptLength(prompt: string, limit = 2000): PromptWarning {\n const length = prompt.length;\n const isWarning = length > limit;\n \n return {\n isWarning,\n message: isWarning \n ? `Prompt length (${length} chars) exceeds recommended limit of ${limit}. This may cause truncation or unexpected results.`\n : undefined,\n length,\n limit,\n };\n}\n","import type { NovelAIClient } from '../client/NovelAIClient';\nimport type {\n GenerateImagePayload,\n NovelAIParameters,\n V4ConditionInput,\n ImageResponse,\n} from '../types';\nimport { NovelAIModel, NovelAISampler, UCPreset, NoiseSchedule } from '../types';\nimport { validateResolution, validateSteps, validateScale, validateSeed } from '../utils/Validators';\n\n/**\n * Fluent builder for constructing NovelAI image generation requests\n * Provides method chaining and compile-time type safety\n */\nexport class ImageRequestBuilder {\n private client: NovelAIClient;\n\n // Core parameters with sensible defaults\n private model: NovelAIModel = NovelAIModel.V45_Full;\n private width = 832;\n private height = 1216;\n private prompt = '';\n private characterPrompts: string[] = [];\n private negativePrompt = '';\n private characterNegativePrompts: string[] = [];\n private seed: number = Math.floor(Math.random() * 4294967295);\n private steps = 23;\n private scale = 5.0;\n private nSamples = 1;\n private sampler: NovelAISampler = NovelAISampler.EulerAncestral;\n private ucPreset: UCPreset = UCPreset.Heavy;\n private qualityToggle = true;\n private smea = false;\n private smeaDyn = false;\n private dynamicThresholding = false;\n private noiseSchedule: NoiseSchedule = NoiseSchedule.Karras;\n\n constructor(client: NovelAIClient) {\n this.client = client;\n }\n\n /**\n * Set the model to use for generation\n */\n setModel(model: NovelAIModel): this {\n this.model = model;\n return this;\n }\n\n /**\n * Set the output image dimensions\n * @throws ValidationError if dimensions are not multiples of 64\n */\n setSize(width: number, height: number): this {\n validateResolution(width, height);\n this.width = width;\n this.height = height;\n return this;\n }\n\n /**\n * Set the main prompt (base scene description)\n * For multi-character prompts, use the array overload\n */\n setPrompt(base: string, characters?: string[]): this {\n this.prompt = base;\n if (characters) {\n this.characterPrompts = characters;\n }\n return this;\n }\n\n /**\n * Add character prompts for multi-character scenes\n */\n addCharacter(characterPrompt: string): this {\n this.characterPrompts.push(characterPrompt);\n return this;\n }\n\n /**\n * Set the negative prompt (what to avoid in generation)\n * Optionally provide per-character negative prompts\n */\n setNegativePrompt(base: string, characterNegatives?: string[]): this {\n this.negativePrompt = base;\n if (characterNegatives) {\n this.characterNegativePrompts = characterNegatives;\n }\n return this;\n }\n\n /**\n * Add a per-character negative prompt\n * Should correspond to character prompts added via addCharacter()\n */\n addCharacterNegative(negativePrompt: string): this {\n this.characterNegativePrompts.push(negativePrompt);\n return this;\n }\n\n /**\n * Set the random seed for reproducible generations\n */\n setSeed(seed: number): this {\n validateSeed(seed);\n this.seed = seed;\n return this;\n }\n\n /**\n * Set the number of sampling steps\n * @throws ValidationError if steps are out of range (1-50)\n */\n setSteps(steps: number): this {\n validateSteps(steps);\n this.steps = steps;\n return this;\n }\n\n /**\n * Set the guidance scale (CFG)\n * @throws ValidationError if scale is out of range (0-10)\n */\n setScale(scale: number): this {\n validateScale(scale);\n this.scale = scale;\n return this;\n }\n\n /**\n * Set the number of images to generate in a single request\n * Note: Each additional sample consumes Anlas credits\n * @param count - Number of images (1-4 typically supported)\n */\n setBatchSize(count: number): this {\n if (!Number.isInteger(count) || count < 1) {\n throw new Error('Batch size must be a positive integer');\n }\n this.nSamples = count;\n return this;\n }\n\n /**\n * Set the sampling algorithm\n */\n setSampler(sampler: NovelAISampler): this {\n this.sampler = sampler;\n return this;\n }\n\n /**\n * Set the UC preset (predefined negative prompt configuration)\n */\n setUCPreset(preset: UCPreset): this {\n this.ucPreset = preset;\n return this;\n }\n\n /**\n * Toggle automatic quality tags insertion\n */\n setQualityToggle(enabled: boolean): this {\n this.qualityToggle = enabled;\n return this;\n }\n\n /**\n * Enable SMEA (Sinusoidal Multipass Euler Ancestral)\n * @param dynamic - If true, enables dynamic SMEA variant\n */\n enableSMEA(dynamic = false): this {\n this.smea = true;\n this.smeaDyn = dynamic;\n return this;\n }\n\n /**\n * Disable SMEA\n */\n disableSMEA(): this {\n this.smea = false;\n this.smeaDyn = false;\n return this;\n }\n\n /**\n * Set the noise schedule algorithm\n */\n setNoiseSchedule(schedule: NoiseSchedule): this {\n this.noiseSchedule = schedule;\n return this;\n }\n\n /**\n * Enable dynamic thresholding\n * Enhances contrast at high CFG scales (scale > 7)\n */\n enableDynamicThresholding(): this {\n this.dynamicThresholding = true;\n return this;\n }\n\n /**\n * Disable dynamic thresholding\n */\n disableDynamicThresholding(): this {\n this.dynamicThresholding = false;\n return this;\n }\n\n /**\n * Build the V4 condition input structure for prompts\n */\n private buildV4ConditionInput(base: string, characters: string[]): V4ConditionInput {\n return {\n caption: {\n base_caption: base,\n char_captions: characters,\n },\n use_coords: false,\n use_order: true,\n legacy_uc: false,\n };\n }\n\n /**\n * Build the formatted input string for the API\n * Combines base prompt with character prompts using pipe delimiter\n */\n private buildInputString(): string {\n if (this.characterPrompts.length === 0) {\n return this.prompt;\n }\n return [this.prompt, ...this.characterPrompts].join(' | ');\n }\n\n /**\n * Build the complete API payload\n */\n buildPayload(): GenerateImagePayload {\n const parameters: NovelAIParameters = {\n width: this.width,\n height: this.height,\n scale: this.scale,\n sampler: this.sampler,\n steps: this.steps,\n n_samples: this.nSamples,\n seed: this.seed,\n negative_prompt: this.negativePrompt,\n\n // V4-specific structured prompts\n v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),\n v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, this.characterNegativePrompts),\n\n // Quality and preset controls (camelCase - API requirement)\n qualityToggle: this.qualityToggle,\n ucPreset: this.ucPreset,\n\n // Technical flags (snake_case - API requirement)\n params_version: 3,\n noise_schedule: this.noiseSchedule,\n sm: this.smea,\n sm_dyn: this.smeaDyn,\n dynamic_thresholding: this.dynamicThresholding,\n prefer_brownian: true,\n deliberate_euler_ancestral_bug: true,\n legacy: false,\n legacy_v3_extend: false,\n };\n\n return {\n input: this.buildInputString(),\n model: this.model,\n action: 'generate',\n parameters,\n };\n }\n\n /**\n * Execute the image generation request\n */\n async generate(): Promise<ImageResponse> {\n const payload = this.buildPayload();\n return this.client._execute(payload);\n }\n}\n","import type { ClientConfig, GenerateImagePayload, ImageResponse } from '../types';\nimport { APIClient } from '../network/APIClient';\nimport { ImageRequestBuilder } from '../builder/ImageRequestBuilder';\n\n/**\n * Main entry point for the NovelAI Image SDK\n * \n * @example\n * ```typescript\n * const client = new NovelAIClient({ token: process.env.NAI_TOKEN });\n * \n * const result = await client.image()\n * .setPrompt('1girl, cyberpunk, neon lights')\n * .setSize(832, 1216)\n * .generate();\n * \n * fs.writeFileSync('output.png', result.images[0]);\n * ```\n */\nexport class NovelAIClient {\n private readonly apiClient: APIClient;\n\n /**\n * Create a new NovelAI client\n * @param config - Client configuration including token and optional base URL\n */\n constructor(config: ClientConfig) {\n if (!config.token) {\n throw new Error('NovelAI API token is required');\n }\n\n this.apiClient = new APIClient({\n token: config.token,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n }\n\n /**\n * Start building an image generation request\n * @returns A new ImageRequestBuilder instance\n */\n image(): ImageRequestBuilder {\n return new ImageRequestBuilder(this);\n }\n\n /**\n * Execute a generation request (called internally by the builder)\n * @internal\n */\n async _execute(payload: GenerateImagePayload): Promise<ImageResponse> {\n return this.apiClient.generateImage(payload);\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -82,6 +82,7 @@ interface NovelAIParameters {
82
82
  noise_schedule: NoiseSchedule | string;
83
83
  sm: boolean;
84
84
  sm_dyn: boolean;
85
+ dynamic_thresholding: boolean;
85
86
  prefer_brownian: boolean;
86
87
  deliberate_euler_ancestral_bug: boolean;
87
88
  legacy: boolean;
@@ -161,14 +162,17 @@ declare class ImageRequestBuilder {
161
162
  private prompt;
162
163
  private characterPrompts;
163
164
  private negativePrompt;
165
+ private characterNegativePrompts;
164
166
  private seed;
165
167
  private steps;
166
168
  private scale;
169
+ private nSamples;
167
170
  private sampler;
168
171
  private ucPreset;
169
172
  private qualityToggle;
170
173
  private smea;
171
174
  private smeaDyn;
175
+ private dynamicThresholding;
172
176
  private noiseSchedule;
173
177
  constructor(client: NovelAIClient);
174
178
  /**
@@ -191,8 +195,14 @@ declare class ImageRequestBuilder {
191
195
  addCharacter(characterPrompt: string): this;
192
196
  /**
193
197
  * Set the negative prompt (what to avoid in generation)
198
+ * Optionally provide per-character negative prompts
194
199
  */
195
- setNegativePrompt(negative: string): this;
200
+ setNegativePrompt(base: string, characterNegatives?: string[]): this;
201
+ /**
202
+ * Add a per-character negative prompt
203
+ * Should correspond to character prompts added via addCharacter()
204
+ */
205
+ addCharacterNegative(negativePrompt: string): this;
196
206
  /**
197
207
  * Set the random seed for reproducible generations
198
208
  */
@@ -207,6 +217,12 @@ declare class ImageRequestBuilder {
207
217
  * @throws ValidationError if scale is out of range (0-10)
208
218
  */
209
219
  setScale(scale: number): this;
220
+ /**
221
+ * Set the number of images to generate in a single request
222
+ * Note: Each additional sample consumes Anlas credits
223
+ * @param count - Number of images (1-4 typically supported)
224
+ */
225
+ setBatchSize(count: number): this;
210
226
  /**
211
227
  * Set the sampling algorithm
212
228
  */
@@ -232,6 +248,15 @@ declare class ImageRequestBuilder {
232
248
  * Set the noise schedule algorithm
233
249
  */
234
250
  setNoiseSchedule(schedule: NoiseSchedule): this;
251
+ /**
252
+ * Enable dynamic thresholding
253
+ * Enhances contrast at high CFG scales (scale > 7)
254
+ */
255
+ enableDynamicThresholding(): this;
256
+ /**
257
+ * Disable dynamic thresholding
258
+ */
259
+ disableDynamicThresholding(): this;
235
260
  /**
236
261
  * Build the V4 condition input structure for prompts
237
262
  */
@@ -367,5 +392,22 @@ declare function validateScale(scale: number): void;
367
392
  * Validates that seed is a valid unsigned 32-bit integer
368
393
  */
369
394
  declare function validateSeed(seed: number): void;
395
+ /**
396
+ * Warning result for prompt length check
397
+ */
398
+ interface PromptWarning {
399
+ isWarning: boolean;
400
+ message?: string;
401
+ length: number;
402
+ limit: number;
403
+ }
404
+ /**
405
+ * Check if prompt length exceeds recommended limit
406
+ * T5 encoder has different tokenization than CLIP, so this is a heuristic
407
+ * @param prompt - The full prompt string
408
+ * @param limit - Character limit (default: 2000)
409
+ * @returns Warning object with details
410
+ */
411
+ declare function checkPromptLength(prompt: string, limit?: number): PromptWarning;
370
412
 
371
- export { type ClientConfig, type GenerateImagePayload, type ImageGenerationOptions, type ImageMetadata, ImageRequestBuilder, type ImageResponse, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, type NovelAIParameters, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, UCPreset, type V4ConditionInput, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
413
+ export { type ClientConfig, type GenerateImagePayload, type ImageGenerationOptions, type ImageMetadata, ImageRequestBuilder, type ImageResponse, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, type NovelAIParameters, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, type PromptWarning, UCPreset, type V4ConditionInput, checkPromptLength, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
package/dist/index.d.ts CHANGED
@@ -82,6 +82,7 @@ interface NovelAIParameters {
82
82
  noise_schedule: NoiseSchedule | string;
83
83
  sm: boolean;
84
84
  sm_dyn: boolean;
85
+ dynamic_thresholding: boolean;
85
86
  prefer_brownian: boolean;
86
87
  deliberate_euler_ancestral_bug: boolean;
87
88
  legacy: boolean;
@@ -161,14 +162,17 @@ declare class ImageRequestBuilder {
161
162
  private prompt;
162
163
  private characterPrompts;
163
164
  private negativePrompt;
165
+ private characterNegativePrompts;
164
166
  private seed;
165
167
  private steps;
166
168
  private scale;
169
+ private nSamples;
167
170
  private sampler;
168
171
  private ucPreset;
169
172
  private qualityToggle;
170
173
  private smea;
171
174
  private smeaDyn;
175
+ private dynamicThresholding;
172
176
  private noiseSchedule;
173
177
  constructor(client: NovelAIClient);
174
178
  /**
@@ -191,8 +195,14 @@ declare class ImageRequestBuilder {
191
195
  addCharacter(characterPrompt: string): this;
192
196
  /**
193
197
  * Set the negative prompt (what to avoid in generation)
198
+ * Optionally provide per-character negative prompts
194
199
  */
195
- setNegativePrompt(negative: string): this;
200
+ setNegativePrompt(base: string, characterNegatives?: string[]): this;
201
+ /**
202
+ * Add a per-character negative prompt
203
+ * Should correspond to character prompts added via addCharacter()
204
+ */
205
+ addCharacterNegative(negativePrompt: string): this;
196
206
  /**
197
207
  * Set the random seed for reproducible generations
198
208
  */
@@ -207,6 +217,12 @@ declare class ImageRequestBuilder {
207
217
  * @throws ValidationError if scale is out of range (0-10)
208
218
  */
209
219
  setScale(scale: number): this;
220
+ /**
221
+ * Set the number of images to generate in a single request
222
+ * Note: Each additional sample consumes Anlas credits
223
+ * @param count - Number of images (1-4 typically supported)
224
+ */
225
+ setBatchSize(count: number): this;
210
226
  /**
211
227
  * Set the sampling algorithm
212
228
  */
@@ -232,6 +248,15 @@ declare class ImageRequestBuilder {
232
248
  * Set the noise schedule algorithm
233
249
  */
234
250
  setNoiseSchedule(schedule: NoiseSchedule): this;
251
+ /**
252
+ * Enable dynamic thresholding
253
+ * Enhances contrast at high CFG scales (scale > 7)
254
+ */
255
+ enableDynamicThresholding(): this;
256
+ /**
257
+ * Disable dynamic thresholding
258
+ */
259
+ disableDynamicThresholding(): this;
235
260
  /**
236
261
  * Build the V4 condition input structure for prompts
237
262
  */
@@ -367,5 +392,22 @@ declare function validateScale(scale: number): void;
367
392
  * Validates that seed is a valid unsigned 32-bit integer
368
393
  */
369
394
  declare function validateSeed(seed: number): void;
395
+ /**
396
+ * Warning result for prompt length check
397
+ */
398
+ interface PromptWarning {
399
+ isWarning: boolean;
400
+ message?: string;
401
+ length: number;
402
+ limit: number;
403
+ }
404
+ /**
405
+ * Check if prompt length exceeds recommended limit
406
+ * T5 encoder has different tokenization than CLIP, so this is a heuristic
407
+ * @param prompt - The full prompt string
408
+ * @param limit - Character limit (default: 2000)
409
+ * @returns Warning object with details
410
+ */
411
+ declare function checkPromptLength(prompt: string, limit?: number): PromptWarning;
370
412
 
371
- export { type ClientConfig, type GenerateImagePayload, type ImageGenerationOptions, type ImageMetadata, ImageRequestBuilder, type ImageResponse, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, type NovelAIParameters, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, UCPreset, type V4ConditionInput, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
413
+ export { type ClientConfig, type GenerateImagePayload, type ImageGenerationOptions, type ImageMetadata, ImageRequestBuilder, type ImageResponse, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, type NovelAIParameters, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, type PromptWarning, UCPreset, type V4ConditionInput, checkPromptLength, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
package/dist/index.js CHANGED
@@ -289,6 +289,16 @@ function validateSeed(seed) {
289
289
  throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);
290
290
  }
291
291
  }
292
+ function checkPromptLength(prompt, limit = 2e3) {
293
+ const length = prompt.length;
294
+ const isWarning = length > limit;
295
+ return {
296
+ isWarning,
297
+ message: isWarning ? `Prompt length (${length} chars) exceeds recommended limit of ${limit}. This may cause truncation or unexpected results.` : void 0,
298
+ length,
299
+ limit
300
+ };
301
+ }
292
302
 
293
303
  // src/builder/ImageRequestBuilder.ts
294
304
  var ImageRequestBuilder = class {
@@ -300,14 +310,17 @@ var ImageRequestBuilder = class {
300
310
  this.prompt = "";
301
311
  this.characterPrompts = [];
302
312
  this.negativePrompt = "";
313
+ this.characterNegativePrompts = [];
303
314
  this.seed = Math.floor(Math.random() * 4294967295);
304
315
  this.steps = 23;
305
316
  this.scale = 5;
317
+ this.nSamples = 1;
306
318
  this.sampler = "k_euler_ancestral" /* EulerAncestral */;
307
319
  this.ucPreset = 0 /* Heavy */;
308
320
  this.qualityToggle = true;
309
321
  this.smea = false;
310
322
  this.smeaDyn = false;
323
+ this.dynamicThresholding = false;
311
324
  this.noiseSchedule = "karras" /* Karras */;
312
325
  this.client = client;
313
326
  }
@@ -348,9 +361,21 @@ var ImageRequestBuilder = class {
348
361
  }
349
362
  /**
350
363
  * Set the negative prompt (what to avoid in generation)
364
+ * Optionally provide per-character negative prompts
365
+ */
366
+ setNegativePrompt(base, characterNegatives) {
367
+ this.negativePrompt = base;
368
+ if (characterNegatives) {
369
+ this.characterNegativePrompts = characterNegatives;
370
+ }
371
+ return this;
372
+ }
373
+ /**
374
+ * Add a per-character negative prompt
375
+ * Should correspond to character prompts added via addCharacter()
351
376
  */
352
- setNegativePrompt(negative) {
353
- this.negativePrompt = negative;
377
+ addCharacterNegative(negativePrompt) {
378
+ this.characterNegativePrompts.push(negativePrompt);
354
379
  return this;
355
380
  }
356
381
  /**
@@ -379,6 +404,18 @@ var ImageRequestBuilder = class {
379
404
  this.scale = scale;
380
405
  return this;
381
406
  }
407
+ /**
408
+ * Set the number of images to generate in a single request
409
+ * Note: Each additional sample consumes Anlas credits
410
+ * @param count - Number of images (1-4 typically supported)
411
+ */
412
+ setBatchSize(count) {
413
+ if (!Number.isInteger(count) || count < 1) {
414
+ throw new Error("Batch size must be a positive integer");
415
+ }
416
+ this.nSamples = count;
417
+ return this;
418
+ }
382
419
  /**
383
420
  * Set the sampling algorithm
384
421
  */
@@ -424,6 +461,21 @@ var ImageRequestBuilder = class {
424
461
  this.noiseSchedule = schedule;
425
462
  return this;
426
463
  }
464
+ /**
465
+ * Enable dynamic thresholding
466
+ * Enhances contrast at high CFG scales (scale > 7)
467
+ */
468
+ enableDynamicThresholding() {
469
+ this.dynamicThresholding = true;
470
+ return this;
471
+ }
472
+ /**
473
+ * Disable dynamic thresholding
474
+ */
475
+ disableDynamicThresholding() {
476
+ this.dynamicThresholding = false;
477
+ return this;
478
+ }
427
479
  /**
428
480
  * Build the V4 condition input structure for prompts
429
481
  */
@@ -458,12 +510,12 @@ var ImageRequestBuilder = class {
458
510
  scale: this.scale,
459
511
  sampler: this.sampler,
460
512
  steps: this.steps,
461
- n_samples: 1,
513
+ n_samples: this.nSamples,
462
514
  seed: this.seed,
463
515
  negative_prompt: this.negativePrompt,
464
516
  // V4-specific structured prompts
465
517
  v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),
466
- v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, []),
518
+ v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, this.characterNegativePrompts),
467
519
  // Quality and preset controls (camelCase - API requirement)
468
520
  qualityToggle: this.qualityToggle,
469
521
  ucPreset: this.ucPreset,
@@ -472,6 +524,7 @@ var ImageRequestBuilder = class {
472
524
  noise_schedule: this.noiseSchedule,
473
525
  sm: this.smea,
474
526
  sm_dyn: this.smeaDyn,
527
+ dynamic_thresholding: this.dynamicThresholding,
475
528
  prefer_brownian: true,
476
529
  deliberate_euler_ancestral_bug: true,
477
530
  legacy: false,
@@ -525,6 +578,6 @@ var NovelAIClient = class {
525
578
  }
526
579
  };
527
580
 
528
- export { ImageRequestBuilder, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, UCPreset, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
581
+ export { ImageRequestBuilder, NoiseSchedule, NovelAIAuthError, NovelAIClient, NovelAIError, NovelAIModel, NovelAINetworkError, NovelAIPaymentError, NovelAIRateLimitError, NovelAISampler, NovelAIServerError, NovelAIValidationError, UCPreset, checkPromptLength, toBase64, toDataURL, validateResolution, validateScale, validateSeed, validateSteps };
529
582
  //# sourceMappingURL=index.js.map
530
583
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/index.ts","../src/utils/ZipParser.ts","../src/network/APIClient.ts","../src/types/Model.ts","../src/types/Sampler.ts","../src/utils/Validators.ts","../src/builder/ImageRequestBuilder.ts","../src/client/NovelAIClient.ts"],"names":["NovelAIModel","NovelAISampler","UCPreset","NoiseSchedule"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base error class for all NovelAI SDK errors\n */\nexport class NovelAIError extends Error {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = 'NovelAIError';\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Authentication error (401/403)\n * Thrown when the API token is invalid or expired\n */\nexport class NovelAIAuthError extends NovelAIError {\n constructor(message = 'Authentication failed. Check your Persistent API Token (pst-...).') {\n super(message, 401);\n this.name = 'NovelAIAuthError';\n }\n}\n\n/**\n * Payment required error (402)\n * Thrown when the user has insufficient Anlas credits\n */\nexport class NovelAIPaymentError extends NovelAIError {\n constructor(message = 'Insufficient Anlas credits for this generation.') {\n super(message, 402);\n this.name = 'NovelAIPaymentError';\n }\n}\n\n/**\n * Validation error (400)\n * Thrown when the API rejects the payload due to schema issues\n */\nexport class NovelAIValidationError extends NovelAIError {\n public readonly details?: string;\n\n constructor(message: string, details?: string) {\n super(message, 400);\n this.name = 'NovelAIValidationError';\n this.details = details;\n }\n}\n\n/**\n * Network error\n * Thrown on timeouts, connection failures, or other network issues\n */\nexport class NovelAINetworkError extends NovelAIError {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'NovelAINetworkError';\n this.cause = cause;\n }\n}\n\n/**\n * Rate limit error (429)\n * Thrown when too many requests are made\n */\nexport class NovelAIRateLimitError extends NovelAIError {\n public readonly retryAfter?: number;\n\n constructor(message = 'Rate limit exceeded. Please wait before retrying.', retryAfter?: number) {\n super(message, 429);\n this.name = 'NovelAIRateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Server error (500+)\n * Thrown when the NovelAI server encounters an internal error\n */\nexport class NovelAIServerError extends NovelAIError {\n public readonly correlationId?: string;\n\n constructor(message = 'NovelAI server error. This may be due to payload schema issues.', correlationId?: string) {\n super(message, 500);\n this.name = 'NovelAIServerError';\n this.correlationId = correlationId;\n }\n}\n","/**\n * Isomorphic ZIP parser that works in both Node.js and browser environments\n * Extracts PNG files from NovelAI's application/x-zip-compressed response\n */\n\n/**\n * Detects if we're running in a Node.js environment\n */\nfunction isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Extract PNG files from a ZIP archive buffer\n * @param data - The raw ZIP archive data\n * @returns Array of extracted PNG file contents\n */\nexport async function extractImagesFromZip(\n data: ArrayBuffer | Uint8Array\n): Promise<Uint8Array[]> {\n const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n\n if (isNodeEnvironment()) {\n return extractWithAdmZip(buffer);\n } else {\n return extractWithFflate(buffer);\n }\n}\n\n/**\n * Node.js extraction using adm-zip\n */\nasync function extractWithAdmZip(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for Node.js environment\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(Buffer.from(buffer));\n const entries = zip.getEntries();\n const images: Uint8Array[] = [];\n\n for (const entry of entries) {\n if (entry.entryName.endsWith('.png') && !entry.isDirectory) {\n const data = entry.getData();\n images.push(new Uint8Array(data));\n }\n }\n\n return images;\n}\n\n/**\n * Browser extraction using fflate\n */\nasync function extractWithFflate(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for browser environment\n const { unzipSync } = await import('fflate');\n const unzipped = unzipSync(buffer);\n const images: Uint8Array[] = [];\n\n for (const [filename, data] of Object.entries(unzipped)) {\n if (filename.endsWith('.png')) {\n images.push(data);\n }\n }\n\n return images;\n}\n\n/**\n * Convert Uint8Array to Base64 string (useful for browser display)\n */\nexport function toBase64(data: Uint8Array): string {\n if (isNodeEnvironment()) {\n return Buffer.from(data).toString('base64');\n } else {\n // Browser environment\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Convert Uint8Array to data URL for direct use in img src\n */\nexport function toDataURL(data: Uint8Array, mimeType = 'image/png'): string {\n return `data:${mimeType};base64,${toBase64(data)}`;\n}\n","import type { GenerateImagePayload, ImageResponse, APIErrorResponse } from '../types';\nimport {\n NovelAIError,\n NovelAIAuthError,\n NovelAIPaymentError,\n NovelAIValidationError,\n NovelAINetworkError,\n NovelAIRateLimitError,\n NovelAIServerError,\n} from '../errors';\nimport { extractImagesFromZip } from '../utils/ZipParser';\n\nconst DEFAULT_BASE_URL = 'https://image.novelai.net';\nconst DEFAULT_TIMEOUT = 60000;\nconst GENERATE_ENDPOINT = '/ai/generate-image';\n\nexport interface APIClientConfig {\n token: string;\n baseUrl?: string;\n timeout?: number;\n}\n\n/**\n * Low-level HTTP client for NovelAI API\n * Handles authentication, binary response parsing, and error mapping\n */\nexport class APIClient {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: APIClientConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * Generate an image using the NovelAI API\n */\n async generateImage(payload: GenerateImagePayload): Promise<ImageResponse> {\n const url = `${this.baseUrl}${GENERATE_ENDPOINT}`;\n\n // Generate correlation ID for debugging\n const correlationId = this.generateCorrelationId();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/x-zip-compressed, application/json',\n 'x-correlation-id': correlationId,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response, correlationId);\n }\n\n // Parse the ZIP response\n const arrayBuffer = await response.arrayBuffer();\n const images = await extractImagesFromZip(arrayBuffer);\n\n return {\n images,\n metadata: {\n seed: payload.parameters.seed,\n prompt: payload.input,\n model: payload.model,\n sampler: payload.parameters.sampler as string,\n steps: payload.parameters.steps,\n scale: payload.parameters.scale,\n },\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof NovelAIError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new NovelAINetworkError(`Request timed out after ${this.timeout}ms`, error);\n }\n throw new NovelAINetworkError(`Network error: ${error.message}`, error);\n }\n\n throw new NovelAINetworkError('An unknown error occurred');\n }\n }\n\n /**\n * Handle non-2xx responses and throw appropriate errors\n */\n private async handleErrorResponse(response: Response, correlationId: string): Promise<never> {\n let errorBody: APIErrorResponse | null = null;\n\n try {\n errorBody = await response.json() as APIErrorResponse;\n } catch {\n // Response may not be JSON\n }\n\n const message = errorBody?.message ?? errorBody?.error ?? response.statusText;\n\n switch (response.status) {\n case 400:\n throw new NovelAIValidationError(\n `Bad request: ${message}`,\n JSON.stringify(errorBody)\n );\n case 401:\n case 403:\n throw new NovelAIAuthError(message);\n case 402:\n throw new NovelAIPaymentError(message);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n throw new NovelAIRateLimitError(message, retryAfter ? parseInt(retryAfter) : undefined);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n throw new NovelAIServerError(\n `Server error (${response.status}): ${message}. This may be caused by payload schema issues.`,\n correlationId\n );\n default:\n throw new NovelAIError(\n `HTTP ${response.status}: ${message}`,\n response.status\n );\n }\n }\n\n /**\n * Generate a 6-character alphanumeric correlation ID for debugging\n */\n private generateCorrelationId(): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 6; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n }\n}\n","/**\n * Supported NovelAI image generation models\n */\nexport enum NovelAIModel {\n /** V4.5 Full - Latest model with T5 encoding and multi-character support */\n V45_Full = \"nai-diffusion-4-5-full\",\n /** V4 Curated - More conservative aesthetic choices */\n V4_Curated = \"nai-diffusion-4-curated\",\n /** V4 Inpainting - For image editing and inpainting tasks */\n Inpainting = \"nai-diffusion-4-inpainting\",\n}\n","/**\n * Supported sampling algorithms for image generation\n */\nexport enum NovelAISampler {\n /** Standard Euler sampler */\n Euler = \"k_euler\",\n /** Euler Ancestral - recommended for anime-style generations */\n EulerAncestral = \"k_euler_ancestral\",\n /** DPM++ 2M - stable and aesthetic */\n DPM_2M = \"k_dpmpp_2m\",\n /** DPM++ 2S Ancestral */\n DPM_2S_Ancestral = \"k_dpmpp_2s_ancestral\",\n /** DPM++ SDE */\n DPM_SDE = \"k_dpmpp_sde\",\n /** DDIM V3 */\n DDIM = \"ddim_v3\",\n}\n\n/**\n * Preset negative prompt configurations\n */\nexport enum UCPreset {\n /** Heavy - Low Quality + Bad Anatomy */\n Heavy = 0,\n /** Light - Low Quality only */\n Light = 1,\n /** None - Use custom negative prompt only */\n None = 2,\n}\n\n/**\n * Noise schedule algorithms\n */\nexport enum NoiseSchedule {\n Native = \"native\",\n Karras = \"karras\",\n Exponential = \"exponential\",\n Polyexponential = \"polyexponential\",\n}\n","/**\n * Validation error for invalid SDK parameters\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Validates that image dimensions are multiples of 64\n * @throws ValidationError if dimensions are invalid\n */\nexport function validateResolution(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height)) {\n throw new ValidationError('Width and height must be integers');\n }\n if (width <= 0 || height <= 0) {\n throw new ValidationError('Width and height must be positive');\n }\n if (width % 64 !== 0) {\n throw new ValidationError(`Width must be a multiple of 64, got ${width}`);\n }\n if (height % 64 !== 0) {\n throw new ValidationError(`Height must be a multiple of 64, got ${height}`);\n }\n}\n\n/**\n * Validates that step count is within acceptable range\n * @throws ValidationError if steps are out of range\n */\nexport function validateSteps(steps: number): void {\n if (!Number.isInteger(steps)) {\n throw new ValidationError('Steps must be an integer');\n }\n if (steps < 1 || steps > 50) {\n throw new ValidationError(`Steps must be between 1 and 50, got ${steps}`);\n }\n}\n\n/**\n * Validates that scale (CFG) is within acceptable range\n * @throws ValidationError if scale is out of range\n */\nexport function validateScale(scale: number): void {\n if (typeof scale !== 'number' || isNaN(scale)) {\n throw new ValidationError('Scale must be a number');\n }\n if (scale < 0 || scale > 10) {\n throw new ValidationError(`Scale must be between 0 and 10, got ${scale}`);\n }\n}\n\n/**\n * Validates that seed is a valid unsigned 32-bit integer\n */\nexport function validateSeed(seed: number): void {\n if (!Number.isInteger(seed)) {\n throw new ValidationError('Seed must be an integer');\n }\n if (seed < 0 || seed > 4294967295) {\n throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);\n }\n}\n","import type { NovelAIClient } from '../client/NovelAIClient';\nimport type {\n GenerateImagePayload,\n NovelAIParameters,\n V4ConditionInput,\n ImageResponse,\n} from '../types';\nimport { NovelAIModel, NovelAISampler, UCPreset, NoiseSchedule } from '../types';\nimport { validateResolution, validateSteps, validateScale, validateSeed } from '../utils/Validators';\n\n/**\n * Fluent builder for constructing NovelAI image generation requests\n * Provides method chaining and compile-time type safety\n */\nexport class ImageRequestBuilder {\n private client: NovelAIClient;\n\n // Core parameters with sensible defaults\n private model: NovelAIModel = NovelAIModel.V45_Full;\n private width = 832;\n private height = 1216;\n private prompt = '';\n private characterPrompts: string[] = [];\n private negativePrompt = '';\n private seed: number = Math.floor(Math.random() * 4294967295);\n private steps = 23;\n private scale = 5.0;\n private sampler: NovelAISampler = NovelAISampler.EulerAncestral;\n private ucPreset: UCPreset = UCPreset.Heavy;\n private qualityToggle = true;\n private smea = false;\n private smeaDyn = false;\n private noiseSchedule: NoiseSchedule = NoiseSchedule.Karras;\n\n constructor(client: NovelAIClient) {\n this.client = client;\n }\n\n /**\n * Set the model to use for generation\n */\n setModel(model: NovelAIModel): this {\n this.model = model;\n return this;\n }\n\n /**\n * Set the output image dimensions\n * @throws ValidationError if dimensions are not multiples of 64\n */\n setSize(width: number, height: number): this {\n validateResolution(width, height);\n this.width = width;\n this.height = height;\n return this;\n }\n\n /**\n * Set the main prompt (base scene description)\n * For multi-character prompts, use the array overload\n */\n setPrompt(base: string, characters?: string[]): this {\n this.prompt = base;\n if (characters) {\n this.characterPrompts = characters;\n }\n return this;\n }\n\n /**\n * Add character prompts for multi-character scenes\n */\n addCharacter(characterPrompt: string): this {\n this.characterPrompts.push(characterPrompt);\n return this;\n }\n\n /**\n * Set the negative prompt (what to avoid in generation)\n */\n setNegativePrompt(negative: string): this {\n this.negativePrompt = negative;\n return this;\n }\n\n /**\n * Set the random seed for reproducible generations\n */\n setSeed(seed: number): this {\n validateSeed(seed);\n this.seed = seed;\n return this;\n }\n\n /**\n * Set the number of sampling steps\n * @throws ValidationError if steps are out of range (1-50)\n */\n setSteps(steps: number): this {\n validateSteps(steps);\n this.steps = steps;\n return this;\n }\n\n /**\n * Set the guidance scale (CFG)\n * @throws ValidationError if scale is out of range (0-10)\n */\n setScale(scale: number): this {\n validateScale(scale);\n this.scale = scale;\n return this;\n }\n\n /**\n * Set the sampling algorithm\n */\n setSampler(sampler: NovelAISampler): this {\n this.sampler = sampler;\n return this;\n }\n\n /**\n * Set the UC preset (predefined negative prompt configuration)\n */\n setUCPreset(preset: UCPreset): this {\n this.ucPreset = preset;\n return this;\n }\n\n /**\n * Toggle automatic quality tags insertion\n */\n setQualityToggle(enabled: boolean): this {\n this.qualityToggle = enabled;\n return this;\n }\n\n /**\n * Enable SMEA (Sinusoidal Multipass Euler Ancestral)\n * @param dynamic - If true, enables dynamic SMEA variant\n */\n enableSMEA(dynamic = false): this {\n this.smea = true;\n this.smeaDyn = dynamic;\n return this;\n }\n\n /**\n * Disable SMEA\n */\n disableSMEA(): this {\n this.smea = false;\n this.smeaDyn = false;\n return this;\n }\n\n /**\n * Set the noise schedule algorithm\n */\n setNoiseSchedule(schedule: NoiseSchedule): this {\n this.noiseSchedule = schedule;\n return this;\n }\n\n /**\n * Build the V4 condition input structure for prompts\n */\n private buildV4ConditionInput(base: string, characters: string[]): V4ConditionInput {\n return {\n caption: {\n base_caption: base,\n char_captions: characters,\n },\n use_coords: false,\n use_order: true,\n legacy_uc: false,\n };\n }\n\n /**\n * Build the formatted input string for the API\n * Combines base prompt with character prompts using pipe delimiter\n */\n private buildInputString(): string {\n if (this.characterPrompts.length === 0) {\n return this.prompt;\n }\n return [this.prompt, ...this.characterPrompts].join(' | ');\n }\n\n /**\n * Build the complete API payload\n */\n buildPayload(): GenerateImagePayload {\n const parameters: NovelAIParameters = {\n width: this.width,\n height: this.height,\n scale: this.scale,\n sampler: this.sampler,\n steps: this.steps,\n n_samples: 1,\n seed: this.seed,\n negative_prompt: this.negativePrompt,\n\n // V4-specific structured prompts\n v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),\n v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, []),\n\n // Quality and preset controls (camelCase - API requirement)\n qualityToggle: this.qualityToggle,\n ucPreset: this.ucPreset,\n\n // Technical flags (snake_case - API requirement)\n params_version: 3,\n noise_schedule: this.noiseSchedule,\n sm: this.smea,\n sm_dyn: this.smeaDyn,\n prefer_brownian: true,\n deliberate_euler_ancestral_bug: true,\n legacy: false,\n legacy_v3_extend: false,\n };\n\n return {\n input: this.buildInputString(),\n model: this.model,\n action: 'generate',\n parameters,\n };\n }\n\n /**\n * Execute the image generation request\n */\n async generate(): Promise<ImageResponse> {\n const payload = this.buildPayload();\n return this.client._execute(payload);\n }\n}\n","import type { ClientConfig, GenerateImagePayload, ImageResponse } from '../types';\nimport { APIClient } from '../network/APIClient';\nimport { ImageRequestBuilder } from '../builder/ImageRequestBuilder';\n\n/**\n * Main entry point for the NovelAI Image SDK\n * \n * @example\n * ```typescript\n * const client = new NovelAIClient({ token: process.env.NAI_TOKEN });\n * \n * const result = await client.image()\n * .setPrompt('1girl, cyberpunk, neon lights')\n * .setSize(832, 1216)\n * .generate();\n * \n * fs.writeFileSync('output.png', result.images[0]);\n * ```\n */\nexport class NovelAIClient {\n private readonly apiClient: APIClient;\n\n /**\n * Create a new NovelAI client\n * @param config - Client configuration including token and optional base URL\n */\n constructor(config: ClientConfig) {\n if (!config.token) {\n throw new Error('NovelAI API token is required');\n }\n\n this.apiClient = new APIClient({\n token: config.token,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n }\n\n /**\n * Start building an image generation request\n * @returns A new ImageRequestBuilder instance\n */\n image(): ImageRequestBuilder {\n return new ImageRequestBuilder(this);\n }\n\n /**\n * Execute a generation request (called internally by the builder)\n * @internal\n */\n async _execute(payload: GenerateImagePayload): Promise<ImageResponse> {\n return this.apiClient.generateImage(payload);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/errors/index.ts","../src/utils/ZipParser.ts","../src/network/APIClient.ts","../src/types/Model.ts","../src/types/Sampler.ts","../src/utils/Validators.ts","../src/builder/ImageRequestBuilder.ts","../src/client/NovelAIClient.ts"],"names":["NovelAIModel","NovelAISampler","UCPreset","NoiseSchedule"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Base error class for all NovelAI SDK errors\n */\nexport class NovelAIError extends Error {\n public readonly statusCode?: number;\n\n constructor(message: string, statusCode?: number) {\n super(message);\n this.name = 'NovelAIError';\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Authentication error (401/403)\n * Thrown when the API token is invalid or expired\n */\nexport class NovelAIAuthError extends NovelAIError {\n constructor(message = 'Authentication failed. Check your Persistent API Token (pst-...).') {\n super(message, 401);\n this.name = 'NovelAIAuthError';\n }\n}\n\n/**\n * Payment required error (402)\n * Thrown when the user has insufficient Anlas credits\n */\nexport class NovelAIPaymentError extends NovelAIError {\n constructor(message = 'Insufficient Anlas credits for this generation.') {\n super(message, 402);\n this.name = 'NovelAIPaymentError';\n }\n}\n\n/**\n * Validation error (400)\n * Thrown when the API rejects the payload due to schema issues\n */\nexport class NovelAIValidationError extends NovelAIError {\n public readonly details?: string;\n\n constructor(message: string, details?: string) {\n super(message, 400);\n this.name = 'NovelAIValidationError';\n this.details = details;\n }\n}\n\n/**\n * Network error\n * Thrown on timeouts, connection failures, or other network issues\n */\nexport class NovelAINetworkError extends NovelAIError {\n public readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message);\n this.name = 'NovelAINetworkError';\n this.cause = cause;\n }\n}\n\n/**\n * Rate limit error (429)\n * Thrown when too many requests are made\n */\nexport class NovelAIRateLimitError extends NovelAIError {\n public readonly retryAfter?: number;\n\n constructor(message = 'Rate limit exceeded. Please wait before retrying.', retryAfter?: number) {\n super(message, 429);\n this.name = 'NovelAIRateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Server error (500+)\n * Thrown when the NovelAI server encounters an internal error\n */\nexport class NovelAIServerError extends NovelAIError {\n public readonly correlationId?: string;\n\n constructor(message = 'NovelAI server error. This may be due to payload schema issues.', correlationId?: string) {\n super(message, 500);\n this.name = 'NovelAIServerError';\n this.correlationId = correlationId;\n }\n}\n","/**\n * Isomorphic ZIP parser that works in both Node.js and browser environments\n * Extracts PNG files from NovelAI's application/x-zip-compressed response\n */\n\n/**\n * Detects if we're running in a Node.js environment\n */\nfunction isNodeEnvironment(): boolean {\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null\n );\n}\n\n/**\n * Extract PNG files from a ZIP archive buffer\n * @param data - The raw ZIP archive data\n * @returns Array of extracted PNG file contents\n */\nexport async function extractImagesFromZip(\n data: ArrayBuffer | Uint8Array\n): Promise<Uint8Array[]> {\n const buffer = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n\n if (isNodeEnvironment()) {\n return extractWithAdmZip(buffer);\n } else {\n return extractWithFflate(buffer);\n }\n}\n\n/**\n * Node.js extraction using adm-zip\n */\nasync function extractWithAdmZip(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for Node.js environment\n const AdmZip = (await import('adm-zip')).default;\n const zip = new AdmZip(Buffer.from(buffer));\n const entries = zip.getEntries();\n const images: Uint8Array[] = [];\n\n for (const entry of entries) {\n if (entry.entryName.endsWith('.png') && !entry.isDirectory) {\n const data = entry.getData();\n images.push(new Uint8Array(data));\n }\n }\n\n return images;\n}\n\n/**\n * Browser extraction using fflate\n */\nasync function extractWithFflate(buffer: Uint8Array): Promise<Uint8Array[]> {\n // Dynamic import for browser environment\n const { unzipSync } = await import('fflate');\n const unzipped = unzipSync(buffer);\n const images: Uint8Array[] = [];\n\n for (const [filename, data] of Object.entries(unzipped)) {\n if (filename.endsWith('.png')) {\n images.push(data);\n }\n }\n\n return images;\n}\n\n/**\n * Convert Uint8Array to Base64 string (useful for browser display)\n */\nexport function toBase64(data: Uint8Array): string {\n if (isNodeEnvironment()) {\n return Buffer.from(data).toString('base64');\n } else {\n // Browser environment\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n}\n\n/**\n * Convert Uint8Array to data URL for direct use in img src\n */\nexport function toDataURL(data: Uint8Array, mimeType = 'image/png'): string {\n return `data:${mimeType};base64,${toBase64(data)}`;\n}\n","import type { GenerateImagePayload, ImageResponse, APIErrorResponse } from '../types';\nimport {\n NovelAIError,\n NovelAIAuthError,\n NovelAIPaymentError,\n NovelAIValidationError,\n NovelAINetworkError,\n NovelAIRateLimitError,\n NovelAIServerError,\n} from '../errors';\nimport { extractImagesFromZip } from '../utils/ZipParser';\n\nconst DEFAULT_BASE_URL = 'https://image.novelai.net';\nconst DEFAULT_TIMEOUT = 60000;\nconst GENERATE_ENDPOINT = '/ai/generate-image';\n\nexport interface APIClientConfig {\n token: string;\n baseUrl?: string;\n timeout?: number;\n}\n\n/**\n * Low-level HTTP client for NovelAI API\n * Handles authentication, binary response parsing, and error mapping\n */\nexport class APIClient {\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: APIClientConfig) {\n this.token = config.token;\n this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n }\n\n /**\n * Generate an image using the NovelAI API\n */\n async generateImage(payload: GenerateImagePayload): Promise<ImageResponse> {\n const url = `${this.baseUrl}${GENERATE_ENDPOINT}`;\n\n // Generate correlation ID for debugging\n const correlationId = this.generateCorrelationId();\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n 'Accept': 'application/x-zip-compressed, application/json',\n 'x-correlation-id': correlationId,\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response, correlationId);\n }\n\n // Parse the ZIP response\n const arrayBuffer = await response.arrayBuffer();\n const images = await extractImagesFromZip(arrayBuffer);\n\n return {\n images,\n metadata: {\n seed: payload.parameters.seed,\n prompt: payload.input,\n model: payload.model,\n sampler: payload.parameters.sampler as string,\n steps: payload.parameters.steps,\n scale: payload.parameters.scale,\n },\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n if (error instanceof NovelAIError) {\n throw error;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new NovelAINetworkError(`Request timed out after ${this.timeout}ms`, error);\n }\n throw new NovelAINetworkError(`Network error: ${error.message}`, error);\n }\n\n throw new NovelAINetworkError('An unknown error occurred');\n }\n }\n\n /**\n * Handle non-2xx responses and throw appropriate errors\n */\n private async handleErrorResponse(response: Response, correlationId: string): Promise<never> {\n let errorBody: APIErrorResponse | null = null;\n\n try {\n errorBody = await response.json() as APIErrorResponse;\n } catch {\n // Response may not be JSON\n }\n\n const message = errorBody?.message ?? errorBody?.error ?? response.statusText;\n\n switch (response.status) {\n case 400:\n throw new NovelAIValidationError(\n `Bad request: ${message}`,\n JSON.stringify(errorBody)\n );\n case 401:\n case 403:\n throw new NovelAIAuthError(message);\n case 402:\n throw new NovelAIPaymentError(message);\n case 429: {\n const retryAfter = response.headers.get('retry-after');\n throw new NovelAIRateLimitError(message, retryAfter ? parseInt(retryAfter) : undefined);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n throw new NovelAIServerError(\n `Server error (${response.status}): ${message}. This may be caused by payload schema issues.`,\n correlationId\n );\n default:\n throw new NovelAIError(\n `HTTP ${response.status}: ${message}`,\n response.status\n );\n }\n }\n\n /**\n * Generate a 6-character alphanumeric correlation ID for debugging\n */\n private generateCorrelationId(): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n let result = '';\n for (let i = 0; i < 6; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length));\n }\n return result;\n }\n}\n","/**\n * Supported NovelAI image generation models\n */\nexport enum NovelAIModel {\n /** V4.5 Full - Latest model with T5 encoding and multi-character support */\n V45_Full = \"nai-diffusion-4-5-full\",\n /** V4 Curated - More conservative aesthetic choices */\n V4_Curated = \"nai-diffusion-4-curated\",\n /** V4 Inpainting - For image editing and inpainting tasks */\n Inpainting = \"nai-diffusion-4-inpainting\",\n}\n","/**\n * Supported sampling algorithms for image generation\n */\nexport enum NovelAISampler {\n /** Standard Euler sampler */\n Euler = \"k_euler\",\n /** Euler Ancestral - recommended for anime-style generations */\n EulerAncestral = \"k_euler_ancestral\",\n /** DPM++ 2M - stable and aesthetic */\n DPM_2M = \"k_dpmpp_2m\",\n /** DPM++ 2S Ancestral */\n DPM_2S_Ancestral = \"k_dpmpp_2s_ancestral\",\n /** DPM++ SDE */\n DPM_SDE = \"k_dpmpp_sde\",\n /** DDIM V3 */\n DDIM = \"ddim_v3\",\n}\n\n/**\n * Preset negative prompt configurations\n */\nexport enum UCPreset {\n /** Heavy - Low Quality + Bad Anatomy */\n Heavy = 0,\n /** Light - Low Quality only */\n Light = 1,\n /** None - Use custom negative prompt only */\n None = 2,\n}\n\n/**\n * Noise schedule algorithms\n */\nexport enum NoiseSchedule {\n Native = \"native\",\n Karras = \"karras\",\n Exponential = \"exponential\",\n Polyexponential = \"polyexponential\",\n}\n","/**\n * Validation error for invalid SDK parameters\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Validates that image dimensions are multiples of 64\n * @throws ValidationError if dimensions are invalid\n */\nexport function validateResolution(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height)) {\n throw new ValidationError('Width and height must be integers');\n }\n if (width <= 0 || height <= 0) {\n throw new ValidationError('Width and height must be positive');\n }\n if (width % 64 !== 0) {\n throw new ValidationError(`Width must be a multiple of 64, got ${width}`);\n }\n if (height % 64 !== 0) {\n throw new ValidationError(`Height must be a multiple of 64, got ${height}`);\n }\n}\n\n/**\n * Validates that step count is within acceptable range\n * @throws ValidationError if steps are out of range\n */\nexport function validateSteps(steps: number): void {\n if (!Number.isInteger(steps)) {\n throw new ValidationError('Steps must be an integer');\n }\n if (steps < 1 || steps > 50) {\n throw new ValidationError(`Steps must be between 1 and 50, got ${steps}`);\n }\n}\n\n/**\n * Validates that scale (CFG) is within acceptable range\n * @throws ValidationError if scale is out of range\n */\nexport function validateScale(scale: number): void {\n if (typeof scale !== 'number' || isNaN(scale)) {\n throw new ValidationError('Scale must be a number');\n }\n if (scale < 0 || scale > 10) {\n throw new ValidationError(`Scale must be between 0 and 10, got ${scale}`);\n }\n}\n\n/**\n * Validates that seed is a valid unsigned 32-bit integer\n */\nexport function validateSeed(seed: number): void {\n if (!Number.isInteger(seed)) {\n throw new ValidationError('Seed must be an integer');\n }\n if (seed < 0 || seed > 4294967295) {\n throw new ValidationError(`Seed must be between 0 and 2^32-1, got ${seed}`);\n }\n}\n\n/**\n * Warning result for prompt length check\n */\nexport interface PromptWarning {\n isWarning: boolean;\n message?: string;\n length: number;\n limit: number;\n}\n\n/**\n * Check if prompt length exceeds recommended limit\n * T5 encoder has different tokenization than CLIP, so this is a heuristic\n * @param prompt - The full prompt string\n * @param limit - Character limit (default: 2000)\n * @returns Warning object with details\n */\nexport function checkPromptLength(prompt: string, limit = 2000): PromptWarning {\n const length = prompt.length;\n const isWarning = length > limit;\n \n return {\n isWarning,\n message: isWarning \n ? `Prompt length (${length} chars) exceeds recommended limit of ${limit}. This may cause truncation or unexpected results.`\n : undefined,\n length,\n limit,\n };\n}\n","import type { NovelAIClient } from '../client/NovelAIClient';\nimport type {\n GenerateImagePayload,\n NovelAIParameters,\n V4ConditionInput,\n ImageResponse,\n} from '../types';\nimport { NovelAIModel, NovelAISampler, UCPreset, NoiseSchedule } from '../types';\nimport { validateResolution, validateSteps, validateScale, validateSeed } from '../utils/Validators';\n\n/**\n * Fluent builder for constructing NovelAI image generation requests\n * Provides method chaining and compile-time type safety\n */\nexport class ImageRequestBuilder {\n private client: NovelAIClient;\n\n // Core parameters with sensible defaults\n private model: NovelAIModel = NovelAIModel.V45_Full;\n private width = 832;\n private height = 1216;\n private prompt = '';\n private characterPrompts: string[] = [];\n private negativePrompt = '';\n private characterNegativePrompts: string[] = [];\n private seed: number = Math.floor(Math.random() * 4294967295);\n private steps = 23;\n private scale = 5.0;\n private nSamples = 1;\n private sampler: NovelAISampler = NovelAISampler.EulerAncestral;\n private ucPreset: UCPreset = UCPreset.Heavy;\n private qualityToggle = true;\n private smea = false;\n private smeaDyn = false;\n private dynamicThresholding = false;\n private noiseSchedule: NoiseSchedule = NoiseSchedule.Karras;\n\n constructor(client: NovelAIClient) {\n this.client = client;\n }\n\n /**\n * Set the model to use for generation\n */\n setModel(model: NovelAIModel): this {\n this.model = model;\n return this;\n }\n\n /**\n * Set the output image dimensions\n * @throws ValidationError if dimensions are not multiples of 64\n */\n setSize(width: number, height: number): this {\n validateResolution(width, height);\n this.width = width;\n this.height = height;\n return this;\n }\n\n /**\n * Set the main prompt (base scene description)\n * For multi-character prompts, use the array overload\n */\n setPrompt(base: string, characters?: string[]): this {\n this.prompt = base;\n if (characters) {\n this.characterPrompts = characters;\n }\n return this;\n }\n\n /**\n * Add character prompts for multi-character scenes\n */\n addCharacter(characterPrompt: string): this {\n this.characterPrompts.push(characterPrompt);\n return this;\n }\n\n /**\n * Set the negative prompt (what to avoid in generation)\n * Optionally provide per-character negative prompts\n */\n setNegativePrompt(base: string, characterNegatives?: string[]): this {\n this.negativePrompt = base;\n if (characterNegatives) {\n this.characterNegativePrompts = characterNegatives;\n }\n return this;\n }\n\n /**\n * Add a per-character negative prompt\n * Should correspond to character prompts added via addCharacter()\n */\n addCharacterNegative(negativePrompt: string): this {\n this.characterNegativePrompts.push(negativePrompt);\n return this;\n }\n\n /**\n * Set the random seed for reproducible generations\n */\n setSeed(seed: number): this {\n validateSeed(seed);\n this.seed = seed;\n return this;\n }\n\n /**\n * Set the number of sampling steps\n * @throws ValidationError if steps are out of range (1-50)\n */\n setSteps(steps: number): this {\n validateSteps(steps);\n this.steps = steps;\n return this;\n }\n\n /**\n * Set the guidance scale (CFG)\n * @throws ValidationError if scale is out of range (0-10)\n */\n setScale(scale: number): this {\n validateScale(scale);\n this.scale = scale;\n return this;\n }\n\n /**\n * Set the number of images to generate in a single request\n * Note: Each additional sample consumes Anlas credits\n * @param count - Number of images (1-4 typically supported)\n */\n setBatchSize(count: number): this {\n if (!Number.isInteger(count) || count < 1) {\n throw new Error('Batch size must be a positive integer');\n }\n this.nSamples = count;\n return this;\n }\n\n /**\n * Set the sampling algorithm\n */\n setSampler(sampler: NovelAISampler): this {\n this.sampler = sampler;\n return this;\n }\n\n /**\n * Set the UC preset (predefined negative prompt configuration)\n */\n setUCPreset(preset: UCPreset): this {\n this.ucPreset = preset;\n return this;\n }\n\n /**\n * Toggle automatic quality tags insertion\n */\n setQualityToggle(enabled: boolean): this {\n this.qualityToggle = enabled;\n return this;\n }\n\n /**\n * Enable SMEA (Sinusoidal Multipass Euler Ancestral)\n * @param dynamic - If true, enables dynamic SMEA variant\n */\n enableSMEA(dynamic = false): this {\n this.smea = true;\n this.smeaDyn = dynamic;\n return this;\n }\n\n /**\n * Disable SMEA\n */\n disableSMEA(): this {\n this.smea = false;\n this.smeaDyn = false;\n return this;\n }\n\n /**\n * Set the noise schedule algorithm\n */\n setNoiseSchedule(schedule: NoiseSchedule): this {\n this.noiseSchedule = schedule;\n return this;\n }\n\n /**\n * Enable dynamic thresholding\n * Enhances contrast at high CFG scales (scale > 7)\n */\n enableDynamicThresholding(): this {\n this.dynamicThresholding = true;\n return this;\n }\n\n /**\n * Disable dynamic thresholding\n */\n disableDynamicThresholding(): this {\n this.dynamicThresholding = false;\n return this;\n }\n\n /**\n * Build the V4 condition input structure for prompts\n */\n private buildV4ConditionInput(base: string, characters: string[]): V4ConditionInput {\n return {\n caption: {\n base_caption: base,\n char_captions: characters,\n },\n use_coords: false,\n use_order: true,\n legacy_uc: false,\n };\n }\n\n /**\n * Build the formatted input string for the API\n * Combines base prompt with character prompts using pipe delimiter\n */\n private buildInputString(): string {\n if (this.characterPrompts.length === 0) {\n return this.prompt;\n }\n return [this.prompt, ...this.characterPrompts].join(' | ');\n }\n\n /**\n * Build the complete API payload\n */\n buildPayload(): GenerateImagePayload {\n const parameters: NovelAIParameters = {\n width: this.width,\n height: this.height,\n scale: this.scale,\n sampler: this.sampler,\n steps: this.steps,\n n_samples: this.nSamples,\n seed: this.seed,\n negative_prompt: this.negativePrompt,\n\n // V4-specific structured prompts\n v4_prompt: this.buildV4ConditionInput(this.prompt, this.characterPrompts),\n v4_negative_prompt: this.buildV4ConditionInput(this.negativePrompt, this.characterNegativePrompts),\n\n // Quality and preset controls (camelCase - API requirement)\n qualityToggle: this.qualityToggle,\n ucPreset: this.ucPreset,\n\n // Technical flags (snake_case - API requirement)\n params_version: 3,\n noise_schedule: this.noiseSchedule,\n sm: this.smea,\n sm_dyn: this.smeaDyn,\n dynamic_thresholding: this.dynamicThresholding,\n prefer_brownian: true,\n deliberate_euler_ancestral_bug: true,\n legacy: false,\n legacy_v3_extend: false,\n };\n\n return {\n input: this.buildInputString(),\n model: this.model,\n action: 'generate',\n parameters,\n };\n }\n\n /**\n * Execute the image generation request\n */\n async generate(): Promise<ImageResponse> {\n const payload = this.buildPayload();\n return this.client._execute(payload);\n }\n}\n","import type { ClientConfig, GenerateImagePayload, ImageResponse } from '../types';\nimport { APIClient } from '../network/APIClient';\nimport { ImageRequestBuilder } from '../builder/ImageRequestBuilder';\n\n/**\n * Main entry point for the NovelAI Image SDK\n * \n * @example\n * ```typescript\n * const client = new NovelAIClient({ token: process.env.NAI_TOKEN });\n * \n * const result = await client.image()\n * .setPrompt('1girl, cyberpunk, neon lights')\n * .setSize(832, 1216)\n * .generate();\n * \n * fs.writeFileSync('output.png', result.images[0]);\n * ```\n */\nexport class NovelAIClient {\n private readonly apiClient: APIClient;\n\n /**\n * Create a new NovelAI client\n * @param config - Client configuration including token and optional base URL\n */\n constructor(config: ClientConfig) {\n if (!config.token) {\n throw new Error('NovelAI API token is required');\n }\n\n this.apiClient = new APIClient({\n token: config.token,\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n });\n }\n\n /**\n * Start building an image generation request\n * @returns A new ImageRequestBuilder instance\n */\n image(): ImageRequestBuilder {\n return new ImageRequestBuilder(this);\n }\n\n /**\n * Execute a generation request (called internally by the builder)\n * @internal\n */\n async _execute(payload: GenerateImagePayload): Promise<ImageResponse> {\n return this.apiClient.generateImage(payload);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "novelai-image-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Type-safe TypeScript SDK for NovelAI V4.5 image generation API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -40,7 +40,7 @@
40
40
  "sdk"
41
41
  ],
42
42
  "author": "",
43
- "license": "MIT",
43
+ "license": "Apache-2.0",
44
44
  "dependencies": {
45
45
  "adm-zip": "^0.5.10",
46
46
  "fflate": "^0.8.2"