@nodetool-ai/runtime 0.8.4-a24.3 → 0.8.5
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/.nodetool-build-stamp +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/model-load-events.d.ts +38 -0
- package/dist/model-load-events.d.ts.map +1 -0
- package/dist/model-load-events.js +47 -0
- package/dist/model-load-events.js.map +1 -0
- package/dist/providers/anthropic-provider.d.ts.map +1 -1
- package/dist/providers/anthropic-provider.js +9 -2
- package/dist/providers/anthropic-provider.js.map +1 -1
- package/dist/providers/chatgpt-provider.d.ts +16 -4
- package/dist/providers/chatgpt-provider.d.ts.map +1 -1
- package/dist/providers/chatgpt-provider.js +69 -18
- package/dist/providers/chatgpt-provider.js.map +1 -1
- package/dist/providers/cohere-provider.d.ts.map +1 -1
- package/dist/providers/cohere-provider.js +9 -21
- package/dist/providers/cohere-provider.js.map +1 -1
- package/dist/providers/cost-calculator.d.ts.map +1 -1
- package/dist/providers/cost-calculator.js +5 -0
- package/dist/providers/cost-calculator.js.map +1 -1
- package/dist/providers/embedding-http.d.ts +21 -0
- package/dist/providers/embedding-http.d.ts.map +1 -0
- package/dist/providers/embedding-http.js +38 -0
- package/dist/providers/embedding-http.js.map +1 -0
- package/dist/providers/fake-app-greeting.d.ts +6 -0
- package/dist/providers/fake-app-greeting.d.ts.map +1 -0
- package/dist/providers/fake-app-greeting.js +139 -0
- package/dist/providers/fake-app-greeting.js.map +1 -0
- package/dist/providers/fake-provider.d.ts +6 -1
- package/dist/providers/fake-provider.d.ts.map +1 -1
- package/dist/providers/fake-provider.js +43 -14
- package/dist/providers/fake-provider.js.map +1 -1
- package/dist/providers/gemini-web-provider.d.ts +2 -0
- package/dist/providers/gemini-web-provider.d.ts.map +1 -1
- package/dist/providers/gemini-web-provider.js +10 -16
- package/dist/providers/gemini-web-provider.js.map +1 -1
- package/dist/providers/gguf-header.d.ts +10 -0
- package/dist/providers/gguf-header.d.ts.map +1 -0
- package/dist/providers/gguf-header.js +97 -0
- package/dist/providers/gguf-header.js.map +1 -0
- package/dist/providers/hf-hub-file.d.ts +3 -0
- package/dist/providers/hf-hub-file.d.ts.map +1 -0
- package/dist/providers/hf-hub-file.js +42 -0
- package/dist/providers/hf-hub-file.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +13 -6
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/jina-provider.d.ts +0 -5
- package/dist/providers/jina-provider.d.ts.map +1 -1
- package/dist/providers/jina-provider.js +9 -29
- package/dist/providers/jina-provider.js.map +1 -1
- package/dist/providers/mlx-models.d.ts +33 -0
- package/dist/providers/mlx-models.d.ts.map +1 -0
- package/dist/providers/mlx-models.js +64 -0
- package/dist/providers/mlx-models.js.map +1 -0
- package/dist/providers/node-llama-cpp-models.d.ts +28 -0
- package/dist/providers/node-llama-cpp-models.d.ts.map +1 -0
- package/dist/providers/node-llama-cpp-models.js +82 -0
- package/dist/providers/node-llama-cpp-models.js.map +1 -0
- package/dist/providers/node-llama-cpp-provider.d.ts +9 -2
- package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -1
- package/dist/providers/node-llama-cpp-provider.js +62 -13
- package/dist/providers/node-llama-cpp-provider.js.map +1 -1
- package/dist/providers/node-llama-cpp-trending.generated.d.ts +3 -0
- package/dist/providers/node-llama-cpp-trending.generated.d.ts.map +1 -0
- package/dist/providers/node-llama-cpp-trending.generated.js +253 -0
- package/dist/providers/node-llama-cpp-trending.generated.js.map +1 -0
- package/dist/providers/openai-provider.d.ts.map +1 -1
- package/dist/providers/openai-provider.js +8 -11
- package/dist/providers/openai-provider.js.map +1 -1
- package/dist/providers/python-provider.d.ts +2 -0
- package/dist/providers/python-provider.d.ts.map +1 -1
- package/dist/providers/python-provider.js +13 -4
- package/dist/providers/python-provider.js.map +1 -1
- package/dist/providers/sdcpp-models.d.ts +60 -0
- package/dist/providers/sdcpp-models.d.ts.map +1 -0
- package/dist/providers/sdcpp-models.js +435 -0
- package/dist/providers/sdcpp-models.js.map +1 -0
- package/dist/providers/sdcpp-provider.d.ts +40 -0
- package/dist/providers/sdcpp-provider.d.ts.map +1 -0
- package/dist/providers/sdcpp-provider.js +353 -0
- package/dist/providers/sdcpp-provider.js.map +1 -0
- package/dist/providers/sdcpp-server.d.ts +13 -0
- package/dist/providers/sdcpp-server.d.ts.map +1 -0
- package/dist/providers/sdcpp-server.js +150 -0
- package/dist/providers/sdcpp-server.js.map +1 -0
- package/dist/providers/text-tool-calls.d.ts +52 -0
- package/dist/providers/text-tool-calls.d.ts.map +1 -0
- package/dist/providers/text-tool-calls.js +141 -0
- package/dist/providers/text-tool-calls.js.map +1 -0
- package/dist/providers/types.d.ts +11 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/types.js.map +1 -1
- package/dist/providers/voyage-provider.d.ts +0 -5
- package/dist/providers/voyage-provider.d.ts.map +1 -1
- package/dist/providers/voyage-provider.js +9 -29
- package/dist/providers/voyage-provider.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local image generation with stable-diffusion.cpp.
|
|
3
|
+
*
|
|
4
|
+
* The provider starts the `sd-server` binary from the `sd-cpp` runtime
|
|
5
|
+
* package with the files of the model a generation asks for, then talks to
|
|
6
|
+
* it over its `/sdcpp/v1` job API. Model files come from the Hugging Face
|
|
7
|
+
* cache, where the model picker downloads them.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
import { SD_CPP_RELEASE_TAG, importNodeBuiltin, runtimeLocations, sdCppInstallStatus, sdServerPath } from "@nodetool-ai/config";
|
|
11
|
+
import { missingRuntimePackageError } from "@nodetool-ai/protocol";
|
|
12
|
+
import { BaseProvider } from "./base-provider.js";
|
|
13
|
+
import { SD_CPP_COMPONENT_FLAGS, SD_CPP_MODELS, sdCppModel, sdCppModelRepos, sdCppModelTasks } from "./sdcpp-models.js";
|
|
14
|
+
import { withSdServer } from "./sdcpp-server.js";
|
|
15
|
+
import { resolveHubFile } from "./hf-hub-file.js";
|
|
16
|
+
export const SD_CPP_PROVIDER_ID = "stable_diffusion_cpp";
|
|
17
|
+
const imageResult = z.object({
|
|
18
|
+
output_format: z.string(),
|
|
19
|
+
images: z.array(z.object({ b64_json: z.string().min(1) })).min(1)
|
|
20
|
+
});
|
|
21
|
+
const jobSchema = z.object({
|
|
22
|
+
status: z.enum(["queued", "generating", "completed", "failed", "cancelled"]),
|
|
23
|
+
result: imageResult.nullish(),
|
|
24
|
+
error: z.object({ message: z.string() }).nullish()
|
|
25
|
+
});
|
|
26
|
+
const INSTALL_HINT = "Install stable-diffusion.cpp in Settings › Packages, or run `nodetool runtime add sd-cpp`.";
|
|
27
|
+
export class StableDiffusionCppProvider extends BaseProvider {
|
|
28
|
+
static requiredSecrets() {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
serverPath;
|
|
32
|
+
constructor(secrets = {}) {
|
|
33
|
+
super(SD_CPP_PROVIDER_ID);
|
|
34
|
+
this.serverPath =
|
|
35
|
+
secrets.SD_CPP_SERVER_PATH?.trim() ||
|
|
36
|
+
process.env.SD_CPP_SERVER_PATH?.trim() ||
|
|
37
|
+
undefined;
|
|
38
|
+
}
|
|
39
|
+
declaredCapabilities() {
|
|
40
|
+
return ["text_to_image", "image_to_image"];
|
|
41
|
+
}
|
|
42
|
+
async generateMessage(_args) {
|
|
43
|
+
throw new Error("stable-diffusion.cpp does not support chat generation");
|
|
44
|
+
}
|
|
45
|
+
// eslint-disable-next-line require-yield
|
|
46
|
+
async *generateMessages(_args) {
|
|
47
|
+
throw new Error("stable-diffusion.cpp does not support chat generation");
|
|
48
|
+
}
|
|
49
|
+
async getAvailableImageModels() {
|
|
50
|
+
const binary = await this.findServer();
|
|
51
|
+
return Promise.all(SD_CPP_MODELS.map(async (model) => ({
|
|
52
|
+
id: model.id,
|
|
53
|
+
name: `${model.name} (${model.sizeGb} GB)`,
|
|
54
|
+
provider: SD_CPP_PROVIDER_ID,
|
|
55
|
+
supportedTasks: sdCppModelTasks(model),
|
|
56
|
+
adapter: adapterFor(model, binary !== null, (await missingFiles(model)).length === 0)
|
|
57
|
+
})));
|
|
58
|
+
}
|
|
59
|
+
async textToImage(params) {
|
|
60
|
+
const model = this.spec(params.model.id);
|
|
61
|
+
if (model.textToImage === false) {
|
|
62
|
+
throw new Error(`${model.name} edits a source image. Use it for image-to-image.`);
|
|
63
|
+
}
|
|
64
|
+
const size = outputSize(model, params.width, params.height, params.aspectRatio);
|
|
65
|
+
return this.generate(model, params.signal, {
|
|
66
|
+
prompt: params.prompt,
|
|
67
|
+
negative_prompt: params.negativePrompt ?? "",
|
|
68
|
+
width: size.width,
|
|
69
|
+
height: size.height,
|
|
70
|
+
seed: params.seed ?? -1,
|
|
71
|
+
sample_params: sampleParams(model, params)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async imageToImage(images, params) {
|
|
75
|
+
const source = images[0];
|
|
76
|
+
if (!source?.length) {
|
|
77
|
+
throw new Error("stable-diffusion.cpp image-to-image needs a source image");
|
|
78
|
+
}
|
|
79
|
+
const model = this.spec(params.model.id);
|
|
80
|
+
if (!model.imageInput) {
|
|
81
|
+
throw new Error(`${model.name} generates from text only. Use it for text-to-image.`);
|
|
82
|
+
}
|
|
83
|
+
const explicit = Boolean(params.targetWidth && params.targetHeight);
|
|
84
|
+
const sourceSize = explicit ? null : scaledSource(model, imageDimensions(source));
|
|
85
|
+
const size = outputSize(model, params.targetWidth ?? sourceSize?.width, params.targetHeight ?? sourceSize?.height, params.aspectRatio, !explicit && !model.sourceScale);
|
|
86
|
+
const encoded = Buffer.from(source).toString("base64");
|
|
87
|
+
// An edit model reads the source as a reference. Other models denoise
|
|
88
|
+
// from it, by `strength`.
|
|
89
|
+
const imageFields = model.imageInput === "reference"
|
|
90
|
+
? { ref_images: [encoded] }
|
|
91
|
+
: { init_image: encoded, strength: params.strength ?? 0.75 };
|
|
92
|
+
return this.generate(model, params.signal, {
|
|
93
|
+
prompt: params.prompt,
|
|
94
|
+
negative_prompt: params.negativePrompt ?? "",
|
|
95
|
+
width: size.width,
|
|
96
|
+
height: size.height,
|
|
97
|
+
seed: params.seed ?? -1,
|
|
98
|
+
...imageFields,
|
|
99
|
+
sample_params: sampleParams(model, params)
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
spec(id) {
|
|
103
|
+
const model = sdCppModel(id);
|
|
104
|
+
if (!model) {
|
|
105
|
+
throw new Error(`Unknown stable-diffusion.cpp model "${id}". Known: ${SD_CPP_MODELS.map((m) => m.id).join(", ")}.`);
|
|
106
|
+
}
|
|
107
|
+
return model;
|
|
108
|
+
}
|
|
109
|
+
async generate(model, signal, body) {
|
|
110
|
+
const binary = await this.findServer();
|
|
111
|
+
if (!binary) {
|
|
112
|
+
throw missingRuntimePackageError("sd-server", "sd-cpp");
|
|
113
|
+
}
|
|
114
|
+
const args = await modelArgs(model);
|
|
115
|
+
try {
|
|
116
|
+
return await withSdServer({ binary, args }, signal, async (baseUrl) => {
|
|
117
|
+
const result = await runJob(baseUrl, { ...body, batch_count: 1, output_format: "png" }, signal);
|
|
118
|
+
return new Uint8Array(Buffer.from(result.images[0].b64_json, "base64"));
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
throw await withUpdateHint(binary, error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The `sd-server` to run: the configured path, the desktop or CLI install,
|
|
127
|
+
* then PATH. Null when none exists.
|
|
128
|
+
*/
|
|
129
|
+
async findServer() {
|
|
130
|
+
const fs = await importNodeBuiltin("node:fs/promises");
|
|
131
|
+
const path = await importNodeBuiltin("node:path");
|
|
132
|
+
if (!fs || !path) {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const platform = process.platform;
|
|
136
|
+
const candidates = [];
|
|
137
|
+
if (this.serverPath) {
|
|
138
|
+
candidates.push(this.serverPath);
|
|
139
|
+
}
|
|
140
|
+
const installs = [runtimeLocations().sdCpp];
|
|
141
|
+
try {
|
|
142
|
+
installs.push(runtimeLocations({ ...process.env, NODETOOL_HOST: "cli" }).sdCpp);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Only the configured locations apply.
|
|
146
|
+
}
|
|
147
|
+
for (const dir of installs) {
|
|
148
|
+
if (dir) {
|
|
149
|
+
candidates.push(sdServerPath(dir, platform));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const exe = platform === "win32" ? "sd-server.exe" : "sd-server";
|
|
153
|
+
for (const dir of (process.env.PATH ?? "").split(path.delimiter)) {
|
|
154
|
+
if (dir) {
|
|
155
|
+
candidates.push(path.join(dir, exe));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const candidate of candidates) {
|
|
159
|
+
try {
|
|
160
|
+
await fs.access(candidate, fs.constants.X_OK);
|
|
161
|
+
return candidate;
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// Try the next location.
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Prefix a failure with an update hint when the sd-server install is older
|
|
172
|
+
* than the pinned release: an old server cannot read newer model formats and
|
|
173
|
+
* reports only that it failed to load the file.
|
|
174
|
+
*/
|
|
175
|
+
async function withUpdateHint(binary, error) {
|
|
176
|
+
if (!(error instanceof Error) || error.name === "AbortError") {
|
|
177
|
+
return error;
|
|
178
|
+
}
|
|
179
|
+
const path = await importNodeBuiltin("node:path");
|
|
180
|
+
if (!path) {
|
|
181
|
+
return error;
|
|
182
|
+
}
|
|
183
|
+
const { version } = await sdCppInstallStatus(path.dirname(binary), process.platform);
|
|
184
|
+
if (!version || version === SD_CPP_RELEASE_TAG) {
|
|
185
|
+
return error;
|
|
186
|
+
}
|
|
187
|
+
return new Error(`The installed sd-server is ${version}, and NodeTool needs ${SD_CPP_RELEASE_TAG}. ` +
|
|
188
|
+
"Update stable-diffusion.cpp in Settings › Packages, or run `nodetool runtime add sd-cpp`.\n\n" +
|
|
189
|
+
error.message, { cause: error });
|
|
190
|
+
}
|
|
191
|
+
function adapterFor(model, serverInstalled, filesPresent) {
|
|
192
|
+
const [main, ...extra] = sdCppModelRepos(model).map((repo) => ({
|
|
193
|
+
source: "huggingface",
|
|
194
|
+
repoId: repo.repoId,
|
|
195
|
+
allowPatterns: repo.paths
|
|
196
|
+
}));
|
|
197
|
+
const artifacts = { artifactRef: main, extraArtifactRefs: extra, filesPresent };
|
|
198
|
+
if (!serverInstalled) {
|
|
199
|
+
return {
|
|
200
|
+
state: "missing_dependency",
|
|
201
|
+
reasonCode: "runtime_package_missing",
|
|
202
|
+
reason: `sd-server is not installed. ${INSTALL_HINT}`,
|
|
203
|
+
...artifacts
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return { state: "installed", ...artifacts };
|
|
207
|
+
}
|
|
208
|
+
/** The model files missing from the Hugging Face cache. */
|
|
209
|
+
async function missingFiles(model) {
|
|
210
|
+
const files = Object.values(model.files).filter((file) => Boolean(file));
|
|
211
|
+
const present = await Promise.all(files.map((file) => resolveHubFile(file.repoId, file.path)));
|
|
212
|
+
return files.filter((_, index) => !present[index]);
|
|
213
|
+
}
|
|
214
|
+
/** The sd-server flags that load each file of a model from the HF cache. */
|
|
215
|
+
async function modelArgs(model) {
|
|
216
|
+
const args = [];
|
|
217
|
+
const missing = [];
|
|
218
|
+
for (const [component, file] of Object.entries(model.files)) {
|
|
219
|
+
const resolved = await resolveHubFile(file.repoId, file.path);
|
|
220
|
+
if (!resolved) {
|
|
221
|
+
missing.push(`${file.repoId}/${file.path}`);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
args.push(SD_CPP_COMPONENT_FLAGS[component], resolved);
|
|
225
|
+
}
|
|
226
|
+
if (missing.length > 0) {
|
|
227
|
+
throw new Error(`${model.name} is not fully downloaded. Missing: ${missing.join(", ")}. Download the model from the model picker.`);
|
|
228
|
+
}
|
|
229
|
+
// The default attention needs memory in the square of the pixel count: a
|
|
230
|
+
// 1792x1024 SD-Turbo image asks Metal for 15.7 GB and fails. Flash
|
|
231
|
+
// attention and a tiled VAE keep large sizes within reach.
|
|
232
|
+
return [...args, ...(model.serverArgs ?? []), "--flash-attn", "on", "--vae-tiling"];
|
|
233
|
+
}
|
|
234
|
+
/** The source size an upscaler turns a source image into. */
|
|
235
|
+
function scaledSource(model, size) {
|
|
236
|
+
if (!size || !model.sourceScale) {
|
|
237
|
+
return size;
|
|
238
|
+
}
|
|
239
|
+
const { scale, maxSide } = model.sourceScale;
|
|
240
|
+
const factor = Math.min(scale, maxSide / Math.max(size.width, size.height));
|
|
241
|
+
return { width: size.width * factor, height: size.height * factor };
|
|
242
|
+
}
|
|
243
|
+
function sampleParams(model, params) {
|
|
244
|
+
const sample = {
|
|
245
|
+
sample_steps: params.numInferenceSteps ?? model.defaults.steps,
|
|
246
|
+
guidance: { txt_cfg: params.guidanceScale ?? model.defaults.cfgScale }
|
|
247
|
+
};
|
|
248
|
+
if (model.defaults.sampler) {
|
|
249
|
+
sample.sample_method = model.defaults.sampler;
|
|
250
|
+
}
|
|
251
|
+
if (model.defaults.flowShift !== undefined) {
|
|
252
|
+
sample.flow_shift = model.defaults.flowShift;
|
|
253
|
+
}
|
|
254
|
+
if (params.scheduler) {
|
|
255
|
+
sample.scheduler = params.scheduler;
|
|
256
|
+
}
|
|
257
|
+
return sample;
|
|
258
|
+
}
|
|
259
|
+
/** Round to the 64-pixel grid the diffusion models expect. */
|
|
260
|
+
function grid(value) {
|
|
261
|
+
return Math.max(64, Math.round(value / 64) * 64);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* The output size: the requested width and height, else the aspect ratio at
|
|
265
|
+
* the model's trained area, else a square at the trained size. With `fit`
|
|
266
|
+
* (a size read from a source image), a size above 1.5 times the trained area
|
|
267
|
+
* scales down to it, keeping the aspect ratio.
|
|
268
|
+
*/
|
|
269
|
+
export function outputSize(model, width, height, aspectRatio, fit = false) {
|
|
270
|
+
const area = model.defaults.size * model.defaults.size;
|
|
271
|
+
let w = width && width > 0 ? width : 0;
|
|
272
|
+
let h = height && height > 0 ? height : 0;
|
|
273
|
+
if (!w || !h) {
|
|
274
|
+
const ratio = parseAspectRatio(aspectRatio) ?? 1;
|
|
275
|
+
w = Math.sqrt(area * ratio);
|
|
276
|
+
h = w / ratio;
|
|
277
|
+
}
|
|
278
|
+
const scale = fit ? Math.min(1, Math.sqrt((area * 1.5) / (w * h))) : 1;
|
|
279
|
+
return { width: grid(w * scale), height: grid(h * scale) };
|
|
280
|
+
}
|
|
281
|
+
function parseAspectRatio(value) {
|
|
282
|
+
const match = value?.match(/^(\d+(?:\.\d+)?)\s*[:x/]\s*(\d+(?:\.\d+)?)$/);
|
|
283
|
+
if (!match) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const ratio = Number(match[1]) / Number(match[2]);
|
|
287
|
+
return Number.isFinite(ratio) && ratio > 0 ? ratio : null;
|
|
288
|
+
}
|
|
289
|
+
/** Width and height from a PNG or JPEG header, or null for other formats. */
|
|
290
|
+
export function imageDimensions(bytes) {
|
|
291
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
292
|
+
if (bytes.length >= 24 && bytes[0] === 0x89 && bytes[1] === 0x50) {
|
|
293
|
+
return { width: view.getUint32(16), height: view.getUint32(20) };
|
|
294
|
+
}
|
|
295
|
+
if (bytes.length >= 4 && bytes[0] === 0xff && bytes[1] === 0xd8) {
|
|
296
|
+
let offset = 2;
|
|
297
|
+
while (offset + 9 < bytes.length) {
|
|
298
|
+
if (bytes[offset] !== 0xff) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const marker = bytes[offset + 1];
|
|
302
|
+
const length = view.getUint16(offset + 2);
|
|
303
|
+
if (marker >= 0xc0 && marker <= 0xcf && marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc) {
|
|
304
|
+
return { height: view.getUint16(offset + 5), width: view.getUint16(offset + 7) };
|
|
305
|
+
}
|
|
306
|
+
offset += 2 + length;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
async function requestJson(url, schema, signal, body) {
|
|
312
|
+
const response = await fetch(url, {
|
|
313
|
+
method: body ? "POST" : "GET",
|
|
314
|
+
headers: body ? { "Content-Type": "application/json" } : undefined,
|
|
315
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
316
|
+
redirect: "error",
|
|
317
|
+
signal
|
|
318
|
+
});
|
|
319
|
+
if (!response.ok) {
|
|
320
|
+
throw new Error(`stable-diffusion.cpp HTTP ${response.status}: ${(await response.text()).slice(0, 1000)}`);
|
|
321
|
+
}
|
|
322
|
+
return schema.parse(await response.json());
|
|
323
|
+
}
|
|
324
|
+
/** Submit one img_gen job and poll it to completion, cancelling on abort. */
|
|
325
|
+
async function runJob(baseUrl, body, signal) {
|
|
326
|
+
const { id } = await requestJson(`${baseUrl}/sdcpp/v1/img_gen`, z.object({ id: z.string().min(1) }), signal, body);
|
|
327
|
+
const jobUrl = `${baseUrl}/sdcpp/v1/jobs/${encodeURIComponent(id)}`;
|
|
328
|
+
try {
|
|
329
|
+
for (;;) {
|
|
330
|
+
const job = await requestJson(jobUrl, jobSchema, signal);
|
|
331
|
+
if (job.status === "completed") {
|
|
332
|
+
return imageResult.parse(job.result);
|
|
333
|
+
}
|
|
334
|
+
if (job.status === "failed" || job.status === "cancelled") {
|
|
335
|
+
throw new Error(job.error?.message ?? `stable-diffusion.cpp job ${job.status}`);
|
|
336
|
+
}
|
|
337
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
338
|
+
signal?.throwIfAborted();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
if (signal?.aborted) {
|
|
343
|
+
await fetch(`${jobUrl}/cancel`, {
|
|
344
|
+
method: "POST",
|
|
345
|
+
headers: { "Content-Type": "application/json" },
|
|
346
|
+
body: "{}",
|
|
347
|
+
signal: AbortSignal.timeout(5000)
|
|
348
|
+
}).catch(() => undefined);
|
|
349
|
+
}
|
|
350
|
+
throw error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=sdcpp-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdcpp-provider.js","sourceRoot":"","sources":["../../src/providers/sdcpp-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SdServerLaunch {
|
|
2
|
+
binary: string;
|
|
3
|
+
/** Model flags and paths, e.g. `["--model", "/path/x.gguf"]`. */
|
|
4
|
+
args: string[];
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Run `work` against a server that has `launch` loaded. Calls are serialized,
|
|
8
|
+
* so one generation finishes before another can swap the model.
|
|
9
|
+
*/
|
|
10
|
+
export declare function withSdServer<T>(launch: SdServerLaunch, signal: AbortSignal | undefined, work: (baseUrl: string) => Promise<T>): Promise<T>;
|
|
11
|
+
/** Stop the running server, if any. */
|
|
12
|
+
export declare function stopSdServer(): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=sdcpp-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdcpp-server.d.ts","sourceRoot":"","sources":["../../src/providers/sdcpp-server.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,uCAAuC;AACvC,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAQlD"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one `sd-server` process the stable-diffusion.cpp provider runs.
|
|
3
|
+
*
|
|
4
|
+
* `sd-server` loads one model at start and keeps it in memory. The provider
|
|
5
|
+
* asks for a model per generation: the same model reuses the running server,
|
|
6
|
+
* another model restarts it. Generations run one at a time, so a restart
|
|
7
|
+
* never cuts off a job in flight. An idle server exits after a while to free
|
|
8
|
+
* the model's memory.
|
|
9
|
+
*/
|
|
10
|
+
import { createLogger, importNodeBuiltin } from "@nodetool-ai/config";
|
|
11
|
+
const log = createLogger("nodetool.runtime.providers.sdcpp");
|
|
12
|
+
/** A first load of a large model from a cold disk can take minutes. */
|
|
13
|
+
const READY_TIMEOUT_MS = 15 * 60 * 1000;
|
|
14
|
+
const IDLE_SHUTDOWN_MS = 10 * 60 * 1000;
|
|
15
|
+
let running = null;
|
|
16
|
+
let queue = Promise.resolve();
|
|
17
|
+
let idleTimer = null;
|
|
18
|
+
let exitHookInstalled = false;
|
|
19
|
+
/**
|
|
20
|
+
* Run `work` against a server that has `launch` loaded. Calls are serialized,
|
|
21
|
+
* so one generation finishes before another can swap the model.
|
|
22
|
+
*/
|
|
23
|
+
export function withSdServer(launch, signal, work) {
|
|
24
|
+
const next = queue.then(async () => {
|
|
25
|
+
signal?.throwIfAborted();
|
|
26
|
+
if (idleTimer) {
|
|
27
|
+
clearTimeout(idleTimer);
|
|
28
|
+
idleTimer = null;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const server = await ensureServer(launch, signal);
|
|
32
|
+
return await work(server.baseUrl);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
idleTimer = setTimeout(() => void stopSdServer(), IDLE_SHUTDOWN_MS);
|
|
36
|
+
idleTimer.unref?.();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
queue = next.catch(() => undefined);
|
|
40
|
+
return next;
|
|
41
|
+
}
|
|
42
|
+
/** Stop the running server, if any. */
|
|
43
|
+
export async function stopSdServer() {
|
|
44
|
+
const server = running;
|
|
45
|
+
running = null;
|
|
46
|
+
if (!server) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
server.child.kill();
|
|
50
|
+
await server.exited;
|
|
51
|
+
}
|
|
52
|
+
async function ensureServer(launch, signal) {
|
|
53
|
+
const key = JSON.stringify([launch.binary, ...launch.args]);
|
|
54
|
+
if (running?.key === key && running.child.exitCode === null) {
|
|
55
|
+
return running;
|
|
56
|
+
}
|
|
57
|
+
await stopSdServer();
|
|
58
|
+
const childProcess = await importNodeBuiltin("node:child_process");
|
|
59
|
+
if (!childProcess) {
|
|
60
|
+
throw new Error("stable-diffusion.cpp needs Node.js to start sd-server");
|
|
61
|
+
}
|
|
62
|
+
const port = await freePort();
|
|
63
|
+
const baseUrl = `http://127.0.0.1:${port}`;
|
|
64
|
+
const args = [...launch.args, "--listen-ip", "127.0.0.1", "--listen-port", String(port)];
|
|
65
|
+
log.info("Starting sd-server", { binary: launch.binary, args });
|
|
66
|
+
const child = childProcess.spawn(launch.binary, args, {
|
|
67
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
68
|
+
windowsHide: true
|
|
69
|
+
});
|
|
70
|
+
const tail = [];
|
|
71
|
+
const collect = (chunk) => {
|
|
72
|
+
for (const line of chunk.toString("utf8").split(/\r?\n/)) {
|
|
73
|
+
if (line.trim()) {
|
|
74
|
+
tail.push(line);
|
|
75
|
+
if (tail.length > 30) {
|
|
76
|
+
tail.shift();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
child.stdout?.on("data", collect);
|
|
82
|
+
child.stderr?.on("data", collect);
|
|
83
|
+
const exited = new Promise((resolve) => {
|
|
84
|
+
child.once("exit", () => resolve());
|
|
85
|
+
child.once("error", () => resolve());
|
|
86
|
+
});
|
|
87
|
+
let spawnError = null;
|
|
88
|
+
child.once("error", (error) => {
|
|
89
|
+
spawnError = error;
|
|
90
|
+
});
|
|
91
|
+
installExitHook();
|
|
92
|
+
const server = { key, baseUrl, child, exited };
|
|
93
|
+
running = server;
|
|
94
|
+
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
95
|
+
while (Date.now() < deadline) {
|
|
96
|
+
signal?.throwIfAborted();
|
|
97
|
+
if (spawnError || child.exitCode !== null || child.signalCode !== null) {
|
|
98
|
+
running = null;
|
|
99
|
+
const reason = spawnError ? spawnError.message : `exit code ${child.exitCode ?? child.signalCode}`;
|
|
100
|
+
throw new Error(`sd-server stopped before it was ready (${reason}):\n${tail.join("\n")}`);
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const response = await fetch(`${baseUrl}/sdcpp/v1/capabilities`, {
|
|
104
|
+
signal: AbortSignal.timeout(2000)
|
|
105
|
+
});
|
|
106
|
+
if (response.ok) {
|
|
107
|
+
log.info("sd-server is ready", { baseUrl });
|
|
108
|
+
return server;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
// Not listening yet: the model is still loading.
|
|
113
|
+
}
|
|
114
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
115
|
+
}
|
|
116
|
+
await stopSdServer();
|
|
117
|
+
throw new Error(`sd-server did not become ready in ${READY_TIMEOUT_MS / 60000} minutes:\n${tail.join("\n")}`);
|
|
118
|
+
}
|
|
119
|
+
async function freePort() {
|
|
120
|
+
const net = await importNodeBuiltin("node:net");
|
|
121
|
+
if (!net) {
|
|
122
|
+
throw new Error("stable-diffusion.cpp needs Node.js to pick a port");
|
|
123
|
+
}
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const probe = net.createServer();
|
|
126
|
+
probe.once("error", reject);
|
|
127
|
+
probe.listen(0, "127.0.0.1", () => {
|
|
128
|
+
const address = probe.address();
|
|
129
|
+
probe.close(() => {
|
|
130
|
+
if (address && typeof address === "object") {
|
|
131
|
+
resolve(address.port);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
reject(new Error("Could not pick a port for sd-server"));
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** Kill the child when the server process exits, so no sd-server outlives it. */
|
|
141
|
+
function installExitHook() {
|
|
142
|
+
if (exitHookInstalled || typeof process === "undefined") {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
exitHookInstalled = true;
|
|
146
|
+
process.once("exit", () => {
|
|
147
|
+
running?.child.kill();
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=sdcpp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdcpp-server.js","sourceRoot":"","sources":["../../src/providers/sdcpp-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool calling for chat models that have no tool-call API and write their
|
|
3
|
+
* calls as text: local Transformers.js models and the ChatGPT and Gemini web
|
|
4
|
+
* chats. The prompt lists the tools and asks for `<tool_call>` blocks of JSON
|
|
5
|
+
* in the Hermes format, which small models such as SmolLM2 were trained on.
|
|
6
|
+
* {@link parseToolCalls} reads the calls back out of the reply.
|
|
7
|
+
*/
|
|
8
|
+
import type { ProviderTool, ToolCall } from "./types.js";
|
|
9
|
+
/** A tool in the OpenAI function format that chat templates expect. */
|
|
10
|
+
export interface ToolSpec {
|
|
11
|
+
type: "function";
|
|
12
|
+
function: {
|
|
13
|
+
name: string;
|
|
14
|
+
description: string;
|
|
15
|
+
parameters: NonNullable<ProviderTool["inputSchema"]>;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function toToolSpecs(tools: ProviderTool[]): ToolSpec[];
|
|
19
|
+
/** Earlier calls, written back as the block the tools prompt asks for. */
|
|
20
|
+
export declare function toolCallText(calls: ToolCall[]): string;
|
|
21
|
+
/** The instructions that list the tools and the call format. */
|
|
22
|
+
export declare function toolsPromptSection(tools: ToolSpec[]): string;
|
|
23
|
+
export interface ParsedOutput {
|
|
24
|
+
/** The text with every parsed `<tool_call>` block removed. */
|
|
25
|
+
content: string;
|
|
26
|
+
toolCalls: ToolCall[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Split model output into text and tool calls. A block whose body is not valid
|
|
30
|
+
* JSON calls stays in the text, so a malformed call is visible, not lost. An
|
|
31
|
+
* unclosed block at the end counts: generation often stops on the end token
|
|
32
|
+
* before the closing tag. A web chat may put the block in a code fence, which
|
|
33
|
+
* is removed with it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseToolCalls(output: string): ParsedOutput;
|
|
36
|
+
/**
|
|
37
|
+
* Pass streamed text through until a `<tool_call>` starts, so the call JSON
|
|
38
|
+
* never reaches the chat as text. Text that could be the start of the tag is
|
|
39
|
+
* held until the next token decides it.
|
|
40
|
+
*/
|
|
41
|
+
export declare class ToolCallTextFilter {
|
|
42
|
+
private raw;
|
|
43
|
+
private pending;
|
|
44
|
+
private inCall;
|
|
45
|
+
/** Add a token and return the text that is safe to show. */
|
|
46
|
+
push(text: string): string;
|
|
47
|
+
/** The held text once the stream has ended. */
|
|
48
|
+
flush(): string;
|
|
49
|
+
/** Everything the model wrote. */
|
|
50
|
+
get output(): string;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=text-tool-calls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-tool-calls.d.ts","sourceRoot":"","sources":["../../src/providers/text-tool-calls.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAIzD,uEAAuE;AACvE,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,WAAW,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC;KACtD,CAAC;CACH;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,CAS7D;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAGtD;AAED,gEAAgE;AAChE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,CAa5D;AAwCD,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAe3D;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,GAAG,CAAM;IACjB,OAAO,CAAC,OAAO,CAAM;IACrB,OAAO,CAAC,MAAM,CAAS;IAEvB,4DAA4D;IAC5D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuBzB;IAED,+CAA+C;IAC/C,KAAK,IAAI,MAAM,CAId;IAED,kCAAkC;IAClC,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
|