Skip to content

Commit fe9af5e

Browse files
committed
fix: add support for generate-image-stream endpoint and stream mode, better bot detection evasion
1 parent 7be747d commit fe9af5e

30 files changed

+1687
-1693
lines changed

LICENSE

Lines changed: 661 additions & 21 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,23 @@
1818
>
1919
> Built with modern JavaScript/TypeScript features for both browser and Node.js environments, it provides full access to NovelAI's latest models (V3, V4, V4.5) and Director tools while maintaining a clean interface. This project is based on the [NekoAI-API](https://github.com/Nya-Foundation/NekoAI-API) Python package.
2020
21+
### 📄 License Change Notice
22+
23+
> **Important**: This project has transitioned from MIT to **AGPL-3.0** license to ensure better compliance and alignment with our inspiration source. As this work builds significantly upon concepts and approaches from NekoAI-API, we've adopted a more appropriate license that better reflects the collaborative nature of open-source development and provides stronger copyleft protections for the community.
24+
2125
## 🌟 Core Capabilities
2226

2327
| Feature | Description |
2428
| --------------------------- | ------------------------------------------------------------------------------------------------------ |
2529
| 🚀 **Lightweight** | Focuses on image generation and Director tools, providing a simple and easy-to-use interface. |
2630
| ⚙️ **Parameterized** | Provides strongly typed interfaces to easily set up generation parameters with validation. |
2731
| 🔑 **Token Authentication** | Supports direct token authentication for API access. |
32+
| 🎬 **Real-time Streaming** | Stream V4/V4.5 generation progress in real-time, watching each denoising step as it happens. |
2833
| 🌐 **Cross-Platform** | Works in both browser and Node.js environments. |
2934
|**Latest Models** | Full support for V3, V4, and V4.5 models including multi-character generation. |
3035
| 🛠️ **Director Tools** | Complete support for all NovelAI Director tools like line art, background removal, and emotion change. |
3136
| 🔄 **TypeScript Support** | Full TypeScript definitions for all API parameters and responses. |
32-
| 🖼️ **Flexible Image Input** | Accepts various image input formats (paths, URLs, Blob, File, ArrayBuffer) for cross-platform use. |
3337
| 🔁 **Automatic Retries** | Built-in retry mechanism for handling rate limits and temporary API failures. |
34-
| 📦 **Modular Structure** | Well-organized, domain-specific modules for better maintainability and code organization. |
3538

3639
## 📦 Installation
3740

@@ -97,7 +100,7 @@ const images = await client.generateImage({
97100
prompt: "1girl, cute, anime style, detailed",
98101
model: Model.V4_5_CUR,
99102
resPreset: Resolution.NORMAL_PORTRAIT,
100-
nSamples: 1,
103+
n_samples: 1,
101104
seed: 1234567890, // Fixed seed for reproducibility
102105
});
103106

examples/custom-host-test.js

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,31 @@
1-
const {
2-
NovelAI,
3-
Model,
4-
Resolution,
5-
Sampler,
6-
createCustomHost,
7-
} = require("nekoai-js");
1+
const { NovelAI, Model, Resolution, Sampler } = require("nekoai-js");
82

93
// Test function for custom host
104
async function testCustomHost() {
115
const client = new NovelAI({
126
token: process.env.NOVELAI_TOKEN,
7+
host: "https://image.novelai.net", // Official API endpoint
8+
// host: "https://your-custom-host.com", // Uncomment to use a custom host
9+
verbose: true,
1310
});
1411

15-
console.log("Testing custom host...");
16-
17-
// Create a custom host (this example uses the official API endpoint, but you can use any compatible server)
18-
const customHost = createCustomHost(
19-
"https://image.novelai.net", // Custom host URL
20-
);
21-
2212
try {
2313
const images = await client.generateImage(
2414
{
2515
prompt: "1girl, blue hair, cute, anime style",
2616
model: Model.V3,
2717
resPreset: Resolution.NORMAL_PORTRAIT,
28-
nSamples: 1,
18+
n_samples: 1,
2919
steps: 28,
3020
scale: 6.0,
3121
sampler: Sampler.EULER,
3222
seed: Math.floor(Math.random() * 4294967288),
3323
ucPreset: 0,
3424
qualityToggle: true,
35-
negativePrompt:
25+
negative_prompt:
3626
"nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit",
3727
},
38-
customHost,
28+
false,
3929
true,
4030
); // Use our custom host
4131

examples/extract-metadata.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async function browserExample() {
4242
const positivePrompt = metadata.entries.find(
4343
(e) => e.keyword === "Positive prompt",
4444
);
45-
const negativePrompt = metadata.entries.find(
45+
const negative_prompt = metadata.entries.find(
4646
(e) => e.keyword === "Negative prompt",
4747
);
4848
const parameters = metadata.entries.find(
@@ -52,7 +52,7 @@ async function browserExample() {
5252
document.getElementById("positive").textContent =
5353
positivePrompt?.text || "";
5454
document.getElementById("negative").textContent =
55-
negativePrompt?.text || "";
55+
negative_prompt?.text || "";
5656
document.getElementById("parameters").textContent = parameters?.text || "";
5757
}
5858

@@ -106,9 +106,9 @@ async function nodeExample() {
106106
);
107107
}
108108

109-
if (summary.negativePrompt) {
109+
if (summary.negative_prompt) {
110110
console.log(
111-
`- Negative prompt: ${summary.negativePrompt.substring(0, 100)}...`,
111+
`- Negative prompt: ${summary.negative_prompt.substring(0, 100)}...`,
112112
);
113113
}
114114

examples/img2img-test.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require("dotenv").config();
66
async function testImg2Img() {
77
const client = new NovelAI({
88
token: process.env.NOVELAI_TOKEN,
9+
verbose: true,
910
});
1011

1112
console.log("Testing img2img generation...");
@@ -36,13 +37,13 @@ async function testImg2Img() {
3637
action: Action.IMG2IMG,
3738
width: dimensions.width,
3839
height: dimensions.height,
39-
nSamples: 1,
40+
n_samples: 1,
4041
steps: 28,
4142
scale: 7.0,
4243
sampler: Sampler.DPM2S_ANC,
43-
dynamicThresholding: false,
44-
cfgRescale: 0,
45-
noiseSchedule: Noise.KARRAS,
44+
dynamic_thresholding: false,
45+
cfg_rescale: 0,
46+
noise_schedule: Noise.KARRAS,
4647
seed: Math.floor(Math.random() * 4294967288),
4748
ucPreset: 0,
4849
qualityToggle: true,
@@ -52,7 +53,7 @@ async function testImg2Img() {
5253
strength: 0.7, // How much to change the image (0.01-0.99)
5354
noise: 0.2, // How much noise to add
5455

55-
negativePrompt:
56+
negative_prompt:
5657
"nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit",
5758
},
5859
undefined,

examples/img2img-v4.5-test.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require("dotenv").config();
66
async function testImg2Img45Full() {
77
const client = new NovelAI({
88
token: process.env.NOVELAI_TOKEN,
9+
verbose: true,
910
});
1011

1112
console.log("Testing img2img V4.5 generation...");
@@ -36,15 +37,15 @@ async function testImg2Img45Full() {
3637
action: Action.IMG2IMG,
3738
width: dimensions.width,
3839
height: dimensions.height,
39-
nSamples: 1,
40+
n_samples: 1,
4041
steps: 28,
4142
scale: 5.5,
4243
sampler: Sampler.DPM2S_ANC,
43-
dynamicThresholding: false,
44-
cfgRescale: 0,
45-
noiseSchedule: Noise.KARRAS,
44+
dynamic_thresholding: false,
45+
cfg_rescale: 0,
46+
noise_schedule: Noise.KARRAS,
4647
seed: Math.floor(Math.random() * 4294967288),
47-
extraNoiseSeed: Math.floor(Math.random() * 4294967288),
48+
extra_noise_seed: Math.floor(Math.random() * 4294967288),
4849
ucPreset: 0,
4950
qualityToggle: true,
5051

@@ -53,7 +54,7 @@ async function testImg2Img45Full() {
5354
strength: 0.7, // How much to change the image (0.01-0.99)
5455
noise: 0.2, // How much noise to add
5556

56-
negativePrompt:
57+
negative_prompt:
5758
"nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit",
5859
},
5960
undefined,

examples/inpaint-test.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require("dotenv").config();
66
async function testInpaint() {
77
const client = new NovelAI({
88
token: process.env.NOVELAI_TOKEN,
9+
verbose: true,
910
});
1011

1112
return; // Disable inpainting test for now
@@ -42,24 +43,24 @@ async function testInpaint() {
4243
action: Action.INPAINT,
4344
width: dimensions.width,
4445
height: dimensions.height,
45-
nSamples: 1,
46+
n_samples: 1,
4647
steps: 28,
4748
scale: 7.0,
4849
sampler: Sampler.EULER,
49-
dynamicThresholding: false,
50-
cfgRescale: 0,
51-
noiseSchedule: Noise.KARRAS,
50+
dynamic_thresholding: false,
51+
cfg_rescale: 0,
52+
noise_schedule: Noise.KARRAS,
5253
seed: Math.floor(Math.random() * 4294967288),
53-
extraNoiseSeed: Math.floor(Math.random() * 4294967288),
54+
extra_noise_seed: Math.floor(Math.random() * 4294967288),
5455
ucPreset: 0,
5556
qualityToggle: true,
5657

5758
// inpaint specific parameters
5859
image: base64Image,
5960
mask: base64Mask,
60-
addOriginalImage: true, // Overlay the original image
61+
add_original_image: true, // Overlay the original image
6162

62-
negativePrompt:
63+
negative_prompt:
6364
"nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit",
6465
},
6566
undefined,

examples/model-v3-test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ require("dotenv").config(); // Load environment variables from .env file
55
async function testModelV3() {
66
const client = new NovelAI({
77
token: process.env.NOVELAI_TOKEN,
8+
verbose: true,
89
});
910

1011
console.log("Testing Model V3 generation...");
@@ -15,13 +16,13 @@ async function testModelV3() {
1516
prompt: "1girl, blue hair, cute, anime style",
1617
model: Model.V3,
1718
resPreset: Resolution.NORMAL_PORTRAIT,
18-
nSamples: 1,
19+
n_samples: 1,
1920
steps: 28,
2021
scale: 6.3,
2122
sampler: Sampler.DPM2S_ANC,
2223
sm: true,
23-
smDyn: true,
24-
negativePrompt:
24+
sm_dyn: true,
25+
negative_prompt:
2526
"nsfw, lowres, {bad}, error, fewer, extra, missing, worst quality, jpeg artifacts, bad quality",
2627
},
2728
undefined,

examples/model-v4-5-full-test.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
1-
const { NovelAI, Model, Resolution, Sampler, Noise } = require("nekoai-js");
1+
const { NovelAI, Model, Resolution, Sampler } = require("nekoai-js");
2+
const Stream = require("stream");
23
require("dotenv").config();
34

45
// Test function for V4 model generation
56
async function testModelV45Full() {
67
const client = new NovelAI({
78
token: process.env.NOVELAI_TOKEN,
9+
verbose: true,
810
});
911

1012
console.log("Testing Model V4.5 generation...");
1113

1214
try {
1315
const images = await client.generateImage(
1416
{
15-
prompt: "1girl, blue hair, cute, anime style",
17+
prompt: "1girl, cute",
18+
negative_prompt: "1234",
1619
model: Model.V4_5,
1720
resPreset: Resolution.NORMAL_PORTRAIT,
18-
nSamples: 1,
19-
steps: 28,
20-
scale: 5.5,
21+
seed: 3417044607,
22+
steps: 30,
23+
scale: 5,
2124
sampler: Sampler.EULER_ANC,
22-
noiseSchedule: Noise.KARRAS,
23-
ucPreset: 0,
25+
ucPreset: 3,
2426
},
25-
undefined,
27+
false,
2628
true,
2729
); // Set verbose to true to see Anlas cost
2830

examples/model-v4-5-multichar-test.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ require("dotenv").config();
55
async function testModelV45MultiChar() {
66
const client = new NovelAI({
77
token: process.env.NOVELAI_TOKEN,
8+
verbose: true,
89
});
910

1011
console.log("Testing Model V4.5 with multiple characters...");
@@ -18,8 +19,8 @@ async function testModelV45MultiChar() {
1819
steps: 28,
1920
scale: 5.5,
2021
sampler: "k_euler_ancestral",
21-
noiseSchedule: "karras",
22-
negativePrompt:
22+
noise_schedule: "karras",
23+
negative_prompt:
2324
"nsfw, lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit",
2425
// Character prompts for multiple characters
2526
characterPrompts: [

0 commit comments

Comments
 (0)