@atomic-chat/core 0.19.0 → 0.20.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/app-daemon.js +5 -0
- package/dist/app-daemon.js.map +1 -1
- package/dist/cli/bin.js +0 -0
- package/dist/cli/launch.js +2 -0
- package/dist/cli/launch.js.map +1 -1
- package/dist/cli/main.d.ts +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cloud/registry.js +1 -0
- package/dist/cloud/registry.js.map +1 -1
- package/dist/config/paths.d.ts +1 -1
- package/dist/config/paths.js +12 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/contracts/engine-builds.d.ts +6 -1
- package/dist/contracts/engine-builds.js +1 -1
- package/dist/contracts/engine-builds.js.map +1 -1
- package/dist/contracts/engines.d.ts +1 -1
- package/dist/contracts/engines.js +2 -0
- package/dist/contracts/engines.js.map +1 -1
- package/dist/contracts/errors.d.ts +7 -1
- package/dist/contracts/errors.js.map +1 -1
- package/dist/contracts/events.d.ts +3 -1
- package/dist/contracts/geniex.d.ts +98 -0
- package/dist/contracts/geniex.js +15 -0
- package/dist/contracts/geniex.js.map +1 -0
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/model-yml.d.ts +40 -0
- package/dist/contracts/model-yml.js +7 -0
- package/dist/contracts/model-yml.js.map +1 -1
- package/dist/contracts/session.d.ts +6 -1
- package/dist/contracts/session.js.map +1 -1
- package/dist/contracts/settings.d.ts +12 -1
- package/dist/contracts/settings.js.map +1 -1
- package/dist/core/app-lease.d.ts +56 -0
- package/dist/core/app-lease.js +50 -0
- package/dist/core/app-lease.js.map +1 -0
- package/dist/core/atomic-core.d.ts +1 -1
- package/dist/core/create.js +109 -5
- package/dist/core/create.js.map +1 -1
- package/dist/engine-builds/engines.d.ts +28 -7
- package/dist/engine-builds/engines.js +49 -5
- package/dist/engine-builds/engines.js.map +1 -1
- package/dist/engine-builds/geniex.d.ts +35 -0
- package/dist/engine-builds/geniex.js +111 -0
- package/dist/engine-builds/geniex.js.map +1 -0
- package/dist/engine-builds/manifest.d.ts +43 -0
- package/dist/engine-builds/manifest.js +92 -0
- package/dist/engine-builds/manifest.js.map +1 -1
- package/dist/engine-builds/order.d.ts +2 -1
- package/dist/engine-builds/order.js +2 -0
- package/dist/engine-builds/order.js.map +1 -1
- package/dist/engine-builds/select.d.ts +15 -0
- package/dist/engine-builds/select.js +14 -0
- package/dist/engine-builds/select.js.map +1 -1
- package/dist/engine-builds/service.d.ts +5 -3
- package/dist/engine-builds/service.js +21 -2
- package/dist/engine-builds/service.js.map +1 -1
- package/dist/engines/service.d.ts +2 -1
- package/dist/engines/service.js +3 -1
- package/dist/engines/service.js.map +1 -1
- package/dist/engines/versions.js +3 -0
- package/dist/engines/versions.js.map +1 -1
- package/dist/integrations/catalog.d.ts +3 -1
- package/dist/integrations/catalog.js +8 -2
- package/dist/integrations/catalog.js.map +1 -1
- package/dist/integrations/config-io.d.ts +45 -4
- package/dist/integrations/config-io.js +91 -6
- package/dist/integrations/config-io.js.map +1 -1
- package/dist/integrations/configure/codex-repair.d.ts +75 -0
- package/dist/integrations/configure/codex-repair.js +254 -0
- package/dist/integrations/configure/codex-repair.js.map +1 -0
- package/dist/integrations/configure/codex.d.ts +48 -10
- package/dist/integrations/configure/codex.js +126 -32
- package/dist/integrations/configure/codex.js.map +1 -1
- package/dist/integrations/configure/registry.d.ts +4 -1
- package/dist/integrations/configure/registry.js +1 -0
- package/dist/integrations/configure/registry.js.map +1 -1
- package/dist/models/gguf/kv-cache.d.ts +5 -0
- package/dist/models/gguf/kv-cache.js +35 -2
- package/dist/models/gguf/kv-cache.js.map +1 -1
- package/dist/models/gguf/reader.d.ts +5 -0
- package/dist/models/gguf/reader.js +15 -3
- package/dist/models/gguf/reader.js.map +1 -1
- package/dist/router/resolve.d.ts +3 -2
- package/dist/router/resolve.js +3 -1
- package/dist/router/resolve.js.map +1 -1
- package/dist/runtime/geniex/accelerators.d.ts +20 -0
- package/dist/runtime/geniex/accelerators.js +53 -0
- package/dist/runtime/geniex/accelerators.js.map +1 -0
- package/dist/runtime/geniex/check.d.ts +34 -0
- package/dist/runtime/geniex/check.js +117 -0
- package/dist/runtime/geniex/check.js.map +1 -0
- package/dist/runtime/geniex/chip.d.ts +29 -0
- package/dist/runtime/geniex/chip.js +35 -0
- package/dist/runtime/geniex/chip.js.map +1 -0
- package/dist/runtime/geniex/devices.d.ts +13 -0
- package/dist/runtime/geniex/devices.js +32 -0
- package/dist/runtime/geniex/devices.js.map +1 -0
- package/dist/runtime/geniex/geniex-host.d.ts +17 -0
- package/dist/runtime/geniex/geniex-host.js +26 -0
- package/dist/runtime/geniex/geniex-host.js.map +1 -0
- package/dist/runtime/geniex/host/args.d.ts +56 -0
- package/dist/runtime/geniex/host/args.js +115 -0
- package/dist/runtime/geniex/host/args.js.map +1 -0
- package/dist/runtime/geniex/host/engine.d.ts +76 -0
- package/dist/runtime/geniex/host/engine.js +122 -0
- package/dist/runtime/geniex/host/engine.js.map +1 -0
- package/dist/runtime/geniex/host/ffi-bun.d.ts +15 -0
- package/dist/runtime/geniex/host/ffi-bun.js +415 -0
- package/dist/runtime/geniex/host/ffi-bun.js.map +1 -0
- package/dist/runtime/geniex/host/grammar.d.ts +11 -0
- package/dist/runtime/geniex/host/grammar.js +223 -0
- package/dist/runtime/geniex/host/grammar.js.map +1 -0
- package/dist/runtime/geniex/host/inspect.d.ts +25 -0
- package/dist/runtime/geniex/host/inspect.js +177 -0
- package/dist/runtime/geniex/host/inspect.js.map +1 -0
- package/dist/runtime/geniex/host/library.d.ts +117 -0
- package/dist/runtime/geniex/host/library.js +38 -0
- package/dist/runtime/geniex/host/library.js.map +1 -0
- package/dist/runtime/geniex/host/openai.d.ts +62 -0
- package/dist/runtime/geniex/host/openai.js +458 -0
- package/dist/runtime/geniex/host/openai.js.map +1 -0
- package/dist/runtime/geniex/host/run.d.ts +48 -0
- package/dist/runtime/geniex/host/run.js +208 -0
- package/dist/runtime/geniex/host/run.js.map +1 -0
- package/dist/runtime/geniex/host/server.d.ts +39 -0
- package/dist/runtime/geniex/host/server.js +232 -0
- package/dist/runtime/geniex/host/server.js.map +1 -0
- package/dist/runtime/geniex/host/worker-protocol.d.ts +76 -0
- package/dist/runtime/geniex/host/worker-protocol.js +116 -0
- package/dist/runtime/geniex/host/worker-protocol.js.map +1 -0
- package/dist/runtime/geniex/host/worker-source.generated.d.ts +1 -0
- package/dist/runtime/geniex/host/worker-source.generated.js +4 -0
- package/dist/runtime/geniex/host/worker-source.generated.js.map +1 -0
- package/dist/runtime/geniex/host/worker.d.ts +7 -0
- package/dist/runtime/geniex/host/worker.js +19 -0
- package/dist/runtime/geniex/host/worker.js.map +1 -0
- package/dist/runtime/geniex/host-process.d.ts +48 -0
- package/dist/runtime/geniex/host-process.js +104 -0
- package/dist/runtime/geniex/host-process.js.map +1 -0
- package/dist/runtime/geniex/index.d.ts +11 -0
- package/dist/runtime/geniex/index.js +12 -0
- package/dist/runtime/geniex/index.js.map +1 -0
- package/dist/runtime/geniex/model-yml.d.ts +8 -0
- package/dist/runtime/geniex/model-yml.js +98 -0
- package/dist/runtime/geniex/model-yml.js.map +1 -0
- package/dist/runtime/geniex/runtime.d.ts +94 -0
- package/dist/runtime/geniex/runtime.js +366 -0
- package/dist/runtime/geniex/runtime.js.map +1 -0
- package/dist/runtime/litert-lm/host/openai.d.ts +4 -37
- package/dist/runtime/litert-lm/host/openai.js +11 -96
- package/dist/runtime/litert-lm/host/openai.js.map +1 -1
- package/dist/runtime/litert-lm/host/pool.d.ts +1 -7
- package/dist/runtime/litert-lm/host/pool.js +1 -17
- package/dist/runtime/litert-lm/host/pool.js.map +1 -1
- package/dist/runtime/litert-lm/host/server.js +11 -53
- package/dist/runtime/litert-lm/host/server.js.map +1 -1
- package/dist/runtime/llamacpp/args.d.ts +5 -0
- package/dist/runtime/llamacpp/args.js +2 -0
- package/dist/runtime/llamacpp/args.js.map +1 -1
- package/dist/runtime/llamacpp/fit-margin.d.ts +44 -0
- package/dist/runtime/llamacpp/fit-margin.js +50 -0
- package/dist/runtime/llamacpp/fit-margin.js.map +1 -1
- package/dist/runtime/llamacpp/load-plan.d.ts +5 -0
- package/dist/runtime/llamacpp/load-plan.js +57 -22
- package/dist/runtime/llamacpp/load-plan.js.map +1 -1
- package/dist/runtime/llamacpp/runtime.d.ts +5 -1
- package/dist/runtime/llamacpp/runtime.js +6 -1
- package/dist/runtime/llamacpp/runtime.js.map +1 -1
- package/dist/runtime/shared/external-sessions.js +1 -0
- package/dist/runtime/shared/external-sessions.js.map +1 -1
- package/dist/runtime/shared/fifo-lock.d.ts +10 -0
- package/dist/runtime/shared/fifo-lock.js +21 -0
- package/dist/runtime/shared/fifo-lock.js.map +1 -0
- package/dist/runtime/shared/index.d.ts +2 -0
- package/dist/runtime/shared/index.js +2 -0
- package/dist/runtime/shared/index.js.map +1 -1
- package/dist/runtime/shared/openai-sse.d.ts +112 -0
- package/dist/runtime/shared/openai-sse.js +178 -0
- package/dist/runtime/shared/openai-sse.js.map +1 -0
- package/dist/server/clients.d.ts +6 -0
- package/dist/server/clients.js +11 -0
- package/dist/server/clients.js.map +1 -1
- package/dist/server/control/router.js +2 -0
- package/dist/server/control/router.js.map +1 -1
- package/dist/server/control/routes/geniex.d.ts +7 -0
- package/dist/server/control/routes/geniex.js +22 -0
- package/dist/server/control/routes/geniex.js.map +1 -0
- package/dist/server/control/types.d.ts +11 -1
- package/dist/server/control/types.js.map +1 -1
- package/dist/server/http.js +2 -0
- package/dist/server/http.js.map +1 -1
- package/dist/server/public/embedding.d.ts +8 -7
- package/dist/server/public/embedding.js +15 -7
- package/dist/server/public/embedding.js.map +1 -1
- package/dist/server/public/forward.js +23 -6
- package/dist/server/public/forward.js.map +1 -1
- package/dist/server/public/listing.js +1 -0
- package/dist/server/public/listing.js.map +1 -1
- package/dist/server/public/responses.js +9 -0
- package/dist/server/public/responses.js.map +1 -1
- package/dist/server/public/telemetry.d.ts +7 -1
- package/dist/server/public/telemetry.js +11 -3
- package/dist/server/public/telemetry.js.map +1 -1
- package/dist/server/public/trace.d.ts +8 -4
- package/dist/server/public/trace.js +15 -7
- package/dist/server/public/trace.js.map +1 -1
- package/dist/server/public/validate.d.ts +32 -0
- package/dist/server/public/validate.js +146 -0
- package/dist/server/public/validate.js.map +1 -0
- package/dist/settings/schema/geniex.json +63 -0
- package/dist/settings/schema/mlx.json +1 -1
- package/dist/settings/schema.js +11 -0
- package/dist/settings/schema.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -2
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The hidden `geniex-host` mode of the core binaries (openspec change `add-geniex-runtime`, design
|
|
3
|
+
* D1): one process per model or command, so a crash of Qualcomm's native library never takes the
|
|
4
|
+
* core down. Core starts it with `process.execPath`; nothing else should. The library runs in a
|
|
5
|
+
* Worker (`engine.ts`); this thread keeps the HTTP server and the queue.
|
|
6
|
+
*
|
|
7
|
+
* stdout carries JSON lines only: the probe answer, the model metadata, or `serve`'s readiness line.
|
|
8
|
+
* Errors go to stderr; the ones core maps to its own codes are one JSON line `{code, …}` there.
|
|
9
|
+
*/
|
|
10
|
+
import { mkdir, rm } from 'node:fs/promises';
|
|
11
|
+
import { resolve } from 'node:path';
|
|
12
|
+
import { compareVersions } from '../../../backend/index.js';
|
|
13
|
+
import { GeniexHostUsageError, parseGeniexHostArgs } from './args.js';
|
|
14
|
+
import { GeniexInspectError, inspectGeniexModel } from './inspect.js';
|
|
15
|
+
import { GeniexLibraryError } from './library.js';
|
|
16
|
+
import { createGeniexServer } from './server.js';
|
|
17
|
+
/** The host's exit codes; core reads 6 and 7 as its `GENIEX_*` codes. */
|
|
18
|
+
export const EXIT = {
|
|
19
|
+
ok: 0,
|
|
20
|
+
/** A bug on core's side. */
|
|
21
|
+
usage: 2,
|
|
22
|
+
/** The library does not load (or there is no Worker to load it in). */
|
|
23
|
+
load: 3,
|
|
24
|
+
/** A library call failed, a model file cannot be read, a port is in use. */
|
|
25
|
+
libraryCall: 4,
|
|
26
|
+
requiresNewerEngine: 6,
|
|
27
|
+
variantUnsupported: 7,
|
|
28
|
+
};
|
|
29
|
+
/** SIGTERM, SIGINT or the end of stdin, whichever comes first (Windows has no SIGTERM). */
|
|
30
|
+
export function watchStopSignals() {
|
|
31
|
+
let resolveStop = () => { };
|
|
32
|
+
const stopped = new Promise((done) => (resolveStop = done));
|
|
33
|
+
const stop = () => resolveStop();
|
|
34
|
+
process.on('SIGTERM', stop);
|
|
35
|
+
process.on('SIGINT', stop);
|
|
36
|
+
process.stdin.on('end', stop);
|
|
37
|
+
process.stdin.on('close', stop);
|
|
38
|
+
process.stdin.resume();
|
|
39
|
+
return {
|
|
40
|
+
stopped,
|
|
41
|
+
dispose() {
|
|
42
|
+
process.off('SIGTERM', stop);
|
|
43
|
+
process.off('SIGINT', stop);
|
|
44
|
+
process.stdin.off('end', stop);
|
|
45
|
+
process.stdin.off('close', stop);
|
|
46
|
+
process.stdin.pause();
|
|
47
|
+
process.stdin.destroy();
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Line-oriented output over a stream-oriented CLI io. */
|
|
52
|
+
export function lineIo(io) {
|
|
53
|
+
return { stdout: (line) => io.stdout(`${line}\n`), stderr: (line) => io.stderr(`${line}\n`) };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Where a build keeps the library: `<build>/lib` (task 4.2), absolute. Windows searches DLLs in the
|
|
57
|
+
* folder `SetDllDirectoryW` names instead of the working one, so a relative path would not load.
|
|
58
|
+
*/
|
|
59
|
+
export function libraryDir(build) {
|
|
60
|
+
return resolve(build, 'lib');
|
|
61
|
+
}
|
|
62
|
+
const json = (value) => JSON.stringify(value);
|
|
63
|
+
const said = (error) => (error instanceof Error ? error.message : String(error));
|
|
64
|
+
/** A library failure's exit code: `load` when the library did not open, else a failed call. */
|
|
65
|
+
const failureExit = (error) => error instanceof GeniexLibraryError && error.operation === 'load' ? EXIT.load : EXIT.libraryCall;
|
|
66
|
+
/** Runs `geniex-host <argv…>` and returns its exit code. */
|
|
67
|
+
export async function runGeniexHost(argv, deps) {
|
|
68
|
+
let args;
|
|
69
|
+
try {
|
|
70
|
+
args = parseGeniexHostArgs(argv);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
deps.stderr(error instanceof GeniexHostUsageError ? error.message : said(error));
|
|
74
|
+
return EXIT.usage;
|
|
75
|
+
}
|
|
76
|
+
if (args.mode === 'inspect') {
|
|
77
|
+
try {
|
|
78
|
+
deps.stdout(json(await inspectGeniexModel(args.path)));
|
|
79
|
+
return EXIT.ok;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
deps.stderr(error instanceof GeniexInspectError ? error.message : said(error));
|
|
83
|
+
return EXIT.libraryCall;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
let engine;
|
|
87
|
+
try {
|
|
88
|
+
engine = await deps.startEngine();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
deps.stderr(`GenieX does not load from ${args.lib}: ${said(error)}`);
|
|
92
|
+
return EXIT.load;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
if (args.mode === 'probe') {
|
|
96
|
+
try {
|
|
97
|
+
deps.stdout(json(await engine.probe(libraryDir(args.lib))));
|
|
98
|
+
return EXIT.ok;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
deps.stderr(`GenieX does not load from ${args.lib}: ${said(error)}`);
|
|
102
|
+
return failureExit(error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return await serve(engine, args, deps);
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
await engine.destroy().catch(() => { });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async function serve(engine, args, deps) {
|
|
112
|
+
const watch = (deps.watchStop ?? watchStopSignals)();
|
|
113
|
+
try {
|
|
114
|
+
// What the model says about itself, before the library sees it (task 5.3).
|
|
115
|
+
let info;
|
|
116
|
+
try {
|
|
117
|
+
info = await inspectGeniexModel(args.model);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
deps.stderr(said(error));
|
|
121
|
+
return EXIT.libraryCall;
|
|
122
|
+
}
|
|
123
|
+
if (args.plugin === 'qairt' && args.device !== 'npu') {
|
|
124
|
+
deps.stderr(json({
|
|
125
|
+
code: 'GENIEX_VARIANT_UNSUPPORTED',
|
|
126
|
+
plugin: args.plugin,
|
|
127
|
+
device: args.device,
|
|
128
|
+
message: 'AI Hub bundles run on the NPU only.',
|
|
129
|
+
}));
|
|
130
|
+
return EXIT.variantUnsupported;
|
|
131
|
+
}
|
|
132
|
+
if ((info.kind === 'qairt') !== (args.plugin === 'qairt')) {
|
|
133
|
+
deps.stderr(json({
|
|
134
|
+
code: 'GENIEX_VARIANT_UNSUPPORTED',
|
|
135
|
+
plugin: args.plugin,
|
|
136
|
+
device: args.device,
|
|
137
|
+
message: info.kind === 'qairt'
|
|
138
|
+
? 'An AI Hub bundle runs with the qairt plugin, not llama_cpp.'
|
|
139
|
+
: 'A GGUF file runs with the llama_cpp plugin, not qairt.',
|
|
140
|
+
}));
|
|
141
|
+
return EXIT.variantUnsupported;
|
|
142
|
+
}
|
|
143
|
+
if (info.kind === 'qairt' &&
|
|
144
|
+
info.min_runtime_version &&
|
|
145
|
+
compareVersions(info.min_runtime_version, args.engineVersion) > 0) {
|
|
146
|
+
deps.stderr(json({
|
|
147
|
+
code: 'GENIEX_MODEL_REQUIRES_NEWER_ENGINE',
|
|
148
|
+
required: info.min_runtime_version,
|
|
149
|
+
engine: args.engineVersion,
|
|
150
|
+
}));
|
|
151
|
+
return EXIT.requiresNewerEngine;
|
|
152
|
+
}
|
|
153
|
+
const nCtx = Math.min(args.nCtx, info.max_context_tokens ?? args.nCtx);
|
|
154
|
+
let created;
|
|
155
|
+
try {
|
|
156
|
+
created = await engine.create(libraryDir(args.lib), {
|
|
157
|
+
plugin: args.plugin,
|
|
158
|
+
device: args.device,
|
|
159
|
+
model: args.model,
|
|
160
|
+
mmproj: args.mmproj ?? null,
|
|
161
|
+
nCtx,
|
|
162
|
+
threads: args.threads,
|
|
163
|
+
powerMode: args.powerMode,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
deps.stderr(`GenieX could not create the model from ${args.model}: ${said(error)}`);
|
|
168
|
+
return failureExit(error);
|
|
169
|
+
}
|
|
170
|
+
// Only once there is a model to serve: a failed create leaves no folder behind.
|
|
171
|
+
await mkdir(args.tmp, { recursive: true });
|
|
172
|
+
const server = createGeniexServer({
|
|
173
|
+
engine,
|
|
174
|
+
modelId: args.id,
|
|
175
|
+
caps: { vision: created.vision, reasoning: args.reasoning },
|
|
176
|
+
defaultMaxTokens: Math.min(args.maxTokens, nCtx),
|
|
177
|
+
grammar: args.plugin !== 'qairt',
|
|
178
|
+
tmpDir: args.tmp,
|
|
179
|
+
log: (line) => deps.stderr(line),
|
|
180
|
+
});
|
|
181
|
+
try {
|
|
182
|
+
const url = await server.listen(args.port);
|
|
183
|
+
deps.stdout(json({
|
|
184
|
+
ready: true,
|
|
185
|
+
url,
|
|
186
|
+
model_id: args.id,
|
|
187
|
+
plugin: args.plugin,
|
|
188
|
+
device: args.device,
|
|
189
|
+
n_ctx: nCtx,
|
|
190
|
+
vision: created.vision,
|
|
191
|
+
}));
|
|
192
|
+
await watch.stopped;
|
|
193
|
+
return EXIT.ok;
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
deps.stderr(`GenieX host could not listen on 127.0.0.1:${args.port}: ${said(error)}`);
|
|
197
|
+
return EXIT.libraryCall;
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
await server.close();
|
|
201
|
+
await rm(args.tmp, { recursive: true, force: true }).catch(() => { });
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
watch.dispose();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/runtime/geniex/host/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The host's own OpenAI server (openspec change `add-geniex-runtime`, design D6, tasks 5.4–5.5):
|
|
3
|
+
* `GET /v1/models` and `POST /v1/chat/completions` on `127.0.0.1:<port>`, with no authentication —
|
|
4
|
+
* core's session gateway is the only door in, and it checks the key. Generations run one at a time
|
|
5
|
+
* in arrival order (`FifoLock`): the library is single-threaded, and the Worker that owns it blocks
|
|
6
|
+
* for a whole generation. `/v1/models` never waits on the queue.
|
|
7
|
+
*
|
|
8
|
+
* Every request is a full prompt: the chat template is applied in the Worker, the tokens stream back
|
|
9
|
+
* through it, and the reply parser turns them into deltas. A client that hangs up sets the shared
|
|
10
|
+
* cancel flag the Worker's token callback reads; a stop string does the same. Images come as data
|
|
11
|
+
* URLs and go to the library as files under the host's `tmp`, deleted after the answer.
|
|
12
|
+
*/
|
|
13
|
+
import type { ModelCaps } from '../../shared/index.js';
|
|
14
|
+
import type { GeniexEngine } from './engine.js';
|
|
15
|
+
export interface GeniexServerOptions {
|
|
16
|
+
engine: GeniexEngine;
|
|
17
|
+
/** What `/v1/models` lists and replies carry as `model`: core's session id. */
|
|
18
|
+
modelId: string;
|
|
19
|
+
caps: ModelCaps;
|
|
20
|
+
/** The `max_tokens` of a request that names none. */
|
|
21
|
+
defaultMaxTokens: number;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the plugin takes a GBNF grammar (`response_format`). The qairt plugin does not (spike S4:
|
|
24
|
+
* `Unexpected empty grammar stack after accepting piece: <|im_start|>`), so a request asking for one is a 400.
|
|
25
|
+
*/
|
|
26
|
+
grammar?: boolean;
|
|
27
|
+
/** Where request images are written for the library. */
|
|
28
|
+
tmpDir: string;
|
|
29
|
+
now?: () => number;
|
|
30
|
+
/** One line per failed generation, for the host's stderr (core keeps its tail). */
|
|
31
|
+
log?: (line: string) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface GeniexServer {
|
|
34
|
+
/** Listen on loopback; the base URL (`http://127.0.0.1:<port>`). */
|
|
35
|
+
listen(port: number): Promise<string>;
|
|
36
|
+
/** Stop accepting, cancel what runs, wait for it to end. */
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export declare function createGeniexServer(options: GeniexServerOptions): GeniexServer;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The host's own OpenAI server (openspec change `add-geniex-runtime`, design D6, tasks 5.4–5.5):
|
|
3
|
+
* `GET /v1/models` and `POST /v1/chat/completions` on `127.0.0.1:<port>`, with no authentication —
|
|
4
|
+
* core's session gateway is the only door in, and it checks the key. Generations run one at a time
|
|
5
|
+
* in arrival order (`FifoLock`): the library is single-threaded, and the Worker that owns it blocks
|
|
6
|
+
* for a whole generation. `/v1/models` never waits on the queue.
|
|
7
|
+
*
|
|
8
|
+
* Every request is a full prompt: the chat template is applied in the Worker, the tokens stream back
|
|
9
|
+
* through it, and the reply parser turns them into deltas. A client that hangs up sets the shared
|
|
10
|
+
* cancel flag the Worker's token callback reads; a stop string does the same. Images come as data
|
|
11
|
+
* URLs and go to the library as files under the host's `tmp`, deleted after the answer.
|
|
12
|
+
*/
|
|
13
|
+
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
14
|
+
import { createServer } from 'node:http';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { requestAborted } from '../../../server/public/exchange.js';
|
|
17
|
+
import { completionBody, FifoLock, notServed, OpenAiRequestError, readJsonBody, sendJson, sendOpenAiError, SSE_DONE, sseFramer, } from '../../shared/index.js';
|
|
18
|
+
import { jsonSchemaToGrammar } from './grammar.js';
|
|
19
|
+
import { GeniexLibraryError } from './library.js';
|
|
20
|
+
import { GeniexReplyParser, IMAGE_PLACEHOLDER, parseGeniexChatRequest } from './openai.js';
|
|
21
|
+
/** How long a stop waits for a cancelled generation to end in the library. */
|
|
22
|
+
const CLOSE_WAIT_MS = 10_000;
|
|
23
|
+
const GONE_POLL_MS = 50;
|
|
24
|
+
const MIME_EXT = {
|
|
25
|
+
'image/jpeg': 'jpg',
|
|
26
|
+
'image/png': 'png',
|
|
27
|
+
'image/webp': 'webp',
|
|
28
|
+
'image/gif': 'gif',
|
|
29
|
+
'image/bmp': 'bmp',
|
|
30
|
+
};
|
|
31
|
+
export function createGeniexServer(options) {
|
|
32
|
+
const now = options.now ?? Date.now;
|
|
33
|
+
const lock = new FifoLock();
|
|
34
|
+
/** The generation under way, if any: its cancel flag and a promise for its end. */
|
|
35
|
+
let running = null;
|
|
36
|
+
let counter = 0;
|
|
37
|
+
let closed = false;
|
|
38
|
+
const server = createServer((req, res) => {
|
|
39
|
+
void route(req, res).catch((error) => {
|
|
40
|
+
if (res.headersSent)
|
|
41
|
+
return res.destroy();
|
|
42
|
+
sendOpenAiError(res, error instanceof OpenAiRequestError
|
|
43
|
+
? error
|
|
44
|
+
: new OpenAiRequestError(500, error instanceof Error ? error.message : String(error)));
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
async function route(req, res) {
|
|
48
|
+
const path = (req.url ?? '/').split('?')[0] ?? '/';
|
|
49
|
+
if (req.method === 'GET' && path === '/v1/models')
|
|
50
|
+
return sendJson(res, 200, {
|
|
51
|
+
object: 'list',
|
|
52
|
+
data: [
|
|
53
|
+
{ id: options.modelId, object: 'model', created: Math.floor(now() / 1000), owned_by: 'geniex' },
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
if (req.method === 'POST' && path === '/v1/chat/completions') {
|
|
57
|
+
const chat = parseGeniexChatRequest(await readJsonBody(req), options.caps);
|
|
58
|
+
if (chat.responseFormat && options.grammar === false)
|
|
59
|
+
throw new OpenAiRequestError(400, 'response_format: this model runs on the qairt plugin, which has no grammar sampler', 'response_format');
|
|
60
|
+
let hungUp = false;
|
|
61
|
+
res.on('close', () => {
|
|
62
|
+
if (!res.writableFinished)
|
|
63
|
+
hungUp = true;
|
|
64
|
+
});
|
|
65
|
+
// Bun never says the response closed once the body is read; only its native handle knows (ADR
|
|
66
|
+
// 2026-09-22-detect-a-client-that-hangs-up-before-the-answer-under-bun), polled while it runs.
|
|
67
|
+
const gone = () => hungUp || requestAborted(req, res);
|
|
68
|
+
return lock.run(async () => {
|
|
69
|
+
if (gone() || closed)
|
|
70
|
+
return;
|
|
71
|
+
await generate(chat, res, gone);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
sendOpenAiError(res, notServed(req.method ?? 'GET', path, 'GenieX'));
|
|
75
|
+
}
|
|
76
|
+
/** The request's images as files; the paths in the order the content numbered them. */
|
|
77
|
+
async function writeImages(chat, id) {
|
|
78
|
+
if (chat.images.length === 0)
|
|
79
|
+
return [];
|
|
80
|
+
await mkdir(options.tmpDir, { recursive: true });
|
|
81
|
+
return Promise.all(chat.images.map(async (image, index) => {
|
|
82
|
+
const path = join(options.tmpDir, `${id}-${index}.${MIME_EXT[image.mime] ?? 'img'}`);
|
|
83
|
+
await writeFile(path, Buffer.from(image.base64, 'base64'));
|
|
84
|
+
return path;
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
async function generate(chat, res, gone) {
|
|
88
|
+
const framer = sseFramer(`chatcmpl-${now().toString(36)}${(counter++).toString(36)}`, Math.floor(now() / 1000), options.modelId);
|
|
89
|
+
const images = await writeImages(chat, framer.id);
|
|
90
|
+
const messages = chat.messages.map((message) => ({
|
|
91
|
+
...message,
|
|
92
|
+
content: message.content.map((part) => part.type === 'image'
|
|
93
|
+
? {
|
|
94
|
+
type: 'image',
|
|
95
|
+
path: images[chat.images.findIndex((_, i) => IMAGE_PLACEHOLDER(i) === part.path)] ?? part.path,
|
|
96
|
+
}
|
|
97
|
+
: part),
|
|
98
|
+
}));
|
|
99
|
+
const parser = new GeniexReplyParser(chat.stop, chat.tools !== null);
|
|
100
|
+
const cancel = new Int32Array(new SharedArrayBuffer(4));
|
|
101
|
+
let settle = () => { };
|
|
102
|
+
running = { cancel, ended: new Promise((done) => (settle = done)) };
|
|
103
|
+
const stream = chat.stream;
|
|
104
|
+
const write = (deltas) => {
|
|
105
|
+
if (stream && !gone())
|
|
106
|
+
for (const delta of deltas)
|
|
107
|
+
res.write(framer.delta(delta));
|
|
108
|
+
};
|
|
109
|
+
let promptTokens = 0;
|
|
110
|
+
let generatedTokens = 0;
|
|
111
|
+
let stopReason = 'unknown';
|
|
112
|
+
let failure = null;
|
|
113
|
+
const watch = setInterval(() => {
|
|
114
|
+
if (gone())
|
|
115
|
+
Atomics.store(cancel, 0, 1);
|
|
116
|
+
}, GONE_POLL_MS);
|
|
117
|
+
try {
|
|
118
|
+
const prompt = await options.engine.applyChatTemplate({
|
|
119
|
+
messages,
|
|
120
|
+
tools: chat.toolsJson,
|
|
121
|
+
enableThinking: chat.thinking,
|
|
122
|
+
});
|
|
123
|
+
if (stream && !gone()) {
|
|
124
|
+
res.writeHead(200, {
|
|
125
|
+
'content-type': 'text/event-stream',
|
|
126
|
+
'cache-control': 'no-cache',
|
|
127
|
+
'connection': 'keep-alive',
|
|
128
|
+
});
|
|
129
|
+
res.write(framer.delta({ role: 'assistant', content: '' }));
|
|
130
|
+
}
|
|
131
|
+
const config = {
|
|
132
|
+
maxTokens: chat.maxTokens ?? options.defaultMaxTokens,
|
|
133
|
+
// The library sees the stop strings too; the parser still cuts the text at them.
|
|
134
|
+
stop: chat.stop,
|
|
135
|
+
sampler: {
|
|
136
|
+
...(chat.sampler.temperature !== undefined ? { temperature: chat.sampler.temperature } : {}),
|
|
137
|
+
...(chat.sampler.topP !== undefined ? { topP: chat.sampler.topP } : {}),
|
|
138
|
+
...(chat.sampler.topK !== undefined ? { topK: chat.sampler.topK } : {}),
|
|
139
|
+
...(chat.sampler.seed !== undefined ? { seed: chat.sampler.seed } : {}),
|
|
140
|
+
grammar: chat.responseFormat
|
|
141
|
+
? jsonSchemaToGrammar(JSON.parse(chat.responseFormat.value))
|
|
142
|
+
: null,
|
|
143
|
+
},
|
|
144
|
+
imagePaths: images,
|
|
145
|
+
};
|
|
146
|
+
const result = await options.engine.generate(prompt, config, (token) => {
|
|
147
|
+
write(parser.add(token));
|
|
148
|
+
if (parser.stopped)
|
|
149
|
+
Atomics.store(cancel, 0, 1);
|
|
150
|
+
}, cancel);
|
|
151
|
+
promptTokens = result.promptTokens;
|
|
152
|
+
generatedTokens = result.generatedTokens;
|
|
153
|
+
stopReason = parser.stopped ? 'user' : result.stopReason;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
const text = error instanceof Error ? error.message : String(error);
|
|
157
|
+
failure =
|
|
158
|
+
error instanceof OpenAiRequestError
|
|
159
|
+
? error
|
|
160
|
+
: /prompt too long/i.test(text)
|
|
161
|
+
? // The library's own words for a prompt past the context window (spike S4, qairt).
|
|
162
|
+
new OpenAiRequestError(400, `GenieX: ${text}`, 'messages', undefined, 'context_length_exceeded')
|
|
163
|
+
: new OpenAiRequestError(500, `GenieX: ${error instanceof GeniexLibraryError ? error.message : text}`);
|
|
164
|
+
options.log?.(`generation failed: ${failure.message}`);
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
clearInterval(watch);
|
|
168
|
+
running = null;
|
|
169
|
+
settle();
|
|
170
|
+
await Promise.all(images.map((path) => rm(path, { force: true }).catch(() => { })));
|
|
171
|
+
}
|
|
172
|
+
if (gone())
|
|
173
|
+
return;
|
|
174
|
+
write(parser.flush());
|
|
175
|
+
const finish = failure ? null : parser.finish(stopReason);
|
|
176
|
+
// The library's own count where it gave one (a cancelled or failed generation gives none).
|
|
177
|
+
const completion = generatedTokens > 0 ? generatedTokens : parser.tokens;
|
|
178
|
+
const usage = {
|
|
179
|
+
prompt_tokens: promptTokens,
|
|
180
|
+
completion_tokens: completion,
|
|
181
|
+
total_tokens: promptTokens + completion,
|
|
182
|
+
};
|
|
183
|
+
if (stream) {
|
|
184
|
+
if (!res.headersSent) {
|
|
185
|
+
if (failure)
|
|
186
|
+
return sendOpenAiError(res, failure);
|
|
187
|
+
res.writeHead(200, {
|
|
188
|
+
'content-type': 'text/event-stream',
|
|
189
|
+
'cache-control': 'no-cache',
|
|
190
|
+
'connection': 'keep-alive',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (failure)
|
|
194
|
+
res.write(`data: ${JSON.stringify(failure.body)}\n\n`);
|
|
195
|
+
else {
|
|
196
|
+
res.write(framer.delta({}, finish));
|
|
197
|
+
if (chat.includeUsage)
|
|
198
|
+
res.write(framer.frame({ choices: [], usage }));
|
|
199
|
+
}
|
|
200
|
+
res.end(SSE_DONE);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (failure)
|
|
204
|
+
return sendOpenAiError(res, failure);
|
|
205
|
+
sendJson(res, 200, completionBody(framer, options.modelId, parser.message(), finish, usage));
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
listen: (port) => new Promise((resolve, reject) => {
|
|
209
|
+
server.once('error', reject);
|
|
210
|
+
server.listen(port, '127.0.0.1', () => {
|
|
211
|
+
server.off('error', reject);
|
|
212
|
+
resolve(`http://127.0.0.1:${server.address().port}`);
|
|
213
|
+
});
|
|
214
|
+
}),
|
|
215
|
+
close: async () => {
|
|
216
|
+
closed = true;
|
|
217
|
+
// A model destroyed while the library still generates is a use-after-free in the Worker: cancel,
|
|
218
|
+
// then wait for the generation's end (bounded).
|
|
219
|
+
const current = running;
|
|
220
|
+
if (current) {
|
|
221
|
+
Atomics.store(current.cancel, 0, 1);
|
|
222
|
+
await Promise.race([
|
|
223
|
+
current.ended,
|
|
224
|
+
new Promise((resolve) => setTimeout(resolve, CLOSE_WAIT_MS).unref()),
|
|
225
|
+
]);
|
|
226
|
+
}
|
|
227
|
+
server.closeAllConnections();
|
|
228
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/runtime/geniex/host/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAA;AACnE,OAAO,EACL,cAAc,EACd,QAAQ,EACR,SAAS,EACT,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,SAAS,GACV,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAEjD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AA6B1F,8EAA8E;AAC9E,MAAM,aAAa,GAAG,MAAM,CAAA;AAC5B,MAAM,YAAY,GAAG,EAAE,CAAA;AACvB,MAAM,QAAQ,GAA2B;IACvC,YAAY,EAAE,KAAK;IACnB,WAAW,EAAE,KAAK;IAClB,YAAY,EAAE,MAAM;IACpB,WAAW,EAAE,KAAK;IAClB,WAAW,EAAE,KAAK;CACnB,CAAA;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAA;IACnC,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAA;IAC3B,mFAAmF;IACnF,IAAI,OAAO,GAAwD,IAAI,CAAA;IACvE,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,MAAM,GAAG,KAAK,CAAA;IAElB,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,KAAK,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAC5C,IAAI,GAAG,CAAC,WAAW;gBAAE,OAAO,GAAG,CAAC,OAAO,EAAE,CAAA;YACzC,eAAe,CACb,GAAG,EACH,KAAK,YAAY,kBAAkB;gBACjC,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,IAAI,kBAAkB,CAAC,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CACxF,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,KAAK,UAAU,KAAK,CAAC,GAAoB,EAAE,GAAmB;QAC5D,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAA;QAClD,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY;YAC/C,OAAO,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;gBACxB,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE;oBACJ,EAAE,EAAE,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE;iBAChG;aACF,CAAC,CAAA;QACJ,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,sBAAsB,EAAE,CAAC;YAC7D,MAAM,IAAI,GAAG,sBAAsB,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;YAC1E,IAAI,IAAI,CAAC,cAAc,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK;gBAClD,MAAM,IAAI,kBAAkB,CAC1B,GAAG,EACH,oFAAoF,EACpF,iBAAiB,CAClB,CAAA;YACH,IAAI,MAAM,GAAG,KAAK,CAAA;YAClB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBACnB,IAAI,CAAC,GAAG,CAAC,gBAAgB;oBAAE,MAAM,GAAG,IAAI,CAAA;YAC1C,CAAC,CAAC,CAAA;YACF,8FAA8F;YAC9F,+FAA+F;YAC/F,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,MAAM,IAAI,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;YACrD,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;gBACzB,IAAI,IAAI,EAAE,IAAI,MAAM;oBAAE,OAAM;gBAC5B,MAAM,QAAQ,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;YACjC,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IACtE,CAAC;IAED,uFAAuF;IACvF,KAAK,UAAU,WAAW,CAAC,IAAsB,EAAE,EAAU;QAC3D,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAA;QACvC,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAChD,OAAO,OAAO,CAAC,GAAG,CAChB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC,CAAA;YACpF,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;YAC1D,OAAO,IAAI,CAAA;QACb,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK,UAAU,QAAQ,CAAC,IAAsB,EAAE,GAAmB,EAAE,IAAmB;QACtF,MAAM,MAAM,GAAG,SAAS,CACtB,YAAY,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAC3D,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EACxB,OAAO,CAAC,OAAO,CAChB,CAAA;QACD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC/C,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CACpC,IAAI,CAAC,IAAI,KAAK,OAAO;gBACnB,CAAC,CAAC;oBACE,IAAI,EAAE,OAAgB;oBACtB,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI;iBAC/F;gBACH,CAAC,CAAC,IAAI,CACT;SACF,CAAC,CAAC,CAAA;QACH,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAA;QACpE,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAA;QACvD,IAAI,MAAM,GAAe,GAAG,EAAE,GAAE,CAAC,CAAA;QACjC,OAAO,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,EAAE,CAAA;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,MAAM,KAAK,GAAG,CAAC,MAAe,EAAE,EAAE;YAChC,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE;gBAAE,KAAK,MAAM,KAAK,IAAI,MAAM;oBAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAA;QACnF,CAAC,CAAA;QACD,IAAI,YAAY,GAAG,CAAC,CAAA;QACpB,IAAI,eAAe,GAAG,CAAC,CAAA;QACvB,IAAI,UAAU,GAAqB,SAAS,CAAA;QAC5C,IAAI,OAAO,GAA8B,IAAI,CAAA;QAC7C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,IAAI,IAAI,EAAE;gBAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACzC,CAAC,EAAE,YAAY,CAAC,CAAA;QAChB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC;gBACpD,QAAQ;gBACR,KAAK,EAAE,IAAI,CAAC,SAAS;gBACrB,cAAc,EAAE,IAAI,CAAC,QAAQ;aAC9B,CAAC,CAAA;YACF,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACtB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;oBACjB,cAAc,EAAE,mBAAmB;oBACnC,eAAe,EAAE,UAAU;oBAC3B,YAAY,EAAE,YAAY;iBAC3B,CAAC,CAAA;gBACF,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAA;YAC7D,CAAC;YACD,MAAM,MAAM,GAA2B;gBACrC,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,gBAAgB;gBACrD,iFAAiF;gBACjF,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE;oBACP,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5F,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvE,OAAO,EAAE,IAAI,CAAC,cAAc;wBAC1B,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAY,CAAC;wBACvE,CAAC,CAAC,IAAI;iBACT;gBACD,UAAU,EAAE,MAAM;aACnB,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAC1C,MAAM,EACN,MAAM,EACN,CAAC,KAAK,EAAE,EAAE;gBACR,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;gBACxB,IAAI,MAAM,CAAC,OAAO;oBAAE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACjD,CAAC,EACD,MAAM,CACP,CAAA;YACD,YAAY,GAAG,MAAM,CAAC,YAAY,CAAA;YAClC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAA;YACxC,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAA;QAC1D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YACnE,OAAO;gBACL,KAAK,YAAY,kBAAkB;oBACjC,CAAC,CAAC,KAAK;oBACP,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;wBAC7B,CAAC,CAAC,kFAAkF;4BAClF,IAAI,kBAAkB,CAAC,GAAG,EAAE,WAAW,IAAI,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,yBAAyB,CAAC;wBAClG,CAAC,CAAC,IAAI,kBAAkB,CACpB,GAAG,EACH,WAAW,KAAK,YAAY,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CACxE,CAAA;YACT,OAAO,CAAC,GAAG,EAAE,CAAC,sBAAsB,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;QACxD,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,KAAK,CAAC,CAAA;YACpB,OAAO,GAAG,IAAI,CAAA;YACd,MAAM,EAAE,CAAA;YACR,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QACpF,CAAC;QACD,IAAI,IAAI,EAAE;YAAE,OAAM;QAClB,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAA;QACrB,MAAM,MAAM,GAAwB,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAC9E,2FAA2F;QAC3F,MAAM,UAAU,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;QACxE,MAAM,KAAK,GAAG;YACZ,aAAa,EAAE,YAAY;YAC3B,iBAAiB,EAAE,UAAU;YAC7B,YAAY,EAAE,YAAY,GAAG,UAAU;SACxC,CAAA;QACD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,OAAO;oBAAE,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;gBACjD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;oBACjB,cAAc,EAAE,mBAAmB;oBACnC,eAAe,EAAE,UAAU;oBAC3B,YAAY,EAAE,YAAY;iBAC3B,CAAC,CAAA;YACJ,CAAC;YACD,IAAI,OAAO;gBAAE,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;iBAC9D,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAA;gBACnC,IAAI,IAAI,CAAC,YAAY;oBAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YACxE,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YACjB,OAAM;QACR,CAAC;QACD,IAAI,OAAO;YAAE,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACjD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAA;IAC9F,CAAC;IAED,OAAO;QACL,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;gBACpC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;gBAC3B,OAAO,CAAC,oBAAqB,MAAM,CAAC,OAAO,EAAkB,CAAC,IAAI,EAAE,CAAC,CAAA;YACvE,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,GAAG,IAAI,CAAA;YACb,iGAAiG;YACjG,gDAAgD;YAChD,MAAM,OAAO,GAAG,OAAO,CAAA;YACvB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBACnC,MAAM,OAAO,CAAC,IAAI,CAAC;oBACjB,OAAO,CAAC,KAAK;oBACb,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,KAAK,EAAE,CAAC;iBACrE,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,CAAC,mBAAmB,EAAE,CAAA;YAC5B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAA;QACrE,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the Worker of `geniex-host` does with each message of the main thread (openspec change
|
|
3
|
+
* `add-geniex-runtime`, design D1), apart from the thread it runs on: `worker.ts` is the Bun entry
|
|
4
|
+
* that binds this to `self.onmessage` with the `bun:ffi` library, and the tests drive it in-process
|
|
5
|
+
* with a fake library.
|
|
6
|
+
*
|
|
7
|
+
* The library is single-threaded and `generate` blocks: the Worker handles one message at a time,
|
|
8
|
+
* and while a generation runs it reads nothing — the main thread cancels through the shared flag the
|
|
9
|
+
* generate message carries, which the token callback checks on every token.
|
|
10
|
+
*/
|
|
11
|
+
import type { GeniexGenerateResult, GeniexGenerationConfig, GeniexModelSettings, GeniexTemplateInput, LoadGeniexLibrary } from './library.js';
|
|
12
|
+
/** Main thread → Worker. */
|
|
13
|
+
export type GeniexWorkerRequest = {
|
|
14
|
+
type: 'probe';
|
|
15
|
+
libDir: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: 'create';
|
|
18
|
+
libDir: string;
|
|
19
|
+
settings: GeniexModelSettings;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'template';
|
|
22
|
+
id: number;
|
|
23
|
+
input: GeniexTemplateInput;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'generate';
|
|
26
|
+
id: number;
|
|
27
|
+
prompt: string;
|
|
28
|
+
config: GeniexGenerationConfig;
|
|
29
|
+
/** One `Int32`; non-zero asks the token callback to stop. */
|
|
30
|
+
cancel: SharedArrayBuffer;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'destroy';
|
|
33
|
+
};
|
|
34
|
+
/** Worker → main thread. */
|
|
35
|
+
export type GeniexWorkerAnswer = {
|
|
36
|
+
type: 'probed';
|
|
37
|
+
version: string | null;
|
|
38
|
+
abi: number;
|
|
39
|
+
plugins: string[];
|
|
40
|
+
devices: string[];
|
|
41
|
+
} | {
|
|
42
|
+
type: 'created';
|
|
43
|
+
vision: boolean;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'templated';
|
|
46
|
+
id: number;
|
|
47
|
+
prompt: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'token';
|
|
50
|
+
id: number;
|
|
51
|
+
text: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: 'done';
|
|
54
|
+
id: number;
|
|
55
|
+
result: GeniexGenerateResult;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'error';
|
|
58
|
+
id: number;
|
|
59
|
+
message: string;
|
|
60
|
+
code: number | null;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'destroyed';
|
|
63
|
+
}
|
|
64
|
+
/** `probe` or `create` failed: `load` — the library did not open; `call` — it refused. */
|
|
65
|
+
| {
|
|
66
|
+
type: 'failed';
|
|
67
|
+
stage: 'load' | 'call';
|
|
68
|
+
message: string;
|
|
69
|
+
code: number | null;
|
|
70
|
+
};
|
|
71
|
+
export interface GeniexWorkerDeps {
|
|
72
|
+
loadLibrary: LoadGeniexLibrary;
|
|
73
|
+
post: (answer: GeniexWorkerAnswer) => void;
|
|
74
|
+
}
|
|
75
|
+
/** One Worker's state machine: a library once loaded, a model once created. */
|
|
76
|
+
export declare function createGeniexWorkerHandler(deps: GeniexWorkerDeps): (request: GeniexWorkerRequest) => Promise<void>;
|