@atomic-chat/core 0.20.5 → 0.20.6

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.
Files changed (175) hide show
  1. package/dist/audio/args.d.ts +19 -0
  2. package/dist/audio/args.js +39 -0
  3. package/dist/audio/args.js.map +1 -0
  4. package/dist/audio/capabilities.d.ts +24 -0
  5. package/dist/audio/capabilities.js +96 -0
  6. package/dist/audio/capabilities.js.map +1 -0
  7. package/dist/audio/config.d.ts +40 -0
  8. package/dist/audio/config.js +57 -0
  9. package/dist/audio/config.js.map +1 -0
  10. package/dist/audio/errors.d.ts +23 -0
  11. package/dist/audio/errors.js +52 -0
  12. package/dist/audio/errors.js.map +1 -0
  13. package/dist/audio/gallery.d.ts +30 -0
  14. package/dist/audio/gallery.js +152 -0
  15. package/dist/audio/gallery.js.map +1 -0
  16. package/dist/audio/http.d.ts +26 -0
  17. package/dist/audio/http.js +56 -0
  18. package/dist/audio/http.js.map +1 -0
  19. package/dist/audio/idle.d.ts +22 -0
  20. package/dist/audio/idle.js +44 -0
  21. package/dist/audio/idle.js.map +1 -0
  22. package/dist/audio/index.d.ts +26 -0
  23. package/dist/audio/index.js +27 -0
  24. package/dist/audio/index.js.map +1 -0
  25. package/dist/audio/install.d.ts +57 -0
  26. package/dist/audio/install.js +196 -0
  27. package/dist/audio/install.js.map +1 -0
  28. package/dist/audio/jobs.d.ts +77 -0
  29. package/dist/audio/jobs.js +340 -0
  30. package/dist/audio/jobs.js.map +1 -0
  31. package/dist/audio/model-files.d.ts +12 -0
  32. package/dist/audio/model-files.js +42 -0
  33. package/dist/audio/model-files.js.map +1 -0
  34. package/dist/audio/output.d.ts +32 -0
  35. package/dist/audio/output.js +93 -0
  36. package/dist/audio/output.js.map +1 -0
  37. package/dist/audio/parse.d.ts +15 -0
  38. package/dist/audio/parse.js +149 -0
  39. package/dist/audio/parse.js.map +1 -0
  40. package/dist/audio/recipe.d.ts +22 -0
  41. package/dist/audio/recipe.js +92 -0
  42. package/dist/audio/recipe.js.map +1 -0
  43. package/dist/audio/request.d.ts +24 -0
  44. package/dist/audio/request.js +86 -0
  45. package/dist/audio/request.js.map +1 -0
  46. package/dist/audio/server-process.d.ts +51 -0
  47. package/dist/audio/server-process.js +202 -0
  48. package/dist/audio/server-process.js.map +1 -0
  49. package/dist/audio/service.d.ts +107 -0
  50. package/dist/audio/service.js +402 -0
  51. package/dist/audio/service.js.map +1 -0
  52. package/dist/audio/session.d.ts +73 -0
  53. package/dist/audio/session.js +216 -0
  54. package/dist/audio/session.js.map +1 -0
  55. package/dist/audio/state.d.ts +68 -0
  56. package/dist/audio/state.js +88 -0
  57. package/dist/audio/state.js.map +1 -0
  58. package/dist/audio/types.d.ts +52 -0
  59. package/dist/audio/types.js +8 -0
  60. package/dist/audio/types.js.map +1 -0
  61. package/dist/audio/wav.d.ts +22 -0
  62. package/dist/audio/wav.js +56 -0
  63. package/dist/audio/wav.js.map +1 -0
  64. package/dist/audio/wiring.d.ts +31 -0
  65. package/dist/audio/wiring.js +41 -0
  66. package/dist/audio/wiring.js.map +1 -0
  67. package/dist/backend/install/service.js +4 -2
  68. package/dist/backend/install/service.js.map +1 -1
  69. package/dist/cli/bin.js +0 -0
  70. package/dist/cli/main.d.ts +1 -1
  71. package/dist/client/control-client.d.ts +21 -1
  72. package/dist/client/control-client.js +50 -0
  73. package/dist/client/control-client.js.map +1 -1
  74. package/dist/client/index.d.ts +1 -0
  75. package/dist/client/index.js +1 -0
  76. package/dist/client/index.js.map +1 -1
  77. package/dist/client/model-catalog.d.ts +40 -0
  78. package/dist/client/model-catalog.js +149 -0
  79. package/dist/client/model-catalog.js.map +1 -0
  80. package/dist/config/paths.d.ts +21 -0
  81. package/dist/config/paths.js +12 -0
  82. package/dist/config/paths.js.map +1 -1
  83. package/dist/contracts/audio.d.ts +290 -0
  84. package/dist/contracts/audio.js +24 -0
  85. package/dist/contracts/audio.js.map +1 -0
  86. package/dist/contracts/embedding.js +1 -0
  87. package/dist/contracts/embedding.js.map +1 -1
  88. package/dist/contracts/engine-builds.d.ts +5 -4
  89. package/dist/contracts/engine-builds.js +10 -2
  90. package/dist/contracts/engine-builds.js.map +1 -1
  91. package/dist/contracts/engines.d.ts +1 -1
  92. package/dist/contracts/engines.js +2 -0
  93. package/dist/contracts/engines.js.map +1 -1
  94. package/dist/contracts/errors.d.ts +7 -1
  95. package/dist/contracts/errors.js +29 -0
  96. package/dist/contracts/errors.js.map +1 -1
  97. package/dist/contracts/events.d.ts +10 -0
  98. package/dist/contracts/index.d.ts +1 -0
  99. package/dist/contracts/index.js +1 -0
  100. package/dist/contracts/index.js.map +1 -1
  101. package/dist/core/atomic-core.d.ts +6 -1
  102. package/dist/core/atomic-core.js +7 -1
  103. package/dist/core/atomic-core.js.map +1 -1
  104. package/dist/core/create.js +30 -5
  105. package/dist/core/create.js.map +1 -1
  106. package/dist/core/gpu-residency.d.ts +8 -2
  107. package/dist/core/gpu-residency.js +9 -1
  108. package/dist/core/gpu-residency.js.map +1 -1
  109. package/dist/core/types.d.ts +3 -0
  110. package/dist/core/types.js.map +1 -1
  111. package/dist/diffusion/install.d.ts +6 -3
  112. package/dist/diffusion/install.js +5 -4
  113. package/dist/diffusion/install.js.map +1 -1
  114. package/dist/embedding/index.js +1 -0
  115. package/dist/embedding/index.js.map +1 -1
  116. package/dist/engine-builds/engines.d.ts +5 -3
  117. package/dist/engine-builds/engines.js +71 -11
  118. package/dist/engine-builds/engines.js.map +1 -1
  119. package/dist/engine-builds/index.d.ts +3 -2
  120. package/dist/engine-builds/index.js +3 -2
  121. package/dist/engine-builds/index.js.map +1 -1
  122. package/dist/engine-builds/manifest.d.ts +52 -5
  123. package/dist/engine-builds/manifest.js +60 -9
  124. package/dist/engine-builds/manifest.js.map +1 -1
  125. package/dist/engine-builds/order.d.ts +5 -0
  126. package/dist/engine-builds/order.js +11 -0
  127. package/dist/engine-builds/order.js.map +1 -1
  128. package/dist/engine-builds/select.d.ts +28 -11
  129. package/dist/engine-builds/select.js +50 -16
  130. package/dist/engine-builds/select.js.map +1 -1
  131. package/dist/engine-builds/service.d.ts +14 -8
  132. package/dist/engine-builds/service.js +10 -7
  133. package/dist/engine-builds/service.js.map +1 -1
  134. package/dist/engines/service.d.ts +2 -2
  135. package/dist/engines/service.js +2 -2
  136. package/dist/lock/process-journal.d.ts +3 -3
  137. package/dist/models/compatibility/rules-baseline.js +1 -0
  138. package/dist/models/compatibility/rules-baseline.js.map +1 -1
  139. package/dist/models/compatibility/rules.js +1 -0
  140. package/dist/models/compatibility/rules.js.map +1 -1
  141. package/dist/models/hf.d.ts +3 -0
  142. package/dist/models/hf.js +11 -4
  143. package/dist/models/hf.js.map +1 -1
  144. package/dist/server/control/index.d.ts +1 -1
  145. package/dist/server/control/router.js +2 -0
  146. package/dist/server/control/router.js.map +1 -1
  147. package/dist/server/control/routes/audio.d.ts +15 -0
  148. package/dist/server/control/routes/audio.js +59 -0
  149. package/dist/server/control/routes/audio.js.map +1 -0
  150. package/dist/server/control/types.d.ts +25 -1
  151. package/dist/server/control/types.js.map +1 -1
  152. package/dist/server/http.js +2 -0
  153. package/dist/server/http.js.map +1 -1
  154. package/dist/server/public/audio-speech-params.d.ts +47 -0
  155. package/dist/server/public/audio-speech-params.js +177 -0
  156. package/dist/server/public/audio-speech-params.js.map +1 -0
  157. package/dist/server/public/audio-speech.d.ts +14 -0
  158. package/dist/server/public/audio-speech.js +118 -0
  159. package/dist/server/public/audio-speech.js.map +1 -0
  160. package/dist/server/public/index.d.ts +1 -1
  161. package/dist/server/public/index.js +7 -0
  162. package/dist/server/public/index.js.map +1 -1
  163. package/dist/server/public/trace.js +2 -0
  164. package/dist/server/public/trace.js.map +1 -1
  165. package/dist/server/public/types.d.ts +29 -1
  166. package/dist/telemetry/reports.d.ts +12 -0
  167. package/dist/telemetry/reports.js +38 -0
  168. package/dist/telemetry/reports.js.map +1 -1
  169. package/dist/telemetry/subscribe.d.ts +3 -3
  170. package/dist/telemetry/subscribe.js +8 -3
  171. package/dist/telemetry/subscribe.js.map +1 -1
  172. package/dist/telemetry/types.d.ts +1 -1
  173. package/dist/version.d.ts +1 -1
  174. package/dist/version.js +1 -1
  175. package/package.json +5 -1
@@ -0,0 +1,402 @@
1
+ /**
2
+ * The audio-generation service: one resident `audiocpp_server` for the loaded model, jobs against it,
3
+ * the gallery and the model files, and what the engine-builds module and GPU residency need of it.
4
+ * The shape of image generation's `DiffusionService`, much smaller.
5
+ */
6
+ import { mkdir, stat } from 'node:fs/promises';
7
+ import { AsyncMutex, samePath } from '../diffusion/index.js';
8
+ import { resolveAudioBackend } from './args.js';
9
+ import { resolveModelPath, taskForMode } from './config.js';
10
+ import { audioError, audioIoError } from './errors.js';
11
+ import { AudioGallery } from './gallery.js';
12
+ import { createAudioHttpClient } from './http.js';
13
+ import { startAudioIdleTask } from './idle.js';
14
+ import { listInstalledAudioBuilds, readAudioInstallRecord } from './install.js';
15
+ import { cancelAudioJob, DEFAULT_AUDIO_JOB_TIMINGS, drawAudioSeed, readVoiceRefFile, runAudioJob, startAudioJob, } from './jobs.js';
16
+ import { audioModelFilePath, deleteAudioModelFile, listAudioModelFiles } from './model-files.js';
17
+ import { spawnAudioServer } from './server-process.js';
18
+ import { activateAudioInstall, audioCapabilities, audioGpuCards, buildAudioStatus, emitAudioState, failLoad, loadFromSpec, shutdownAudioSession, takeDownSession, unloadSession, } from './session.js';
19
+ import { AudioState, isTerminalAudioJobState } from './state.js';
20
+ import { DEFAULT_STARTUP_TIMEOUT_SECS } from './types.js';
21
+ const WHAT = {
22
+ speech: 'speech',
23
+ music: 'music',
24
+ effects: 'a sound effect',
25
+ };
26
+ const exists = (path) => stat(path).then((s) => s.isFile() || s.isDirectory(), () => false);
27
+ async function ensureDir(dir, message) {
28
+ await mkdir(dir, { recursive: true }).catch((error) => {
29
+ throw audioIoError(message, error);
30
+ });
31
+ }
32
+ export class AudioService {
33
+ state;
34
+ deps;
35
+ platform;
36
+ env;
37
+ idleTickMs;
38
+ idle;
39
+ /** Stops a load still waiting for its model when the model is unloaded or the core shuts down. */
40
+ loading;
41
+ /** GPU claims in flight, a load's or a respawn's; an unload aborts them rather than wait behind them. */
42
+ claims = new Set();
43
+ /** Unloads asked for and not finished: a GPU claim that starts meanwhile gives up at once. */
44
+ unloadRequests = 0;
45
+ constructor(options) {
46
+ const now = options.now ?? Date.now;
47
+ const platform = options.platform ?? process.platform;
48
+ const http = options.http ?? createAudioHttpClient();
49
+ const log = options.log;
50
+ this.platform = platform;
51
+ this.env = options.env ?? process.env;
52
+ this.idleTickMs = options.idleTickMs;
53
+ this.state = new AudioState(options.paths, now);
54
+ const journal = options.journal;
55
+ const spawn = options.spawn ??
56
+ ((spec, signal) => spawnAudioServer(spec, {
57
+ http,
58
+ runDir: options.paths.runDir,
59
+ tmpDir: options.paths.tmpDir,
60
+ platform,
61
+ env: this.env,
62
+ log,
63
+ ...(options.backendOutput ? { backendOutput: options.backendOutput } : {}),
64
+ ...(signal ? { signal } : {}),
65
+ ...(journal
66
+ ? {
67
+ onSpawned: (pid, port, exe) => journal.add(pid, port, exe, spec.modelId),
68
+ onGone: (pid) => journal.remove(pid),
69
+ }
70
+ : {}),
71
+ }));
72
+ this.deps = {
73
+ state: this.state,
74
+ emit: options.emit,
75
+ log,
76
+ platform,
77
+ now,
78
+ sleep: options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
79
+ spawn,
80
+ ...(journal ? { onServerGone: (pid) => journal.remove(pid) } : {}),
81
+ ...(options.claimGpu ? { claimGpu: this.claimGpu(options.claimGpu) } : {}),
82
+ http,
83
+ gallery: new AudioGallery((level, msg) => log(level, msg)),
84
+ loadLock: new AsyncMutex(),
85
+ timings: { ...DEFAULT_AUDIO_JOB_TIMINGS, ...options.timings },
86
+ drawSeed: options.drawSeed ?? drawAudioSeed,
87
+ readSource: readVoiceRefFile,
88
+ };
89
+ }
90
+ /** Arm the idle timer. */
91
+ start() {
92
+ if (this.idle)
93
+ return;
94
+ this.idle = startAudioIdleTask({
95
+ state: this.state,
96
+ loadLock: this.deps.loadLock,
97
+ unload: (reason) => unloadSession(this.deps, reason),
98
+ log: this.deps.log,
99
+ ...(this.idleTickMs !== undefined ? { tickMs: this.idleTickMs } : {}),
100
+ });
101
+ }
102
+ // --- configuration and status ------------------------------------------------------------------
103
+ /** Optional settings: the output folder (`null` restores `<data>/audios`) and the idle unload. */
104
+ async config(config) {
105
+ if (config.outputDir !== undefined) {
106
+ const chosen = config.outputDir?.trim() ?? '';
107
+ if (chosen !== '')
108
+ await ensureDir(chosen, 'Could not create the output folder.');
109
+ this.state.outputDirOverride = chosen === '' ? null : chosen;
110
+ }
111
+ if (config.idleUnloadSecs !== undefined) {
112
+ this.state.idleUnloadSecs = config.idleUnloadSecs;
113
+ // Re-arm the idle timer with the new interval.
114
+ if (this.state.spec && this.state.activeJobId === undefined)
115
+ this.state.touchIdle();
116
+ }
117
+ await emitAudioState(this.deps, 'config');
118
+ return buildAudioStatus(this.deps);
119
+ }
120
+ status() {
121
+ return buildAudioStatus(this.deps);
122
+ }
123
+ /** The gallery folder; an empty path restores `<data>/audios`. */
124
+ async setOutputDir(path) {
125
+ const trimmed = path.trim();
126
+ if (trimmed !== '')
127
+ await ensureDir(trimmed, 'Could not create the output folder.');
128
+ this.state.outputDirOverride = trimmed === '' ? null : trimmed;
129
+ await emitAudioState(this.deps, 'output-dir');
130
+ return buildAudioStatus(this.deps);
131
+ }
132
+ // --- engine builds and GPU residency -----------------------------------------------------------
133
+ /**
134
+ * What the engine-builds module needs of audio generation: the load lock, the build directories in
135
+ * use, and the activation of a new build — cancel the running job, unload a model whose build the
136
+ * new one replaces (`engine-updated`), report the install.
137
+ */
138
+ engineHost() {
139
+ return {
140
+ exclusive: (fn) => this.deps.loadLock.run(fn),
141
+ inUse: async () => {
142
+ const dirs = [];
143
+ // A resident server, a spec kept after an idle unload or a crash, a server still exiting.
144
+ for (const dir of [
145
+ this.state.session?.spec.binaryDir,
146
+ this.state.spec?.binaryDir,
147
+ this.state.stopping?.spec.binaryDir,
148
+ ])
149
+ if (dir !== undefined && !dirs.includes(dir))
150
+ dirs.push(dir);
151
+ return dirs;
152
+ },
153
+ activate: async (dir, replaced) => {
154
+ const record = await readAudioInstallRecord(dir);
155
+ if (!record)
156
+ throw audioError('INTERNAL', 'The new audio engine build has no install record.', dir);
157
+ if (this.state.activeJobId !== undefined)
158
+ await cancelAudioJob(this.deps, this.state.activeJobId).catch(() => undefined);
159
+ const spec = this.state.spec;
160
+ // The same directory with a fresh tree: what runs from it is the old binary.
161
+ if (replaced && spec && (await samePath(spec.binaryDir, dir, this.platform)))
162
+ await unloadSession(this.deps, 'engine-updated');
163
+ else
164
+ await activateAudioInstall(this.deps, record);
165
+ await emitAudioState(this.deps, 'install');
166
+ },
167
+ // The `install` part of the status changed.
168
+ changed: (reason) => emitAudioState(this.deps, reason),
169
+ };
170
+ }
171
+ /**
172
+ * The GPU the resident, stopping or starting `audiocpp_server` holds, for core's residency rule. The
173
+ * resident or starting one is `busy` while a job runs on it that nobody asked to cancel: residency
174
+ * then refuses a chat load (`GPU_BUSY`) instead of stopping the clip.
175
+ */
176
+ gpuOccupancy() {
177
+ const held = (spec, state, working) => ({
178
+ model_id: spec.modelId,
179
+ cards: audioGpuCards(spec),
180
+ auxiliary: false,
181
+ state,
182
+ ...(working ?? {}),
183
+ });
184
+ const out = [];
185
+ const { session, stopping, starting } = this.state;
186
+ if (session && session.server.exitStatus() === undefined)
187
+ out.push(held(session.spec, 'ready', this.working(session.spec)));
188
+ if (stopping)
189
+ out.push(held(stopping.spec, 'stopping'));
190
+ if (starting)
191
+ out.push(held(starting, 'loading', this.working(starting)));
192
+ return out;
193
+ }
194
+ /** What the active job is making on `spec`; none when no job is live. */
195
+ working(spec) {
196
+ const id = this.state.activeJobId;
197
+ const record = id === undefined ? undefined : this.state.record(id);
198
+ if (!record || record.cancel.requested || isTerminalAudioJobState(record.job.state))
199
+ return undefined;
200
+ return {
201
+ busy: `${spec.displayName} is generating ${WHAT[spec.mode]}`,
202
+ remedy: 'Wait for the clip to finish, or stop it, then try again.',
203
+ };
204
+ }
205
+ /** The session's claim hook over core's: abortable by an unload, whatever signal the caller had. */
206
+ claimGpu(hook) {
207
+ return async (spec, signal, granted) => {
208
+ const controller = new AbortController();
209
+ const forward = () => controller.abort();
210
+ if (signal?.aborted || this.unloadRequests > 0)
211
+ controller.abort();
212
+ signal?.addEventListener('abort', forward, { once: true });
213
+ this.claims.add(controller);
214
+ try {
215
+ await hook({ model_id: spec.modelId, cards: audioGpuCards(spec), auxiliary: false }, controller.signal, granted);
216
+ }
217
+ finally {
218
+ this.claims.delete(controller);
219
+ signal?.removeEventListener('abort', forward);
220
+ }
221
+ };
222
+ }
223
+ // --- model files ---------------------------------------------------------------------------------
224
+ listModelFiles() {
225
+ return listAudioModelFiles(this.state.paths.modelsDir);
226
+ }
227
+ /** Delete a file named relative to `<data>/audio/models`; the loaded model's own file is refused. */
228
+ async deleteModelFile(relativePath) {
229
+ const root = this.state.paths.modelsDir;
230
+ const path = await audioModelFilePath(root, relativePath, this.platform);
231
+ const spec = this.state.spec;
232
+ if (spec && (await samePath(spec.modelPath, path, this.platform)))
233
+ throw audioError('BACKEND_IN_USE', 'That file belongs to the loaded audio model. Unload it first.');
234
+ await deleteAudioModelFile(root, path, this.platform);
235
+ }
236
+ // --- session -------------------------------------------------------------------------------------
237
+ /** Answers once the server serves the model. One load at a time; a load replaces the resident model. */
238
+ async loadModel(request) {
239
+ const { state } = this;
240
+ return this.deps.loadLock.run(async () => {
241
+ // First, before any await: an unload from here on reaches this load, wherever it is waiting.
242
+ const loading = new AbortController();
243
+ this.loading = loading;
244
+ try {
245
+ if (state.closing)
246
+ throw audioError('ENGINE_CRASHED', 'The audio engine is shutting down.');
247
+ if (state.activeJobId !== undefined)
248
+ await cancelAudioJob(this.deps, state.activeJobId).catch(() => undefined);
249
+ await takeDownSession(this.deps);
250
+ state.spec = undefined;
251
+ state.capabilities = undefined;
252
+ let spec;
253
+ try {
254
+ spec = await this.specFor(request);
255
+ }
256
+ catch (error) {
257
+ return await failLoad(this.deps, error, 'load-blocked');
258
+ }
259
+ return await loadFromSpec(this.deps, spec, 'load', loading.signal);
260
+ }
261
+ finally {
262
+ if (this.loading === loading)
263
+ this.loading = undefined;
264
+ }
265
+ });
266
+ }
267
+ /** What a load runs: the newest installed build, the model file checked. */
268
+ async specFor(request) {
269
+ if (request.task !== taskForMode(request.mode))
270
+ throw audioError('INVALID_REQUEST', `A ${request.mode} model is served as audio.cpp's ${taskForMode(request.mode)} task.`, `task: ${request.task}`);
271
+ const modelPath = resolveModelPath(request.file, this.state.paths.modelsDir, this.platform);
272
+ if (!(await exists(modelPath))) {
273
+ const name = modelPath.split(/[\\/]/).pop() || modelPath;
274
+ throw audioError('MODEL_MISSING', `${name} is missing. Download the model again.`, modelPath);
275
+ }
276
+ const record = (await listInstalledAudioBuilds(this.state.paths.backendsDir, this.platform))[0];
277
+ if (!record)
278
+ throw audioError('ENGINE_MISSING', 'The audio engine is not installed.');
279
+ return {
280
+ binaryDir: record.dir,
281
+ backend: resolveAudioBackend(record.backend, this.env),
282
+ buildBackend: record.backend,
283
+ backendId: record.backendId,
284
+ tag: record.tag,
285
+ modelId: request.modelId,
286
+ displayName: request.displayName,
287
+ mode: request.mode,
288
+ family: request.family,
289
+ task: request.task,
290
+ modelPath,
291
+ ...(request.loadOptions ? { loadOptions: { ...request.loadOptions } } : {}),
292
+ ...(request.sessionOptions ? { sessionOptions: { ...request.sessionOptions } } : {}),
293
+ ...(request.defaultRequestOptions
294
+ ? { defaultRequestOptions: { ...request.defaultRequestOptions } }
295
+ : {}),
296
+ ...(request.defaultVoice !== undefined ? { defaultVoice: request.defaultVoice } : {}),
297
+ ...(request.threads !== undefined ? { threads: request.threads } : {}),
298
+ startupTimeoutMs: (request.startupTimeoutSecs !== undefined && request.startupTimeoutSecs > 0
299
+ ? request.startupTimeoutSecs
300
+ : DEFAULT_STARTUP_TIMEOUT_SECS) * 1000,
301
+ };
302
+ }
303
+ async unloadModel() {
304
+ this.unloadRequests += 1;
305
+ let counted = true;
306
+ const done = () => {
307
+ if (!counted)
308
+ return;
309
+ counted = false;
310
+ this.unloadRequests -= 1;
311
+ };
312
+ this.loading?.abort();
313
+ for (const claim of this.claims)
314
+ claim.abort();
315
+ try {
316
+ await this.deps.loadLock.run(async () => {
317
+ try {
318
+ if (this.state.activeJobId !== undefined)
319
+ await cancelAudioJob(this.deps, this.state.activeJobId).catch(() => undefined);
320
+ await unloadSession(this.deps, 'unload');
321
+ // A server taken down outside the lock (a job's crash or cancel) is waited for as well.
322
+ await this.state.stopping?.done;
323
+ }
324
+ finally {
325
+ // Still inside the lock: a load queued behind this unload is never taken for superseded.
326
+ done();
327
+ }
328
+ });
329
+ }
330
+ finally {
331
+ done();
332
+ }
333
+ }
334
+ /** Reset the idle-unload deadline without generating. */
335
+ touchIdle() {
336
+ if (this.state.activeJobId === undefined && this.state.spec)
337
+ this.state.touchIdle();
338
+ }
339
+ capabilities() {
340
+ return audioCapabilities(this.state);
341
+ }
342
+ // --- jobs ----------------------------------------------------------------------------------------
343
+ /** Start a job; answers it at once, its phases and outcome arrive as `audio:job` events. */
344
+ async generate(mode, request) {
345
+ return (await startAudioJob(this.deps, mode, request)).job;
346
+ }
347
+ /** Run one job to completion and answer the clip. */
348
+ runJob(mode, request) {
349
+ return runAudioJob(this.deps, mode, request);
350
+ }
351
+ /**
352
+ * What `POST /v1/audio/speech` needs: the loaded model and what it makes, and a speech job started
353
+ * the way `runJob` starts one — same validation, events, gallery and idle timer — but answered with
354
+ * its id at once, so a client that hangs up can have it cancelled.
355
+ */
356
+ speechBackend() {
357
+ return {
358
+ loaded: () => {
359
+ const spec = this.state.spec;
360
+ return spec ? { modelId: spec.modelId, displayName: spec.displayName, mode: spec.mode } : undefined;
361
+ },
362
+ start: async (request) => {
363
+ const { job, done } = await startAudioJob(this.deps, 'speech', request);
364
+ return { id: job.id, done };
365
+ },
366
+ cancel: (jobId) => cancelAudioJob(this.deps, jobId),
367
+ };
368
+ }
369
+ getJob(id) {
370
+ return this.state.job(id) ?? null;
371
+ }
372
+ cancelJob(id) {
373
+ return cancelAudioJob(this.deps, id);
374
+ }
375
+ // --- gallery -------------------------------------------------------------------------------------
376
+ gallery(options) {
377
+ return this.deps.gallery.list(this.state.outputDir(), options);
378
+ }
379
+ deleteGalleryItem(id) {
380
+ return this.deps.gallery.delete(this.state.outputDir(), id);
381
+ }
382
+ // --- lifecycle -----------------------------------------------------------------------------------
383
+ /** Owner exit: an `audiocpp_server` must not outlive the core. No events, a short grace. */
384
+ async shutdown() {
385
+ this.state.closing = true;
386
+ this.idle?.stop();
387
+ this.idle = undefined;
388
+ this.loading?.abort();
389
+ for (const claim of this.claims)
390
+ claim.abort();
391
+ const id = this.state.activeJobId;
392
+ if (id !== undefined) {
393
+ const record = this.state.record(id);
394
+ if (record) {
395
+ record.cancel.requested = true;
396
+ record.cancel.abort.abort();
397
+ }
398
+ }
399
+ await shutdownAudioSession(this.deps);
400
+ }
401
+ }
402
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audio/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Session lifecycle: bringing `audiocpp_server` up from a spec, tearing it down, and describing the
3
+ * result as the status the client reads. Every state change here emits `audio:state`. The shape of
4
+ * image generation's `session.ts`, without its offload and CPU fallbacks.
5
+ */
6
+ import type { AudioBackendInstallRecord, AudioCapabilities, AudioEngineInstall, AudioErrorBody, AudioStatus, CoreEvents, LoadedAudioModel } from '../contracts/index.js';
7
+ import type { GpuCards } from '../runtime/shared/index.js';
8
+ import type { AudioState } from './state.js';
9
+ import type { AudioServerHandle, AudioServerSpec } from './types.js';
10
+ /** CUDA needs a moment after another engine's process dies before the driver reports the VRAM as free. */
11
+ export declare const GPU_SETTLE_MS = 500;
12
+ /** Owner exit: a short grace, then the kill. */
13
+ export declare const SHUTDOWN_GRACE_MS = 2000;
14
+ export type AudioEventName = 'audio:state' | 'audio:job' | 'audio:error';
15
+ export type AudioEmitter = <K extends AudioEventName>(name: K, payload: CoreEvents[K]) => void;
16
+ export type AudioLogger = (level: 'info' | 'warn' | 'debug', msg: string) => void;
17
+ export interface AudioSessionDeps {
18
+ state: AudioState;
19
+ emit: AudioEmitter;
20
+ log: AudioLogger;
21
+ platform: NodeJS.Platform;
22
+ now: () => number;
23
+ sleep: (ms: number) => Promise<void>;
24
+ /** Bring a server up for `spec`; rejects with the server dead. */
25
+ spawn: (spec: AudioServerSpec, signal?: AbortSignal) => Promise<AudioServerHandle>;
26
+ /** The child is gone (or was never journalled); forget it. */
27
+ onServerGone?: (pid: number) => Promise<void>;
28
+ /**
29
+ * Core's GPU residency: asked before every spawn — a load and a respawn alike — to free the GPU of
30
+ * the other engines. Rejects (`GPU_BUSY`, a cancel) fail the load.
31
+ */
32
+ claimGpu?: (spec: AudioServerSpec, signal?: AbortSignal, granted?: () => void) => Promise<void>;
33
+ }
34
+ export declare function modelNotLoadedError(): import("../contracts/errors.js").AtomicCoreError;
35
+ /** Which GPUs an `audiocpp_server` holds: every card on a device backend, none on the CPU backend. */
36
+ export declare function audioGpuCards(spec: Pick<AudioServerSpec, 'backend'>): GpuCards;
37
+ /** The install the status reports: the resident spec's tree when there is one, otherwise the newest. */
38
+ export declare function currentAudioInstall(deps: Pick<AudioSessionDeps, 'state' | 'platform'>): Promise<AudioEngineInstall>;
39
+ /** Snapshot for `status` and the `state` event. */
40
+ export declare function buildAudioStatus(deps: Pick<AudioSessionDeps, 'state' | 'platform'>): Promise<AudioStatus>;
41
+ export declare function emitAudioState(deps: AudioSessionDeps, reason: string): Promise<void>;
42
+ export declare function emitAudioError(deps: Pick<AudioSessionDeps, 'emit'>, jobId: string | undefined, error: AudioErrorBody): void;
43
+ /** What the loaded model takes, as its server declared it when it last came up. */
44
+ export declare function audioCapabilities(state: AudioState): AudioCapabilities;
45
+ /**
46
+ * A load failure everywhere it is seen: the model state, the `state` event and the `error` event. A
47
+ * load that `signal` stopped (an unload, a shutdown, a cancelled job's respawn) is no failure: the
48
+ * model is `unloaded` and the error is `CANCELLED`, with no `error` event.
49
+ */
50
+ export declare function failLoad(deps: AudioSessionDeps, raw: unknown, reason: string, signal?: AbortSignal): Promise<never>;
51
+ /**
52
+ * Spawn the server for `spec` and make it the resident session. The caller holds the load lock, and
53
+ * any previous session is already gone — or still exiting after a cancel or a crash outside the lock,
54
+ * which is awaited before the claim and the spawn so two servers of this module never share the GPU.
55
+ */
56
+ export declare function loadFromSpec(deps: AudioSessionDeps, spec: AudioServerSpec, reason: string, signal?: AbortSignal): Promise<LoadedAudioModel>;
57
+ /**
58
+ * Take the session out of the state and terminate it. Whether one was running. Touches neither the
59
+ * spec nor the model state: callers decide what the teardown means.
60
+ */
61
+ export declare function takeDownSession(deps: AudioSessionDeps, graceMs?: number): Promise<boolean>;
62
+ /** Explicit unload: stop the server, forget the spec, report `unloaded`. */
63
+ export declare function unloadSession(deps: AudioSessionDeps, reason: string): Promise<void>;
64
+ /**
65
+ * A new engine build is active: a resident server, or a spec kept after a cancel or a crash, that
66
+ * runs from another tree is unloaded, so no job respawns the old binary. The caller holds the load
67
+ * lock and has cancelled any running job.
68
+ */
69
+ export declare function activateAudioInstall(deps: AudioSessionDeps, record: AudioBackendInstallRecord): Promise<void>;
70
+ /** The server was stopped but the spec stays: the next job respawns it. */
71
+ export declare function stopKeepingSpec(deps: AudioSessionDeps, reason: string, error?: AudioErrorBody): Promise<void>;
72
+ /** Owner exit: no events, no waiting beyond a short grace. */
73
+ export declare function shutdownAudioSession(deps: AudioSessionDeps): Promise<void>;