@atomic-chat/core 0.20.5 → 0.20.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.
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 +344 -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 +404 -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 +228 -0
  54. package/dist/audio/session.js.map +1 -0
  55. package/dist/audio/state.d.ts +70 -0
  56. package/dist/audio/state.js +90 -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,56 @@
1
+ /**
2
+ * The HTTP the audio module needs against `audiocpp_server`: a GET or a JSON POST with a deadline and
3
+ * an abort signal, status, content type and the body as bytes back (a speech answer is a WAV, a task
4
+ * answer a JSON document that can run past 100 MB for a long song). Over the raw-socket client rather
5
+ * than the global `fetch`, which in the Bun-compiled binary honours `HTTP_PROXY` even for loopback
6
+ * (ADR 2026-09-15-proxied-downloads-use-a-raw-socket-client), as image generation does.
7
+ */
8
+ import { createPolicyFetch } from '../downloads/index.js';
9
+ /** Thrown when the deadline, not the caller, ended the exchange. */
10
+ export class AudioTimeoutError extends Error {
11
+ constructor(timeoutMs) {
12
+ super(`audiocpp_server did not answer within ${timeoutMs} ms`);
13
+ this.name = 'AudioTimeoutError';
14
+ }
15
+ }
16
+ /** One request with a deadline that covers the whole exchange, body included. */
17
+ async function exchange(fetchImpl, url, init, options) {
18
+ const controller = new AbortController();
19
+ let timedOut = false;
20
+ const timer = setTimeout(() => {
21
+ timedOut = true;
22
+ controller.abort();
23
+ }, options.timeoutMs);
24
+ const forward = () => controller.abort();
25
+ if (options.signal?.aborted)
26
+ controller.abort();
27
+ options.signal?.addEventListener('abort', forward, { once: true });
28
+ try {
29
+ const response = await fetchImpl(url, { ...init, signal: controller.signal });
30
+ const body = Buffer.from(await response.arrayBuffer());
31
+ return { status: response.status, contentType: response.headers.get('content-type') ?? '', body };
32
+ }
33
+ catch (error) {
34
+ if (timedOut)
35
+ throw new AudioTimeoutError(options.timeoutMs);
36
+ throw error;
37
+ }
38
+ finally {
39
+ clearTimeout(timer);
40
+ options.signal?.removeEventListener('abort', forward);
41
+ }
42
+ }
43
+ export function createAudioHttpClient(fetchImpl = createPolicyFetch({})) {
44
+ return {
45
+ get: (url, options) => exchange(fetchImpl, url, { method: 'GET' }, options),
46
+ post: (url, json, options) => {
47
+ const body = JSON.stringify(json);
48
+ const headers = {
49
+ 'content-type': 'application/json',
50
+ 'content-length': String(Buffer.byteLength(body)),
51
+ };
52
+ return exchange(fetchImpl, url, { method: 'POST', headers, body }, options);
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/audio/http.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAmBzD,oEAAoE;AACpE,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IAC1C,YAAY,SAAiB;QAC3B,KAAK,CAAC,yCAAyC,SAAS,KAAK,CAAC,CAAA;QAC9D,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAA;IACjC,CAAC;CACF;AAED,iFAAiF;AACjF,KAAK,UAAU,QAAQ,CACrB,SAAuB,EACvB,GAAW,EACX,IAAiB,EACjB,OAA4B;IAE5B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC5B,QAAQ,GAAG,IAAI,CAAA;QACf,UAAU,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;IACrB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACxC,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;QAAE,UAAU,CAAC,KAAK,EAAE,CAAA;IAC/C,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAClE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;QAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;QACtD,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAA;IACnG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,QAAQ;YAAE,MAAM,IAAI,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QAC5D,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAA;QACnB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACvD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,YAA0B,iBAAiB,CAAC,EAAE,CAAC;IACnF,OAAO;QACL,GAAG,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,CAAC;QAC3E,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,OAAO,GAAG;gBACd,cAAc,EAAE,kBAAkB;gBAClC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;aAClD,CAAA;YACD,OAAO,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;QAC7E,CAAC;KACF,CAAA;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Unload the audio model after `idleUnloadSecs` without a job. The deadline is re-armed by every job
3
+ * that ends and by `touchIdle`. A tick, never a wait behind a load (image generation's `idle.ts`).
4
+ */
5
+ import type { AsyncMutex } from '../diffusion/index.js';
6
+ import type { AudioState } from './state.js';
7
+ /** How often the idle task checks the deadline. */
8
+ export declare const IDLE_TICK_MS = 30000;
9
+ export interface AudioIdleDeps {
10
+ state: AudioState;
11
+ loadLock: AsyncMutex;
12
+ /** Unload the resident model; called with the load lock held. */
13
+ unload: (reason: string) => Promise<void>;
14
+ log: (level: 'info' | 'warn', msg: string) => void;
15
+ tickMs?: number;
16
+ }
17
+ /** One look at the deadline: whether an unload was started. */
18
+ export declare function audioIdleTick(deps: AudioIdleDeps): Promise<boolean>;
19
+ /** Start the ticking; the timer never keeps the process alive. */
20
+ export declare function startAudioIdleTask(deps: AudioIdleDeps): {
21
+ stop(): void;
22
+ };
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Unload the audio model after `idleUnloadSecs` without a job. The deadline is re-armed by every job
3
+ * that ends and by `touchIdle`. A tick, never a wait behind a load (image generation's `idle.ts`).
4
+ */
5
+ /** How often the idle task checks the deadline. */
6
+ export const IDLE_TICK_MS = 30_000;
7
+ /** One look at the deadline: whether an unload was started. */
8
+ export async function audioIdleTick(deps) {
9
+ const { state } = deps;
10
+ if (!state.idleExpired() || state.activeJobId !== undefined)
11
+ return false;
12
+ const release = deps.loadLock.tryAcquire();
13
+ if (!release)
14
+ return false;
15
+ try {
16
+ if (!state.spec) {
17
+ state.clearIdle();
18
+ return false;
19
+ }
20
+ deps.log('info', 'unloading the audio model after idling');
21
+ await deps.unload('idle');
22
+ return true;
23
+ }
24
+ catch (error) {
25
+ deps.log('warn', `idle unload failed: ${error instanceof Error ? error.message : String(error)}`);
26
+ return false;
27
+ }
28
+ finally {
29
+ release();
30
+ }
31
+ }
32
+ /** Start the ticking; the timer never keeps the process alive. */
33
+ export function startAudioIdleTask(deps) {
34
+ let running = false;
35
+ const timer = setInterval(() => {
36
+ if (running)
37
+ return;
38
+ running = true;
39
+ void audioIdleTick(deps).finally(() => (running = false));
40
+ }, deps.tickMs ?? IDLE_TICK_MS);
41
+ timer.unref();
42
+ return { stop: () => clearInterval(timer) };
43
+ }
44
+ //# sourceMappingURL=idle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idle.js","sourceRoot":"","sources":["../../src/audio/idle.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,mDAAmD;AACnD,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAA;AAWlC,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAmB;IACrD,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAA;IACtB,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAA;IAC1C,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,IAAI,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,CAAC,SAAS,EAAE,CAAA;YACjB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,CAAA;QAC1D,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACjG,OAAO,KAAK,CAAA;IACd,CAAC;YAAS,CAAC;QACT,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,kBAAkB,CAAC,IAAmB;IACpD,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,IAAI,OAAO;YAAE,OAAM;QACnB,OAAO,GAAG,IAAI,CAAA;QACd,KAAK,aAAa,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAA;IAC3D,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,YAAY,CAAC,CAAA;IAC/B,KAAK,CAAC,KAAK,EAAE,CAAA;IACb,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAA;AAC7C,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Audio generation on audio.cpp: speech, music and sound effects from text. One resident
3
+ * `audiocpp_server` per loaded model, the builds it runs from, and the clips on disk. A module of its
4
+ * own beside image generation (`src/diffusion/`), not a local runtime.
5
+ */
6
+ export * from './args.js';
7
+ export * from './capabilities.js';
8
+ export * from './config.js';
9
+ export * from './errors.js';
10
+ export * from './gallery.js';
11
+ export * from './http.js';
12
+ export * from './idle.js';
13
+ export * from './install.js';
14
+ export * from './jobs.js';
15
+ export * from './model-files.js';
16
+ export * from './output.js';
17
+ export * from './parse.js';
18
+ export * from './recipe.js';
19
+ export * from './request.js';
20
+ export * from './server-process.js';
21
+ export * from './service.js';
22
+ export * from './session.js';
23
+ export * from './state.js';
24
+ export * from './types.js';
25
+ export * from './wav.js';
26
+ export * from './wiring.js';
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Audio generation on audio.cpp: speech, music and sound effects from text. One resident
3
+ * `audiocpp_server` per loaded model, the builds it runs from, and the clips on disk. A module of its
4
+ * own beside image generation (`src/diffusion/`), not a local runtime.
5
+ */
6
+ export * from './args.js';
7
+ export * from './capabilities.js';
8
+ export * from './config.js';
9
+ export * from './errors.js';
10
+ export * from './gallery.js';
11
+ export * from './http.js';
12
+ export * from './idle.js';
13
+ export * from './install.js';
14
+ export * from './jobs.js';
15
+ export * from './model-files.js';
16
+ export * from './output.js';
17
+ export * from './parse.js';
18
+ export * from './recipe.js';
19
+ export * from './request.js';
20
+ export * from './server-process.js';
21
+ export * from './service.js';
22
+ export * from './session.js';
23
+ export * from './state.js';
24
+ export * from './types.js';
25
+ export * from './wav.js';
26
+ export * from './wiring.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audio/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,cAAc,CAAA;AAC5B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * audio.cpp builds under `<data>/audio/backends/<tag>/<backendId>/`: the install record and its
3
+ * marker, the probe that a tree is audio.cpp and can reach its backend's device, and the listing a
4
+ * load picks its build from. The download, the extraction and the removal of a build are the
5
+ * engine-builds module's, as for sd.cpp (`src/diffusion/install.ts`).
6
+ */
7
+ import type { AtomicCoreError, AudioBackend, AudioBackendInstallRecord } from '../contracts/index.js';
8
+ import type { ExitInfo } from '../runtime/llamacpp/index.js';
9
+ export declare function audioServerBinaryName(platform: NodeJS.Platform): string;
10
+ export interface AudioInstallDeps {
11
+ platform?: NodeJS.Platform;
12
+ env?: NodeJS.ProcessEnv;
13
+ probeTimeoutMs?: number;
14
+ spawnRetryDelayMs?: number;
15
+ log?: (level: 'info' | 'warn', msg: string) => void;
16
+ }
17
+ /** `install.json` holds the record minus `dir`, which is where the file lives. */
18
+ export declare function writeAudioInstallRecord(dir: string, record: AudioBackendInstallRecord): Promise<void>;
19
+ export declare function readAudioInstallRecord(dir: string): Promise<AudioBackendInstallRecord | undefined>;
20
+ /** Every `<root>/<tag>/<backendId>/install.json` with its marker and its server binary, newest install first. */
21
+ export declare function listInstalledAudioBuilds(backendsRoot: string, platform?: NodeJS.Platform): Promise<AudioBackendInstallRecord[]>;
22
+ /** What `audiocpp_server --version` says about itself; `null` when the output is not audio.cpp's. */
23
+ export interface AudioVersionInfo {
24
+ version: string;
25
+ backends: string[];
26
+ }
27
+ export declare function parseAudioVersion(text: string): AudioVersionInfo | null;
28
+ export interface AudioDevice {
29
+ /** `MTL`, `Vulkan`, `CUDA`, `BLAS`, `CPU`, …: ggml's backend registry name. */
30
+ registry: string;
31
+ index: number;
32
+ name: string;
33
+ /** `GPU`, `CPU`, `ACCEL`, `IGPU`. */
34
+ type: string;
35
+ }
36
+ /** The device lines of `audiocpp_server --list-devices` (text; v0.9.3 ignores `--json`). */
37
+ export declare function parseAudioDevices(text: string): AudioDevice[];
38
+ /**
39
+ * The verdict on a finished `--version` run: nothing when the binary is audio.cpp, otherwise the error
40
+ * to raise. A binary the OS loader could not start is a missing runtime, not the wrong program, so the
41
+ * loader's words are read before the output is. The `backends:` line is not checked: a build that
42
+ * loads its GPU backend at run time (the fork's Windows arm64 CUDA build) lists only `cpu` there, so
43
+ * whether a GPU build reaches its device is `--list-devices`' question.
44
+ */
45
+ export declare function audioVersionVerdict(binary: string, text: string, exit: ExitInfo, platform: NodeJS.Platform): AtomicCoreError | undefined;
46
+ /**
47
+ * The verdict on `--list-devices` for a GPU build: nothing when the engine sees a GPU, otherwise the
48
+ * error that sends the install to the next build of the ladder (a Vulkan build on a machine without
49
+ * a Vulkan driver lists only the CPU). A CPU build always passes.
50
+ */
51
+ export declare function audioDevicesVerdict(binary: string, text: string, exit: ExitInfo, platform: NodeJS.Platform, backend: AudioBackend): AtomicCoreError | undefined;
52
+ /**
53
+ * An unpacked tree made runnable and checked: `audiocpp_server` present and executable, answering
54
+ * `--version` as audio.cpp, and — for a GPU build — listing a GPU.
55
+ * Throws `ENGINE_INSTALL_FAILED` otherwise, which moves the install to the next build of the ladder.
56
+ */
57
+ export declare function prepareAudiocppTree(dir: string, backend: AudioBackend, deps?: AudioInstallDeps): Promise<void>;
@@ -0,0 +1,196 @@
1
+ /**
2
+ * audio.cpp builds under `<data>/audio/backends/<tag>/<backendId>/`: the install record and its
3
+ * marker, the probe that a tree is audio.cpp and can reach its backend's device, and the listing a
4
+ * load picks its build from. The download, the extraction and the removal of a build are the
5
+ * engine-builds module's, as for sd.cpp (`src/diffusion/install.ts`).
6
+ */
7
+ import { chmod, readdir, readFile, stat, writeFile } from 'node:fs/promises';
8
+ import { join } from 'node:path';
9
+ import { AUDIO_BACKENDS } from '../contracts/index.js';
10
+ import { INSTALL_RECORD, OWNER_MARKER, PROBE_TIMEOUT_MS, runHelpProbe } from '../diffusion/index.js';
11
+ import { audioError, audioIoError } from './errors.js';
12
+ /** What audio.cpp's `--version` prints first, and the line naming the backends the build carries. */
13
+ const VERSION_MARKER = 'audio.cpp ';
14
+ const BACKENDS_LINE = /^backends:\s*(.+)$/m;
15
+ /** A `--list-devices` line: `MTL:0 "Apple M4 Pro" [GPU]`. */
16
+ const DEVICE_LINE = /^\s*([A-Za-z0-9_]+):(\d+)\s+"([^"]*)"\s+\[([A-Z]+)\]\s*$/gm;
17
+ /** What glibc's `ld.so` and macOS `dyld` print when a library is missing, lowercase. */
18
+ const LOADER_MARKERS = ['error while loading shared libraries', 'library not loaded'];
19
+ /** NTSTATUS codes of a Windows process the loader gave up on before `main`. */
20
+ const WINDOWS_LOADER_FAILURES = new Set([0xc000_0135, 0xc000_0138, 0xc000_0139, 0xc000_007b, 0xc000_0142]);
21
+ export function audioServerBinaryName(platform) {
22
+ return platform === 'win32' ? 'audiocpp_server.exe' : 'audiocpp_server';
23
+ }
24
+ const isFile = (path) => stat(path).then((s) => s.isFile(), () => false);
25
+ const isDirectory = (path) => stat(path).then((s) => s.isDirectory(), () => false);
26
+ /** `install.json` holds the record minus `dir`, which is where the file lives. */
27
+ export async function writeAudioInstallRecord(dir, record) {
28
+ const file = {
29
+ tag: record.tag,
30
+ backendId: record.backendId,
31
+ backend: record.backend,
32
+ engine: record.engine,
33
+ sha256: record.sha256,
34
+ installedAtMs: record.installedAtMs,
35
+ };
36
+ await writeFile(join(dir, OWNER_MARKER), 'atomic-chat\n').catch((error) => {
37
+ throw audioIoError('Could not write the ownership marker.', error);
38
+ });
39
+ await writeFile(join(dir, INSTALL_RECORD), JSON.stringify(file, null, 2)).catch((error) => {
40
+ throw audioIoError('Could not write the install record.', error);
41
+ });
42
+ }
43
+ export async function readAudioInstallRecord(dir) {
44
+ let raw;
45
+ try {
46
+ raw = JSON.parse(await readFile(join(dir, INSTALL_RECORD), 'utf8'));
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw))
52
+ return undefined;
53
+ const file = raw;
54
+ const sha256 = file['sha256'] ?? null;
55
+ const { tag, backendId, backend, engine, installedAtMs } = file;
56
+ if (typeof tag !== 'string' ||
57
+ typeof backendId !== 'string' ||
58
+ typeof backend !== 'string' ||
59
+ !AUDIO_BACKENDS.includes(backend) ||
60
+ engine !== 'audio-cpp' ||
61
+ (sha256 !== null && typeof sha256 !== 'string') ||
62
+ typeof installedAtMs !== 'number' ||
63
+ !Number.isInteger(installedAtMs) ||
64
+ installedAtMs < 0)
65
+ return undefined;
66
+ return { tag, backendId, backend: backend, engine, sha256, installedAtMs, dir };
67
+ }
68
+ /** Every `<root>/<tag>/<backendId>/install.json` with its marker and its server binary, newest install first. */
69
+ export async function listInstalledAudioBuilds(backendsRoot, platform = process.platform) {
70
+ const out = [];
71
+ for (const tag of await readdir(backendsRoot).catch(() => [])) {
72
+ const tagPath = join(backendsRoot, tag);
73
+ if (!(await isDirectory(tagPath)))
74
+ continue;
75
+ for (const backend of await readdir(tagPath).catch(() => [])) {
76
+ const dir = join(tagPath, backend);
77
+ if (!(await isDirectory(dir)) || !(await isFile(join(dir, OWNER_MARKER))))
78
+ continue;
79
+ const record = await readAudioInstallRecord(dir);
80
+ if (record && (await isFile(join(dir, audioServerBinaryName(platform)))))
81
+ out.push(record);
82
+ }
83
+ }
84
+ return out.sort((a, b) => b.installedAtMs - a.installedAtMs);
85
+ }
86
+ export function parseAudioVersion(text) {
87
+ const first = text.split(/\r?\n/).find((line) => line.startsWith(VERSION_MARKER));
88
+ if (!first)
89
+ return null;
90
+ const backends = BACKENDS_LINE.exec(text)?.[1];
91
+ return {
92
+ version: first.slice(VERSION_MARKER.length).trim(),
93
+ backends: backends
94
+ ? backends
95
+ .split(',')
96
+ .map((name) => name.trim().toLowerCase())
97
+ .filter(Boolean)
98
+ : [],
99
+ };
100
+ }
101
+ /** The device lines of `audiocpp_server --list-devices` (text; v0.9.3 ignores `--json`). */
102
+ export function parseAudioDevices(text) {
103
+ return [...text.matchAll(DEVICE_LINE)].map((match) => ({
104
+ registry: match[1] ?? '',
105
+ index: Number(match[2]),
106
+ name: match[3] ?? '',
107
+ type: match[4] ?? '',
108
+ }));
109
+ }
110
+ function loaderFailed(text, exit, platform) {
111
+ const lower = text.toLowerCase();
112
+ return ((platform === 'win32' && exit.code !== null && WINDOWS_LOADER_FAILURES.has(exit.code >>> 0)) ||
113
+ LOADER_MARKERS.some((marker) => lower.includes(marker)));
114
+ }
115
+ const statusOf = (binary, exit) => exit.code === null
116
+ ? `${binary}: ${exit.signal === null ? 'unknown status' : `signal ${String(exit.signal)}`}`
117
+ : `${binary}: exit code ${exit.code}`;
118
+ /**
119
+ * The verdict on a finished `--version` run: nothing when the binary is audio.cpp, otherwise the error
120
+ * to raise. A binary the OS loader could not start is a missing runtime, not the wrong program, so the
121
+ * loader's words are read before the output is. The `backends:` line is not checked: a build that
122
+ * loads its GPU backend at run time (the fork's Windows arm64 CUDA build) lists only `cpu` there, so
123
+ * whether a GPU build reaches its device is `--list-devices`' question.
124
+ */
125
+ export function audioVersionVerdict(binary, text, exit, platform) {
126
+ const output = [...text].slice(0, 800).join('');
127
+ const status = statusOf(binary, exit);
128
+ if (loaderFailed(text, exit, platform))
129
+ return audioError('ENGINE_INSTALL_FAILED', 'The audio engine could not load a library it needs.', output.trim() === '' ? status : `${status}\n${output}`);
130
+ if (parseAudioVersion(text))
131
+ return undefined;
132
+ if (text.trim() === '')
133
+ return audioError('ENGINE_INSTALL_FAILED', 'The audio engine exited without printing anything.', status);
134
+ return audioError('ENGINE_INSTALL_FAILED', 'The downloaded binary is not audio.cpp.', output);
135
+ }
136
+ /**
137
+ * The verdict on `--list-devices` for a GPU build: nothing when the engine sees a GPU, otherwise the
138
+ * error that sends the install to the next build of the ladder (a Vulkan build on a machine without
139
+ * a Vulkan driver lists only the CPU). A CPU build always passes.
140
+ */
141
+ export function audioDevicesVerdict(binary, text, exit, platform, backend) {
142
+ if (backend === 'cpu')
143
+ return undefined;
144
+ if (loaderFailed(text, exit, platform))
145
+ return audioError('ENGINE_INSTALL_FAILED', 'The audio engine could not load a library it needs.', statusOf(binary, exit));
146
+ const gpus = parseAudioDevices(text).filter((device) => device.type === 'GPU' || device.type === 'IGPU');
147
+ if (gpus.length > 0)
148
+ return undefined;
149
+ return audioError('ENGINE_INSTALL_FAILED', `The audio engine found no ${backend} device on this computer.`, [...text].slice(-800).join(''));
150
+ }
151
+ async function setExecutable(path, deps) {
152
+ if ((deps.platform ?? process.platform) === 'win32' || !(await isFile(path)))
153
+ return;
154
+ await chmod(path, 0o755).catch((error) => {
155
+ deps.log?.('warn', `chmod ${path} failed: ${error instanceof Error ? error.message : String(error)}`);
156
+ });
157
+ }
158
+ /**
159
+ * An unpacked tree made runnable and checked: `audiocpp_server` present and executable, answering
160
+ * `--version` as audio.cpp, and — for a GPU build — listing a GPU.
161
+ * Throws `ENGINE_INSTALL_FAILED` otherwise, which moves the install to the next build of the ladder.
162
+ */
163
+ export async function prepareAudiocppTree(dir, backend, deps = {}) {
164
+ const platform = deps.platform ?? process.platform;
165
+ const server = join(dir, audioServerBinaryName(platform));
166
+ if (!(await isFile(server)))
167
+ throw audioError('ENGINE_INSTALL_FAILED', 'The archive did not contain audiocpp_server.', server);
168
+ await setExecutable(server, deps);
169
+ await setExecutable(join(dir, platform === 'win32' ? 'audiocpp_cli.exe' : 'audiocpp_cli'), deps);
170
+ const started = Date.now();
171
+ const probe = (args) => runHelpProbe(server, {
172
+ platform,
173
+ timeoutMs: deps.probeTimeoutMs ?? PROBE_TIMEOUT_MS,
174
+ args,
175
+ deps,
176
+ noResponse: `The audio engine did not respond to ${args.join(' ')}.`,
177
+ couldNotStart: 'The audio engine could not be started.',
178
+ });
179
+ try {
180
+ const version = await probe(['--version']);
181
+ const versionFailure = audioVersionVerdict(server, version.text, version.exit, platform);
182
+ if (versionFailure)
183
+ throw versionFailure;
184
+ const devices = backend === 'cpu' ? null : await probe(['--list-devices']);
185
+ const devicesFailure = devices && audioDevicesVerdict(server, devices.text, devices.exit, platform, backend);
186
+ if (devicesFailure)
187
+ throw devicesFailure;
188
+ deps.log?.('info', `audio engine probe passed in ${((Date.now() - started) / 1000).toFixed(1)}s`);
189
+ }
190
+ catch (error) {
191
+ const { message, details } = error;
192
+ deps.log?.('warn', `audio engine probe failed: ${message} (${details ?? 'no details'})`);
193
+ throw error;
194
+ }
195
+ }
196
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/audio/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Jobs: validate, send to `audiocpp_server`, save, and the cancel path. One job at a time; the
3
+ * request is synchronous (audio.cpp has no job API), so a job moves through phases only —
4
+ * `queued`, `loading` while a server stopped by a cancel or a crash comes back, `generating` while
5
+ * the engine runs, `saving` while the clip is written — each one an `audio:job` event.
6
+ *
7
+ * Cancel: audio.cpp cannot interrupt a running request and goes on generating after a JSON client
8
+ * hangs up, so a cancel aborts the request and stops the process, keeping the spec; the next job
9
+ * respawns the server from it. A job not generating yet just ends.
10
+ */
11
+ import type { AudioCancelResult, AudioErrorBody, AudioGalleryItem, AudioGenerateRequest, AudioJob, AudioJobPhase, AudioMode, AudioSource } from '../contracts/index.js';
12
+ import type { AsyncMutex } from '../diffusion/index.js';
13
+ import type { AudioGallery } from './gallery.js';
14
+ import type { AudioHttpClient } from './http.js';
15
+ import type { AudioSessionDeps } from './session.js';
16
+ export interface AudioJobTimings {
17
+ /** Only stops a wedged engine from holding the slot forever; a long song on a CPU takes many minutes. */
18
+ generationCeilingMs: number;
19
+ /** How long a dropped connection waits for the server's exit to show before it is called a crash. */
20
+ exitWaitMs: number;
21
+ }
22
+ export declare const DEFAULT_AUDIO_JOB_TIMINGS: AudioJobTimings;
23
+ export interface AudioJobDeps extends AudioSessionDeps {
24
+ http: AudioHttpClient;
25
+ gallery: AudioGallery;
26
+ loadLock: AsyncMutex;
27
+ timings: AudioJobTimings;
28
+ drawSeed: () => number;
29
+ /** A reference voice from disk, refused when it is larger than `maxBytes`. */
30
+ readSource: (path: string, maxBytes: number) => Promise<Buffer>;
31
+ }
32
+ export interface AudioJobOutcome {
33
+ job: AudioJob;
34
+ item: AudioGalleryItem;
35
+ /** The clip's bytes, as saved. */
36
+ wav: Buffer;
37
+ }
38
+ export type AudioJobResult = {
39
+ ok: true;
40
+ outcome: AudioJobOutcome;
41
+ } | {
42
+ ok: false;
43
+ error: AudioErrorBody;
44
+ };
45
+ export interface StartedAudioJob {
46
+ job: AudioJob;
47
+ /** Settles when the job is over; never rejects. */
48
+ done: Promise<AudioJobResult>;
49
+ }
50
+ export declare function drawAudioSeed(): number;
51
+ /** A reference voice file, read whole once it is known to be small enough. */
52
+ export declare function readVoiceRefFile(path: string, maxBytes: number): Promise<Buffer>;
53
+ /** The reference voice as the engine takes it: a WAV of at most 5 MiB, base64. */
54
+ export declare function resolveVoiceRef(source: AudioSource, readSource: AudioJobDeps['readSource']): Promise<string>;
55
+ /** The request as the job record keeps it: inline audio bytes blanked, file paths kept. */
56
+ export declare function withoutInlineAudio(request: AudioGenerateRequest): AudioGenerateRequest;
57
+ /** Move a job to `phase` (and to `generating` with it), never out of a terminal state. */
58
+ export declare function setJobPhase(deps: AudioJobDeps, id: string, phase: AudioJobPhase): void;
59
+ /** Move a job to a terminal state exactly once. Whether this call made the transition. */
60
+ export declare function finishAudioJob(deps: AudioJobDeps, id: string, result: {
61
+ ok: true;
62
+ item: AudioGalleryItem;
63
+ } | {
64
+ ok: false;
65
+ error: AudioErrorBody;
66
+ }): boolean;
67
+ /** Validate, register and start a job in `mode` on the loaded model. */
68
+ export declare function startAudioJob(deps: AudioJobDeps, mode: AudioMode, request: AudioGenerateRequest): Promise<StartedAudioJob>;
69
+ /** Run one job to completion; the path a caller that awaits the clip takes. */
70
+ export declare function runAudioJob(deps: AudioJobDeps, mode: AudioMode, request: AudioGenerateRequest): Promise<AudioJobOutcome>;
71
+ /**
72
+ * Cancel a job. While the engine generates, the request is aborted and the server stopped (the spec
73
+ * stays, so the next job respawns it); a clip already being saved is kept. Before that the job ends
74
+ * here and now: its runner may be waiting for the load lock to respawn the server, and the caller may
75
+ * hold that lock (a load, an unload, an engine update), so nothing here waits for the runner then.
76
+ */
77
+ export declare function cancelAudioJob(deps: AudioJobDeps, id: string): Promise<AudioCancelResult>;