@bendyline/gezel-inference 1.0.5 → 1.0.7
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/cache/controller.d.ts +2 -0
- package/dist/cache/controller.js +38 -5
- package/dist/catalog/chat-models/index.json +1 -1
- package/dist/catalog/chat-models/lf/lfm3-1.7b-q4/manifest.json +114 -0
- package/dist/catalog/chat-models/lf/lfm3-1.7b-q4/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/chat-models/raw-index.json +1 -1
- package/dist/catalog/image-loras/index.json +1 -0
- package/dist/catalog/image-loras/kr/krea-2-ink-wash/manifest.json +31 -0
- package/dist/catalog/image-loras/kr/krea-2-ink-wash/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/kr/krea-2-isometric-3d/manifest.json +32 -0
- package/dist/catalog/image-loras/kr/krea-2-isometric-3d/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/kr/krea-2-kids-drawing/manifest.json +31 -0
- package/dist/catalog/image-loras/kr/krea-2-kids-drawing/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/kr/krea-2-pixel-art/manifest.json +31 -0
- package/dist/catalog/image-loras/kr/krea-2-pixel-art/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/kr/krea-2-soft-watercolor/manifest.json +31 -0
- package/dist/catalog/image-loras/kr/krea-2-soft-watercolor/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/kr/krea-2-turbo-4step/manifest.json +31 -0
- package/dist/catalog/image-loras/kr/krea-2-turbo-4step/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/mo/moss-image-gouache/manifest.json +29 -0
- package/dist/catalog/image-loras/mo/moss-image-gouache/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/mo/moss-image-sft-4step/manifest.json +30 -0
- package/dist/catalog/image-loras/mo/moss-image-sft-4step/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/qw/qwen-image-edit-2511-lightning/manifest.json +31 -0
- package/dist/catalog/image-loras/qw/qwen-image-edit-2511-lightning/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/raw-index.json +1 -0
- package/dist/catalog/image-loras/sd/sdxl-3d-render/manifest.json +29 -0
- package/dist/catalog/image-loras/sd/sdxl-3d-render/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/sd/sdxl-coloring-book/manifest.json +30 -0
- package/dist/catalog/image-loras/sd/sdxl-coloring-book/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/sd/sdxl-papercut/manifest.json +29 -0
- package/dist/catalog/image-loras/sd/sdxl-papercut/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-loras/sd/sdxl-pixel-art/manifest.json +29 -0
- package/dist/catalog/image-loras/sd/sdxl-pixel-art/versions/1.0.0/manifest.json +15 -0
- package/dist/catalog/image-models/fl/flux-2-klein-4b-q4/manifest.json +3 -0
- package/dist/catalog/image-models/index.json +1 -1
- package/dist/catalog/image-models/qw/qwen-image-edit-2511-q4/manifest.json +44 -0
- package/dist/catalog/image-models/qw/qwen-image-edit-2511-q4/versions/1.0.0/manifest.json +36 -0
- package/dist/catalog/image-models/raw-index.json +1 -1
- package/dist/catalog/knowledge-catalogs/index.json +1 -1
- package/dist/catalog/knowledge-catalogs/raw-index.json +1 -1
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-arts/versions/2026.10.2/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-astronomy/versions/2026.10.2/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-biology/versions/2026.10.2/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-business/versions/2026.10.2/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-film-tv/versions/2026.10.2/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-food-drink/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-games/versions/2026.10.2/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-general/manifest.json +55 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-general/versions/2026.10.2/manifest.json +165 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-geography/versions/2026.10.2/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-history/versions/2026.10.2/manifest.json +217 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-language/versions/2026.10.2/manifest.json +181 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-law/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-literature/versions/2026.10.2/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-mathematics/versions/2026.10.2/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-medicine/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-military/versions/2026.10.2/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-music/versions/2026.10.2/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-arts/versions/2026.10.2/manifest.json +209 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-business/versions/2026.10.2/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-entertainment/versions/2026.10.2/manifest.json +201 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-military/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-other/versions/2026.10.2/manifest.json +165 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-politics/versions/2026.10.2/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-religion/versions/2026.10.2/manifest.json +201 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-science/versions/2026.10.2/manifest.json +205 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-people-sports/versions/2026.10.2/manifest.json +237 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-politics/versions/2026.10.2/manifest.json +197 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-religion-philosophy/versions/2026.10.2/manifest.json +189 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-science/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-sports/versions/2026.10.2/manifest.json +193 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-technology/versions/2026.10.2/manifest.json +185 -0
- package/dist/catalog/knowledge-catalogs/wi/wikipedia-transportation/versions/2026.10.2/manifest.json +189 -0
- package/dist/catalog/provenance.json +2 -1
- package/dist/engine-components.js +2 -2
- package/dist/engines/electron-native-reuse.d.ts +7 -1
- package/dist/engines/electron-native-reuse.js +12 -4
- package/dist/engines/native-file-manifest.json +546 -406
- package/dist/engines/native-manifest.d.ts +4 -4
- package/dist/engines/native-manifest.js +36 -36
- package/dist/engines/resolver.d.ts +1 -1
- package/dist/engines/resolver.js +48 -51
- package/dist/http/auth-context.d.ts +12 -0
- package/dist/http/routes/image-ensure-routes.d.ts +4 -0
- package/dist/http/routes/image-ensure-routes.js +102 -0
- package/dist/http/routes/v1-image-styles.d.ts +5 -0
- package/dist/http/routes/v1-image-styles.js +91 -0
- package/dist/http/routes/v1-images.d.ts +1 -0
- package/dist/http/routes/v1-images.js +15 -93
- package/dist/inference-service.js +2 -1
- package/dist/knowledge/worker-host.js +2 -0
- package/dist/machine-engine/inspect-runtime.js +12 -3
- package/dist/memory/embed-core.js +3 -0
- package/dist/memory/embeddings.js +2 -0
- package/dist/models/image-fit.js +2 -2
- package/dist/models/weight-facts.d.ts +5 -0
- package/dist/models/weight-facts.js +5 -2
- package/dist/providers/ds4/build-provider.js +1 -1
- package/dist/providers/ds4/residency.js +3 -3
- package/dist/providers/image/img2img-support.d.ts +36 -1
- package/dist/providers/image/img2img-support.js +30 -1
- package/dist/providers/image/local-engine.d.ts +1 -0
- package/dist/providers/image/local-engine.js +8 -2
- package/dist/providers/image/local-factory.d.ts +10 -1
- package/dist/providers/image/local-factory.js +33 -6
- package/dist/providers/image/mock.d.ts +8 -1
- package/dist/providers/image/mock.js +46 -1
- package/dist/providers/image/pull-registry.d.ts +25 -3
- package/dist/providers/image/pull-registry.js +96 -34
- package/dist/providers/image/sd-cpp.d.ts +63 -4
- package/dist/providers/image/sd-cpp.js +361 -38
- package/dist/providers/image/types.d.ts +76 -4
- package/dist/providers/image/types.js +8 -0
- package/dist/providers/llama-cpp/build-provider.js +3 -2
- package/dist/providers/llama-cpp/cache-adapter.d.ts +3 -0
- package/dist/providers/llama-cpp/cache-adapter.js +18 -4
- package/dist/providers/llama-cpp/devices.js +2 -2
- package/dist/providers/llama-cpp/engine-flags.d.ts +5 -0
- package/dist/providers/llama-cpp/engine-flags.js +5 -2
- package/dist/providers/llama-cpp/provider.js +20 -4
- package/dist/providers/mlx/provider.js +13 -4
- package/dist/providers/mlx/python/gezel_mlx_server.py +9 -2
- package/dist/providers/mlx/python/spec_decode.py +44 -5
- package/dist/providers/native/capacity-broker.d.ts +1 -1
- package/dist/providers/native/capacity-broker.js +8 -8
- package/dist/providers/native/capacity-budget.js +5 -4
- package/dist/providers/native/device-capacity-ledger.d.ts +2 -0
- package/dist/providers/native/device-capacity-ledger.js +36 -5
- package/dist/providers/native/device-capacity.js +4 -3
- package/dist/providers/native/local-engine-runtime.js +4 -4
- package/dist/providers/native/process-identity.d.ts +2 -0
- package/dist/providers/native/process-identity.js +70 -0
- package/dist/relevance/relevance-core.js +2 -0
- package/dist/relevance/relevance-model.js +2 -0
- package/dist/relevance/settings.js +2 -2
- package/dist/runtime-lock.d.ts +43 -5
- package/dist/runtime-lock.js +189 -26
- package/dist/system/host-memory.d.ts +46 -0
- package/dist/system/host-memory.js +89 -0
- package/dist/system/memory.js +5 -4
- package/dist/transformers-cache.js +2 -0
- package/dist/utils/download-common.d.ts +1 -1
- package/package.json +8 -8
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
* but logs that it could not anchor to a baked-in digest.
|
|
41
41
|
*/
|
|
42
42
|
/** Native release version this build pins. Placeholder until first public release. */
|
|
43
|
-
export declare const NATIVE_ENGINE_RELEASE = "0.1.
|
|
43
|
+
export declare const NATIVE_ENGINE_RELEASE = "0.1.57";
|
|
44
44
|
/** sha256 of the pinned release's `SHA256SUMS` asset. All-zeros = unpinned. */
|
|
45
|
-
export declare const SHA256SUMS_DIGEST = "
|
|
46
|
-
/** Exact SHA256 values for every engine archive published by native-v0.1.
|
|
45
|
+
export declare const SHA256SUMS_DIGEST = "977b0ad4cdb8983ed44d7a3223267038b1f35b2806d8a1807d7d15c5c7e94f47";
|
|
46
|
+
/** Exact SHA256 values for every engine archive published by native-v0.1.57. */
|
|
47
47
|
export declare const NATIVE_ENGINE_ARCHIVE_SHA256: Readonly<Record<string, string>>;
|
|
48
|
-
/** Download size in bytes of every engine archive published by native-v0.1.
|
|
48
|
+
/** Download size in bytes of every engine archive published by native-v0.1.57. */
|
|
49
49
|
export declare const NATIVE_ENGINE_ARCHIVE_BYTES: Readonly<Record<string, number>>;
|
|
50
50
|
/**
|
|
51
51
|
* True only when the pinned release's standalone macOS archives were
|
|
@@ -40,47 +40,47 @@
|
|
|
40
40
|
* but logs that it could not anchor to a baked-in digest.
|
|
41
41
|
*/
|
|
42
42
|
/** Native release version this build pins. Placeholder until first public release. */
|
|
43
|
-
export const NATIVE_ENGINE_RELEASE = '0.1.
|
|
43
|
+
export const NATIVE_ENGINE_RELEASE = '0.1.57';
|
|
44
44
|
/** sha256 of the pinned release's `SHA256SUMS` asset. All-zeros = unpinned. */
|
|
45
|
-
export const SHA256SUMS_DIGEST = '
|
|
45
|
+
export const SHA256SUMS_DIGEST = '977b0ad4cdb8983ed44d7a3223267038b1f35b2806d8a1807d7d15c5c7e94f47';
|
|
46
46
|
// BEGIN PINNED NATIVE ARCHIVE HASHES
|
|
47
|
-
/** Exact SHA256 values for every engine archive published by native-v0.1.
|
|
47
|
+
/** Exact SHA256 values for every engine archive published by native-v0.1.57. */
|
|
48
48
|
export const NATIVE_ENGINE_ARCHIVE_SHA256 = Object.freeze({
|
|
49
|
-
'gezel-native-0.1.
|
|
50
|
-
'gezel-native-0.1.
|
|
51
|
-
'gezel-native-0.1.
|
|
52
|
-
'gezel-native-0.1.
|
|
53
|
-
'gezel-native-0.1.
|
|
54
|
-
'gezel-native-0.1.
|
|
55
|
-
'gezel-native-0.1.
|
|
56
|
-
'gezel-native-0.1.
|
|
57
|
-
'gezel-native-0.1.
|
|
58
|
-
'gezel-native-0.1.
|
|
59
|
-
'gezel-native-0.1.
|
|
60
|
-
'gezel-native-0.1.
|
|
61
|
-
'gezel-native-0.1.
|
|
62
|
-
'gezel-native-0.1.
|
|
63
|
-
'gezel-native-0.1.
|
|
64
|
-
'gezel-native-0.1.
|
|
49
|
+
'gezel-native-0.1.57-darwin-arm64-metal.tar.gz': '6b97be648b032980cf73663db4424140f4cc04577972dc283b956af677ce884a',
|
|
50
|
+
'gezel-native-0.1.57-darwin-arm64.tar.gz': 'e8ca070c4d3961e95946ed32fe7376ddbc97e407dd3f5b78e26cab20c8fb286a',
|
|
51
|
+
'gezel-native-0.1.57-linux-arm64-cpu.tar.gz': 'cc87822123602a0024c63a0d65789232a665140cb2fe37b106d5bd680d12f795',
|
|
52
|
+
'gezel-native-0.1.57-linux-arm64-cuda.tar.gz': '315a441e5698800945f7030e9da961e20f3cf379a4b75c98e1d6ba88c8fee1c5',
|
|
53
|
+
'gezel-native-0.1.57-linux-arm64.tar.gz': '0684b77d23f008f8a2aa0d9d8931437bacd8569fb6c10d3ddab61a5fb25b6a06',
|
|
54
|
+
'gezel-native-0.1.57-linux-x64-cpu.tar.gz': 'b2100842f51c393b92667535798e49932173d52626f5ae72c40005b3408f1201',
|
|
55
|
+
'gezel-native-0.1.57-linux-x64-cuda.tar.gz': '2fca7720614687e8491be17366060c604551257199d395f795b27a87216bcde9',
|
|
56
|
+
'gezel-native-0.1.57-linux-x64-vulkan.tar.gz': 'c1014a1fe1d241ad1ee9abfa5badafcce208cbff8d38b4b4deb4779f31a95bef',
|
|
57
|
+
'gezel-native-0.1.57-linux-x64.tar.gz': 'a7f3dbe1941c3d03ed121c32be1bdd199aea47080b03d89989590a0f5d13c5ff',
|
|
58
|
+
'gezel-native-0.1.57-win32-arm64-cpu.zip': '12d66681cec1872f23b015c7d0bd45a25ed262342da6b0ecea8bea303adf2105',
|
|
59
|
+
'gezel-native-0.1.57-win32-arm64-cuda.zip': 'b437a9f0894673179f91a1af75d5d7d058dafa1b4f48a57eab123596f1c21ca4',
|
|
60
|
+
'gezel-native-0.1.57-win32-arm64.zip': '21cddb8b733f9a2669d64b1ada18002f60bb2779f2d5e2aacfb88214db00da7e',
|
|
61
|
+
'gezel-native-0.1.57-win32-x64-cpu.zip': 'a81f7c6754f1954a0ed5de1efc47d6194dc60d912138a9d2b8e4f992168b12c6',
|
|
62
|
+
'gezel-native-0.1.57-win32-x64-cuda.zip': '9e3f21713fe77c23536dd4124244ac3834f90c82d6e470cb6836a73bb4f7c592',
|
|
63
|
+
'gezel-native-0.1.57-win32-x64-vulkan.zip': '0d473300317b4f6cb072bdd7875ce1536a85fe50e781c435e1aef1c4cbdb08e5',
|
|
64
|
+
'gezel-native-0.1.57-win32-x64.zip': '89a073abcfc97e50b9a0c39f56862b51ac21139b7ca4a3e7a75105dca56292a2',
|
|
65
65
|
});
|
|
66
|
-
/** Download size in bytes of every engine archive published by native-v0.1.
|
|
66
|
+
/** Download size in bytes of every engine archive published by native-v0.1.57. */
|
|
67
67
|
export const NATIVE_ENGINE_ARCHIVE_BYTES = Object.freeze({
|
|
68
|
-
'gezel-native-0.1.
|
|
69
|
-
'gezel-native-0.1.
|
|
70
|
-
'gezel-native-0.1.
|
|
71
|
-
'gezel-native-0.1.
|
|
72
|
-
'gezel-native-0.1.
|
|
73
|
-
'gezel-native-0.1.
|
|
74
|
-
'gezel-native-0.1.
|
|
75
|
-
'gezel-native-0.1.
|
|
76
|
-
'gezel-native-0.1.
|
|
77
|
-
'gezel-native-0.1.
|
|
78
|
-
'gezel-native-0.1.
|
|
79
|
-
'gezel-native-0.1.
|
|
80
|
-
'gezel-native-0.1.
|
|
81
|
-
'gezel-native-0.1.
|
|
82
|
-
'gezel-native-0.1.
|
|
83
|
-
'gezel-native-0.1.
|
|
68
|
+
'gezel-native-0.1.57-darwin-arm64-metal.tar.gz': 7387963,
|
|
69
|
+
'gezel-native-0.1.57-darwin-arm64.tar.gz': 42223786,
|
|
70
|
+
'gezel-native-0.1.57-linux-arm64-cpu.tar.gz': 9223249,
|
|
71
|
+
'gezel-native-0.1.57-linux-arm64-cuda.tar.gz': 621626283,
|
|
72
|
+
'gezel-native-0.1.57-linux-arm64.tar.gz': 42040003,
|
|
73
|
+
'gezel-native-0.1.57-linux-x64-cpu.tar.gz': 13398337,
|
|
74
|
+
'gezel-native-0.1.57-linux-x64-cuda.tar.gz': 1000325316,
|
|
75
|
+
'gezel-native-0.1.57-linux-x64-vulkan.tar.gz': 26290440,
|
|
76
|
+
'gezel-native-0.1.57-linux-x64.tar.gz': 57190295,
|
|
77
|
+
'gezel-native-0.1.57-win32-arm64-cpu.zip': 6049234,
|
|
78
|
+
'gezel-native-0.1.57-win32-arm64-cuda.zip': 243595554,
|
|
79
|
+
'gezel-native-0.1.57-win32-arm64.zip': 42236484,
|
|
80
|
+
'gezel-native-0.1.57-win32-x64-cpu.zip': 9131460,
|
|
81
|
+
'gezel-native-0.1.57-win32-x64-cuda.zip': 756439338,
|
|
82
|
+
'gezel-native-0.1.57-win32-x64-vulkan.zip': 21673895,
|
|
83
|
+
'gezel-native-0.1.57-win32-x64.zip': 55668381,
|
|
84
84
|
});
|
|
85
85
|
// END PINNED NATIVE ARCHIVE HASHES
|
|
86
86
|
/**
|
|
@@ -32,7 +32,7 @@ export interface ResolveEngineOptions {
|
|
|
32
32
|
signaturePolicy?: SignaturePolicy;
|
|
33
33
|
fetchImpl?: typeof fetch;
|
|
34
34
|
signal?: AbortSignal;
|
|
35
|
-
/** Pre-resolved token: `undefined` =
|
|
35
|
+
/** Pre-resolved token: `undefined` = from the environment; `null` = explicitly none. */
|
|
36
36
|
token?: string | null;
|
|
37
37
|
/** Override the source-pinned SHA256SUMS digest (tests). */
|
|
38
38
|
expectedSha256sumsDigest?: string;
|
package/dist/engines/resolver.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createReadStream, existsSync, readdirSync } from 'node:fs';
|
|
|
3
3
|
import { chmod, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { HttpStatusError, createLogger, nowIso, resolveDistributionProfile, retryTransient, } from '@bendyline/gezel';
|
|
6
|
-
import { DUCKDB_APPLE_TEAM_ID, DUCKDB_ARCHIVE_SHA256, DUCKDB_ASSET, DUCKDB_BINARY_SHA256, DUCKDB_VERSION, DUCKDB_WINDOWS_PUBLISHER, MXC_EXECUTOR_NAME, MXC_EXECUTOR_SHA256, MXC_LICENSE_SHA256, MXC_TARBALL_INTEGRITY, MXC_TARBALL_LICENSE_ENTRY, MXC_TARBALL_SHA256, MXC_TARBALL_URL, MXC_VERIFIED_SENTINEL, MXC_VERSION, MXC_WINDOWS_PUBLISHER, duckdbAssetUrl, duckdbBinaryName, duckdbInstallDir, duckdbPlatformKey, mxcArch, mxcInstallDir, mxcTarballEntry, resolvePlatformKey,
|
|
6
|
+
import { DUCKDB_APPLE_TEAM_ID, DUCKDB_ARCHIVE_SHA256, DUCKDB_ASSET, DUCKDB_BINARY_SHA256, DUCKDB_VERSION, DUCKDB_WINDOWS_PUBLISHER, MXC_EXECUTOR_NAME, MXC_EXECUTOR_SHA256, MXC_LICENSE_SHA256, MXC_TARBALL_INTEGRITY, MXC_TARBALL_LICENSE_ENTRY, MXC_TARBALL_SHA256, MXC_TARBALL_URL, MXC_VERIFIED_SENTINEL, MXC_VERSION, MXC_WINDOWS_PUBLISHER, duckdbAssetUrl, duckdbBinaryName, duckdbInstallDir, duckdbPlatformKey, mxcArch, mxcInstallDir, mxcTarballEntry, resolvePlatformKey, } from '@bendyline/gezel/native';
|
|
7
7
|
import * as tar from 'tar';
|
|
8
8
|
import { downloadWithRetry, friendlyErrors, } from '../utils/download-with-retry.js';
|
|
9
9
|
import { extractZip } from '../utils/extract-zip.js';
|
|
@@ -33,6 +33,7 @@ const ENGINE_ENV_VAR = {
|
|
|
33
33
|
uv: 'GEZEL_UV_BIN',
|
|
34
34
|
duckdb: 'GEZEL_DUCKDB_BIN',
|
|
35
35
|
'apple-fm': 'GEZEL_APPLE_FM_BIN',
|
|
36
|
+
sandbox: 'GEZEL_SANDBOX_BIN',
|
|
36
37
|
};
|
|
37
38
|
/**
|
|
38
39
|
* Thrown for the "can't resolve, and that's expected/actionable" cases:
|
|
@@ -541,14 +542,16 @@ export async function* resolveEngine(opts) {
|
|
|
541
542
|
// `bendyline/gezel` is public, so release metadata and assets are readable
|
|
542
543
|
// anonymously. A token stays OPTIONAL and is used when present purely to
|
|
543
544
|
// lift GitHub's 60-request/hour unauthenticated API rate limit. Do not
|
|
544
|
-
// reinstate a hard gate here: users who install from npm have no
|
|
545
|
-
//
|
|
546
|
-
//
|
|
547
|
-
const
|
|
545
|
+
// reinstate a hard gate here: users who install from npm have no token,
|
|
546
|
+
// and requiring one would make on-device engines unreachable for every
|
|
547
|
+
// consumer outside this repo.
|
|
548
|
+
const auth = {
|
|
549
|
+
token: opts.token !== undefined ? opts.token : resolveGitHubToken(),
|
|
550
|
+
};
|
|
548
551
|
const baseFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
549
552
|
const tag = `native-v${version}`;
|
|
550
553
|
// ── 1. Resolve release + assets ──
|
|
551
|
-
const release = await ghJson(`${apiBase}/repos/${REPO}/releases/tags/${tag}`, baseFetch,
|
|
554
|
+
const release = await ghJson(`${apiBase}/repos/${REPO}/releases/tags/${tag}`, baseFetch, auth);
|
|
552
555
|
const archiveAsset = release.assets?.find((a) => a.name === archiveName);
|
|
553
556
|
const sumsAsset = release.assets?.find((a) => a.name === 'SHA256SUMS');
|
|
554
557
|
if (!archiveAsset) {
|
|
@@ -558,7 +561,7 @@ export async function* resolveEngine(opts) {
|
|
|
558
561
|
yield* fail(`release ${tag} is missing its SHA256SUMS manifest — refusing to install unverified`);
|
|
559
562
|
}
|
|
560
563
|
// ── 2. SHA256SUMS: verify own digest against the source pin, then parse ──
|
|
561
|
-
const sumsBytes = await ghBytes(sumsAsset.url, baseFetch,
|
|
564
|
+
const sumsBytes = await ghBytes(sumsAsset.url, baseFetch, auth);
|
|
562
565
|
const sumsDigest = createHash('sha256').update(sumsBytes).digest('hex');
|
|
563
566
|
if (!unpinned && sumsDigest !== expectedDigest) {
|
|
564
567
|
yield* fail(`SHA256SUMS digest mismatch for ${tag}: this build pins ${expectedDigest.slice(0, 16)}… but the release served ${sumsDigest.slice(0, 16)}…. Refusing — the release may have been tampered with or re-cut.`);
|
|
@@ -584,7 +587,7 @@ export async function* resolveEngine(opts) {
|
|
|
584
587
|
url: archiveAsset.url,
|
|
585
588
|
destPath: archivePath,
|
|
586
589
|
approxSizeBytes: archiveAsset.size ?? 0,
|
|
587
|
-
fetchImpl:
|
|
590
|
+
fetchImpl: gitHubFetch(baseFetch, auth, 'application/octet-stream'),
|
|
588
591
|
...(opts.signal ? { signal: opts.signal } : {}),
|
|
589
592
|
});
|
|
590
593
|
let outcome;
|
|
@@ -765,35 +768,37 @@ function stampEnv(engine, binPath, variant, versionDir) {
|
|
|
765
768
|
process.env.GEZEL_SQLITE_VEC_PATH = sqliteVec;
|
|
766
769
|
}
|
|
767
770
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
// Named host: a bare `gh auth token` answers for gh's default host, which
|
|
776
|
-
// can be a GitHub Enterprise server whose token must not go to github.com.
|
|
777
|
-
const out = execFileSync('gh', ['auth', 'token', '--hostname', 'github.com'], {
|
|
778
|
-
encoding: 'utf8',
|
|
779
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
780
|
-
...windowsHeadlessSpawnOptions(),
|
|
781
|
-
});
|
|
782
|
-
return out.trim() || null;
|
|
783
|
-
}
|
|
784
|
-
catch {
|
|
785
|
-
return null;
|
|
786
|
-
}
|
|
771
|
+
/**
|
|
772
|
+
* An optional token, from the environment only. This module runs inside apps
|
|
773
|
+
* that embed Gezel, so it never borrows the user's GitHub CLI login: `gh` is
|
|
774
|
+
* not its credential to use, and a stale one used to fail public downloads.
|
|
775
|
+
*/
|
|
776
|
+
function resolveGitHubToken() {
|
|
777
|
+
return process.env.GEZEL_GITHUB_TOKEN || process.env.GITHUB_TOKEN || null;
|
|
787
778
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
779
|
+
/**
|
|
780
|
+
* Fetch from GitHub with the optional token. The release is public, so a token
|
|
781
|
+
* GitHub rejects (expired, revoked) is dropped for the rest of the resolve and
|
|
782
|
+
* the request repeats anonymously instead of failing the install.
|
|
783
|
+
*/
|
|
784
|
+
function gitHubFetch(base, auth, accept) {
|
|
785
|
+
return (async (input, init) => {
|
|
786
|
+
const send = () => base(input, {
|
|
787
|
+
...init,
|
|
788
|
+
headers: {
|
|
789
|
+
...init?.headers,
|
|
790
|
+
Accept: accept,
|
|
791
|
+
...(auth.token ? { Authorization: `Bearer ${auth.token}` } : {}),
|
|
792
|
+
},
|
|
793
|
+
});
|
|
794
|
+
const res = await send();
|
|
795
|
+
if (res.status !== 401 || !auth.token)
|
|
796
|
+
return res;
|
|
797
|
+
await res.body?.cancel().catch(() => { });
|
|
798
|
+
log.warn('[engine-resolver] GitHub rejected the token from GEZEL_GITHUB_TOKEN / GITHUB_TOKEN (401); continuing anonymously');
|
|
799
|
+
auth.token = null;
|
|
800
|
+
return send();
|
|
801
|
+
});
|
|
797
802
|
}
|
|
798
803
|
/**
|
|
799
804
|
* The archive itself goes through `downloadWithRetry`, but the two small
|
|
@@ -808,31 +813,23 @@ function ghRetryLog(what) {
|
|
|
808
813
|
log.warn(`[engine-resolver] ${what} failed (${info.reason}); retrying in ${info.delayMs}ms (attempt ${info.attempt}/${info.maxAttempts})`);
|
|
809
814
|
};
|
|
810
815
|
}
|
|
811
|
-
async function ghJson(url, fetchImpl,
|
|
816
|
+
async function ghJson(url, fetchImpl, auth) {
|
|
817
|
+
const get = gitHubFetch(fetchImpl, auth, 'application/vnd.github+json');
|
|
812
818
|
return retryTransient(async () => {
|
|
813
|
-
const res = await
|
|
814
|
-
headers: {
|
|
815
|
-
Accept: 'application/vnd.github+json',
|
|
816
|
-
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
817
|
-
},
|
|
818
|
-
});
|
|
819
|
+
const res = await get(url);
|
|
819
820
|
if (!res.ok) {
|
|
820
821
|
await res.body?.cancel().catch(() => { });
|
|
821
822
|
// A transient status is thrown as HttpStatusError so retryTransient
|
|
822
823
|
// takes another pass; 4xx becomes the terminal EngineUnavailableError.
|
|
823
|
-
throw new HttpStatusError(res.status, `GitHub API returned ${res.status} for ${url}${res.status === 404 ? ' (release not found
|
|
824
|
+
throw new HttpStatusError(res.status, `GitHub API returned ${res.status} for ${url}${res.status === 404 ? ' (release not found)' : ''}`);
|
|
824
825
|
}
|
|
825
826
|
return (await res.json());
|
|
826
827
|
}, { attempts: GH_METADATA_ATTEMPTS, onRetry: ghRetryLog('GitHub release lookup') }).catch(rethrowAsEngineUnavailable);
|
|
827
828
|
}
|
|
828
|
-
async function ghBytes(assetApiUrl, fetchImpl,
|
|
829
|
+
async function ghBytes(assetApiUrl, fetchImpl, auth) {
|
|
830
|
+
const get = gitHubFetch(fetchImpl, auth, 'application/octet-stream');
|
|
829
831
|
return retryTransient(async () => {
|
|
830
|
-
const res = await
|
|
831
|
-
headers: {
|
|
832
|
-
Accept: 'application/octet-stream',
|
|
833
|
-
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
834
|
-
},
|
|
835
|
-
});
|
|
832
|
+
const res = await get(assetApiUrl);
|
|
836
833
|
if (!res.ok) {
|
|
837
834
|
await res.body?.cancel().catch(() => { });
|
|
838
835
|
throw new HttpStatusError(res.status, `asset download returned ${res.status} for ${assetApiUrl}`);
|
|
@@ -18,6 +18,18 @@ declare module 'hono' {
|
|
|
18
18
|
projectId?: string;
|
|
19
19
|
gezelId?: string;
|
|
20
20
|
team?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The signed-in account behind an account session (ADR 0029, the
|
|
23
|
+
* principal from ADR 0004). Absent for app, device and owner
|
|
24
|
+
* credentials.
|
|
25
|
+
*/
|
|
26
|
+
account?: {
|
|
27
|
+
id: string;
|
|
28
|
+
source: 'password' | 'device' | 'os';
|
|
29
|
+
label: string;
|
|
30
|
+
};
|
|
31
|
+
/** The account session this request came in on, for "sign out this browser". */
|
|
32
|
+
accountSessionId?: string;
|
|
21
33
|
};
|
|
22
34
|
}
|
|
23
35
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { ImageModelPullRegistry } from '../../providers/image/pull-registry.js';
|
|
3
|
+
/** One resumable download protocol, with separate registries for models and styles. */
|
|
4
|
+
export declare function registerImageEnsureRoutes(app: Hono, prefix: string, pulls: ImageModelPullRegistry, qualified: (id: string) => string): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { streamSSE } from 'hono/streaming';
|
|
2
|
+
function apiError(code, message) {
|
|
3
|
+
return { error: { message, type: 'invalid_request_error', code } };
|
|
4
|
+
}
|
|
5
|
+
function ensureEvent(jobId, event, totalBytes, qualified) {
|
|
6
|
+
const job = { jobId, modelId: qualified(jobId) };
|
|
7
|
+
switch (event.type) {
|
|
8
|
+
case 'progress':
|
|
9
|
+
return {
|
|
10
|
+
...job,
|
|
11
|
+
type: 'progress',
|
|
12
|
+
bytesWritten: event.bytesWritten,
|
|
13
|
+
totalBytes: event.totalBytes ?? totalBytes,
|
|
14
|
+
};
|
|
15
|
+
case 'retrying':
|
|
16
|
+
return {
|
|
17
|
+
...job,
|
|
18
|
+
type: 'retrying',
|
|
19
|
+
attempt: event.attempt,
|
|
20
|
+
maxAttempts: event.maxAttempts,
|
|
21
|
+
delayMs: event.delayMs,
|
|
22
|
+
reason: event.reason,
|
|
23
|
+
};
|
|
24
|
+
case 'error':
|
|
25
|
+
return { ...job, type: 'error', error: event.error };
|
|
26
|
+
case 'done':
|
|
27
|
+
return { ...job, type: 'done' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function pullStatus(pull) {
|
|
31
|
+
if (!pull.finished)
|
|
32
|
+
return 'running';
|
|
33
|
+
return pull.error ? 'error' : 'done';
|
|
34
|
+
}
|
|
35
|
+
/** One resumable download protocol, with separate registries for models and styles. */
|
|
36
|
+
export function registerImageEnsureRoutes(app, prefix, pulls, qualified) {
|
|
37
|
+
app.get(`${prefix}/:jobId`, (c) => {
|
|
38
|
+
const pull = pulls.get(c.req.param('jobId'));
|
|
39
|
+
if (!pull)
|
|
40
|
+
return c.json(apiError('job_not_found', 'job not found'), 404);
|
|
41
|
+
return c.json({
|
|
42
|
+
job_id: pull.id,
|
|
43
|
+
model_id: qualified(pull.id),
|
|
44
|
+
status: pullStatus(pull),
|
|
45
|
+
started_at: Date.parse(pull.startedAt),
|
|
46
|
+
bytes_written: pull.bytesWritten,
|
|
47
|
+
total_bytes: pull.totalBytes,
|
|
48
|
+
...(pull.error ? { error: pull.error } : {}),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
app.get(`${prefix}/:jobId/events`, (c) => {
|
|
52
|
+
const jobId = c.req.param('jobId');
|
|
53
|
+
const snapshot = pulls.get(jobId);
|
|
54
|
+
if (!snapshot)
|
|
55
|
+
return c.json(apiError('job_not_found', 'job not found'), 404);
|
|
56
|
+
return streamSSE(c, async (stream) => {
|
|
57
|
+
let closed = false;
|
|
58
|
+
let sawError = false;
|
|
59
|
+
const unsubscribe = pulls.subscribe(jobId, (event) => {
|
|
60
|
+
// A failed pull ends with an error and then its done; the error is terminal.
|
|
61
|
+
if (sawError)
|
|
62
|
+
return;
|
|
63
|
+
if (event.type === 'error')
|
|
64
|
+
sawError = true;
|
|
65
|
+
const terminal = event.type === 'done' || event.type === 'error';
|
|
66
|
+
void stream
|
|
67
|
+
.writeSSE({
|
|
68
|
+
data: JSON.stringify(ensureEvent(jobId, event, snapshot.totalBytes, qualified)),
|
|
69
|
+
})
|
|
70
|
+
.then(() => {
|
|
71
|
+
if (terminal)
|
|
72
|
+
closed = true;
|
|
73
|
+
})
|
|
74
|
+
.catch(() => {
|
|
75
|
+
closed = true;
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
if (!unsubscribe)
|
|
79
|
+
return;
|
|
80
|
+
stream.onAbort(() => {
|
|
81
|
+
closed = true;
|
|
82
|
+
unsubscribe();
|
|
83
|
+
});
|
|
84
|
+
while (!closed) {
|
|
85
|
+
await stream.sleep(1000);
|
|
86
|
+
try {
|
|
87
|
+
await stream.writeSSE({ event: 'ping', data: '' });
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
closed = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
unsubscribe();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
app.delete(`${prefix}/:jobId`, (c) => {
|
|
97
|
+
if (!pulls.cancel(c.req.param('jobId'))) {
|
|
98
|
+
return c.json(apiError('job_not_found', 'No download in progress for that job'), 404);
|
|
99
|
+
}
|
|
100
|
+
return c.json({ cancelled: true });
|
|
101
|
+
});
|
|
102
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import type { ImageModelPullRegistry } from '../../providers/image/pull-registry.js';
|
|
3
|
+
import type { ImagesRouteContext } from './v1-images.js';
|
|
4
|
+
/** App-scoped access to catalog LoRAs; no paths, URLs or engine arguments from callers. */
|
|
5
|
+
export declare function v1ImageStylesRoutes(ctx: ImagesRouteContext, pulls: ImageModelPullRegistry): Hono;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { isSafeModelId } from '../../models/model-id.js';
|
|
4
|
+
import { registerImageEnsureRoutes } from './image-ensure-routes.js';
|
|
5
|
+
const styleId = z.string().min(1).max(512).refine(isSafeModelId);
|
|
6
|
+
const ensureRequest = z.object({ style: styleId }).strict();
|
|
7
|
+
const apiError = (code, message) => ({
|
|
8
|
+
error: { code, message, type: 'invalid_request_error' },
|
|
9
|
+
});
|
|
10
|
+
/** App-scoped access to catalog LoRAs; no paths, URLs or engine arguments from callers. */
|
|
11
|
+
export function v1ImageStylesRoutes(ctx, pulls) {
|
|
12
|
+
const app = new Hono();
|
|
13
|
+
app.get('/', async (c) => {
|
|
14
|
+
const provider = await ctx.images.current();
|
|
15
|
+
if (!provider.listLoras || !provider.pullLora || !provider.deleteLora) {
|
|
16
|
+
return c.json(apiError('styles_unsupported', 'Update Gezel to add image styles.'), 409);
|
|
17
|
+
}
|
|
18
|
+
const [installed, catalog] = await Promise.all([
|
|
19
|
+
provider.listLoras(),
|
|
20
|
+
ctx.catalog.list('image-lora'),
|
|
21
|
+
]);
|
|
22
|
+
const data = [];
|
|
23
|
+
for (const item of catalog) {
|
|
24
|
+
const m = item.manifest;
|
|
25
|
+
if (m.kind !== 'image-lora' || m.purpose !== 'style')
|
|
26
|
+
continue;
|
|
27
|
+
data.push({
|
|
28
|
+
id: m.id,
|
|
29
|
+
object: 'image_style',
|
|
30
|
+
name: m.name,
|
|
31
|
+
description: m.description,
|
|
32
|
+
availability: installed.some((l) => l.id === m.id)
|
|
33
|
+
? 'available'
|
|
34
|
+
: pulls.get(m.id)?.finished === false
|
|
35
|
+
? 'downloading'
|
|
36
|
+
: 'download-required',
|
|
37
|
+
base_models: m.baseModels.map((id) => `sd-cpp:${id}`),
|
|
38
|
+
download_bytes: m.approxSizeBytes,
|
|
39
|
+
...((m.licenseShortName ?? m.license) ? { license: m.licenseShortName ?? m.license } : {}),
|
|
40
|
+
commercial_use: m.commercialUse,
|
|
41
|
+
...(m.licenseUrl ? { license_url: m.licenseUrl } : {}),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
for (const l of installed) {
|
|
45
|
+
if (l.purpose !== 'style' || data.some((s) => s.id === l.id))
|
|
46
|
+
continue;
|
|
47
|
+
data.push({
|
|
48
|
+
id: l.id,
|
|
49
|
+
object: 'image_style',
|
|
50
|
+
name: l.name,
|
|
51
|
+
availability: 'available',
|
|
52
|
+
download_bytes: l.approxSizeBytes,
|
|
53
|
+
base_models: l.baseModels.map((id) => `sd-cpp:${id}`),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return c.json({ object: 'list', data });
|
|
57
|
+
});
|
|
58
|
+
app.post('/ensure', async (c) => {
|
|
59
|
+
const { style } = ensureRequest.parse(await c.req.json());
|
|
60
|
+
const provider = await ctx.images.current();
|
|
61
|
+
if (!provider.listLoras || !provider.pullLora)
|
|
62
|
+
return c.json(apiError('styles_unsupported', 'Update Gezel to add image styles.'), 409);
|
|
63
|
+
const installed = await provider.listLoras();
|
|
64
|
+
if (installed.some((l) => l.id === style && l.purpose === 'style'))
|
|
65
|
+
return c.json({ status: 'ready', model_id: style });
|
|
66
|
+
const item = await ctx.catalog.get('image-lora', style);
|
|
67
|
+
if (item?.manifest.kind !== 'image-lora' || item.manifest.purpose !== 'style')
|
|
68
|
+
return c.json(apiError('unknown_style', 'That style is not in the catalog.'), 404);
|
|
69
|
+
const models = await provider.listInstalledModels();
|
|
70
|
+
if (!models.some((model) => item.manifest.kind === 'image-lora' && item.manifest.baseModels.includes(model.id))) {
|
|
71
|
+
return c.json(apiError('style_model_required', 'Download a compatible image model before adding this style.'), 409);
|
|
72
|
+
}
|
|
73
|
+
await pulls.start(style);
|
|
74
|
+
return c.json({ status: 'downloading', model_id: style, job_id: style }, 202);
|
|
75
|
+
});
|
|
76
|
+
registerImageEnsureRoutes(app, '/ensure', pulls, (id) => id);
|
|
77
|
+
app.delete('/:id', async (c) => {
|
|
78
|
+
const id = styleId.parse(c.req.param('id'));
|
|
79
|
+
if (pulls.get(id)?.finished === false)
|
|
80
|
+
return c.json(apiError('style_downloading', 'Cancel the style download before removing it.'), 409);
|
|
81
|
+
await ctx.images.reset();
|
|
82
|
+
const provider = await ctx.images.current();
|
|
83
|
+
if (!provider.deleteLora || !provider.listLoras)
|
|
84
|
+
return c.json(apiError('styles_unsupported', 'Update Gezel to manage image styles.'), 409);
|
|
85
|
+
if (!(await provider.listLoras()).some((l) => l.id === id && l.purpose === 'style'))
|
|
86
|
+
return c.json(apiError('unknown_style', 'That style is not installed.'), 404);
|
|
87
|
+
await provider.deleteLora(id);
|
|
88
|
+
return c.body(null, 204);
|
|
89
|
+
});
|
|
90
|
+
return app;
|
|
91
|
+
}
|