@atomic-chat/core 0.21.0 → 0.21.2

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 (186) hide show
  1. package/dist/backend/advisor/advisor.js +11 -2
  2. package/dist/backend/advisor/advisor.js.map +1 -1
  3. package/dist/backend/install/cuda-guard.d.ts +62 -0
  4. package/dist/backend/install/cuda-guard.js +80 -0
  5. package/dist/backend/install/cuda-guard.js.map +1 -0
  6. package/dist/backend/install/cuda-runtime-source.d.ts +76 -0
  7. package/dist/backend/install/cuda-runtime-source.js +294 -0
  8. package/dist/backend/install/cuda-runtime-source.js.map +1 -0
  9. package/dist/backend/install/index.d.ts +3 -0
  10. package/dist/backend/install/index.js +3 -0
  11. package/dist/backend/install/index.js.map +1 -1
  12. package/dist/backend/install/runtime-backend.d.ts +30 -3
  13. package/dist/backend/install/runtime-backend.js +106 -28
  14. package/dist/backend/install/runtime-backend.js.map +1 -1
  15. package/dist/backend/install/service.d.ts +42 -24
  16. package/dist/backend/install/service.js +176 -31
  17. package/dist/backend/install/service.js.map +1 -1
  18. package/dist/backend/install/windows-launch-check.d.ts +72 -0
  19. package/dist/backend/install/windows-launch-check.js +173 -0
  20. package/dist/backend/install/windows-launch-check.js.map +1 -0
  21. package/dist/backend/installed/installed.d.ts +13 -0
  22. package/dist/backend/installed/installed.js +32 -0
  23. package/dist/backend/installed/installed.js.map +1 -1
  24. package/dist/backend/select/bad-backends.d.ts +68 -0
  25. package/dist/backend/select/bad-backends.js +136 -0
  26. package/dist/backend/select/bad-backends.js.map +1 -0
  27. package/dist/backend/select/features.d.ts +18 -1
  28. package/dist/backend/select/features.js +29 -1
  29. package/dist/backend/select/features.js.map +1 -1
  30. package/dist/backend/select/index.d.ts +1 -0
  31. package/dist/backend/select/index.js +1 -0
  32. package/dist/backend/select/index.js.map +1 -1
  33. package/dist/backend/turboquant.d.ts +8 -0
  34. package/dist/backend/turboquant.js +37 -9
  35. package/dist/backend/turboquant.js.map +1 -1
  36. package/dist/cli/main.d.ts +1 -1
  37. package/dist/contracts/diagnostics.d.ts +21 -0
  38. package/dist/contracts/diagnostics.js +71 -0
  39. package/dist/contracts/diagnostics.js.map +1 -0
  40. package/dist/contracts/errors.d.ts +18 -76
  41. package/dist/contracts/errors.js +145 -2
  42. package/dist/contracts/errors.js.map +1 -1
  43. package/dist/contracts/hardware.d.ts +8 -0
  44. package/dist/contracts/index.d.ts +2 -0
  45. package/dist/contracts/index.js +2 -0
  46. package/dist/contracts/index.js.map +1 -1
  47. package/dist/contracts/load-diag.d.ts +34 -0
  48. package/dist/contracts/load-diag.js +48 -0
  49. package/dist/contracts/load-diag.js.map +1 -0
  50. package/dist/core/atomic-core.d.ts +1 -1
  51. package/dist/core/atomic-core.js +2 -1
  52. package/dist/core/atomic-core.js.map +1 -1
  53. package/dist/core/create.js +25 -15
  54. package/dist/core/create.js.map +1 -1
  55. package/dist/core/managed-environment.d.ts +2 -0
  56. package/dist/core/managed-environment.js +2 -0
  57. package/dist/core/managed-environment.js.map +1 -1
  58. package/dist/decision/service.d.ts +2 -23
  59. package/dist/decision/service.js +27 -0
  60. package/dist/decision/service.js.map +1 -1
  61. package/dist/decision/wiring.d.ts +2 -0
  62. package/dist/decision/wiring.js +1 -6
  63. package/dist/decision/wiring.js.map +1 -1
  64. package/dist/diffusion/errors.js +3 -3
  65. package/dist/diffusion/errors.js.map +1 -1
  66. package/dist/diffusion/jobs.js +1 -0
  67. package/dist/diffusion/jobs.js.map +1 -1
  68. package/dist/diffusion/remote-job.js +1 -0
  69. package/dist/diffusion/remote-job.js.map +1 -1
  70. package/dist/diffusion/service.d.ts +2 -6
  71. package/dist/diffusion/service.js +1 -0
  72. package/dist/diffusion/service.js.map +1 -1
  73. package/dist/diffusion/session.d.ts +2 -5
  74. package/dist/diffusion/session.js +1 -0
  75. package/dist/diffusion/session.js.map +1 -1
  76. package/dist/diffusion/wiring.d.ts +2 -0
  77. package/dist/diffusion/wiring.js +1 -5
  78. package/dist/diffusion/wiring.js.map +1 -1
  79. package/dist/downloads/archive.js +8 -3
  80. package/dist/downloads/archive.js.map +1 -1
  81. package/dist/downloads/disk.d.ts +18 -0
  82. package/dist/downloads/disk.js +32 -1
  83. package/dist/downloads/disk.js.map +1 -1
  84. package/dist/downloads/downloader.d.ts +2 -18
  85. package/dist/downloads/downloader.js +208 -97
  86. package/dist/downloads/downloader.js.map +1 -1
  87. package/dist/downloads/fs-retry.d.ts +27 -0
  88. package/dist/downloads/fs-retry.js +40 -0
  89. package/dist/downloads/fs-retry.js.map +1 -0
  90. package/dist/downloads/index.d.ts +1 -0
  91. package/dist/downloads/index.js +1 -0
  92. package/dist/downloads/index.js.map +1 -1
  93. package/dist/downloads/protocol.d.ts +6 -2
  94. package/dist/downloads/protocol.js +27 -5
  95. package/dist/downloads/protocol.js.map +1 -1
  96. package/dist/embedding/service.d.ts +2 -18
  97. package/dist/embedding/service.js +21 -1
  98. package/dist/embedding/service.js.map +1 -1
  99. package/dist/embedding/wiring.d.ts +2 -0
  100. package/dist/embedding/wiring.js +1 -6
  101. package/dist/embedding/wiring.js.map +1 -1
  102. package/dist/hardware/index.d.ts +1 -0
  103. package/dist/hardware/index.js +1 -0
  104. package/dist/hardware/index.js.map +1 -1
  105. package/dist/hardware/probe-common.d.ts +9 -1
  106. package/dist/hardware/probe-common.js.map +1 -1
  107. package/dist/hardware/probe-windows.d.ts +10 -2
  108. package/dist/hardware/probe-windows.js +65 -10
  109. package/dist/hardware/probe-windows.js.map +1 -1
  110. package/dist/hardware/probe.js +1 -1
  111. package/dist/hardware/probe.js.map +1 -1
  112. package/dist/hardware/service.d.ts +11 -0
  113. package/dist/hardware/service.js +31 -4
  114. package/dist/hardware/service.js.map +1 -1
  115. package/dist/hardware/windows-registry.d.ts +80 -0
  116. package/dist/hardware/windows-registry.js +197 -0
  117. package/dist/hardware/windows-registry.js.map +1 -0
  118. package/dist/lock/instance-lock.js +7 -3
  119. package/dist/lock/instance-lock.js.map +1 -1
  120. package/dist/remote-access/manager.d.ts +2 -0
  121. package/dist/remote-access/manager.js +18 -2
  122. package/dist/remote-access/manager.js.map +1 -1
  123. package/dist/runtime/environment/service.d.ts +2 -14
  124. package/dist/runtime/environment/service.js +10 -0
  125. package/dist/runtime/environment/service.js.map +1 -1
  126. package/dist/runtime/environment/wiring.d.ts +2 -23
  127. package/dist/runtime/environment/wiring.js +1 -0
  128. package/dist/runtime/environment/wiring.js.map +1 -1
  129. package/dist/runtime/llamacpp/args.d.ts +11 -0
  130. package/dist/runtime/llamacpp/args.js +28 -3
  131. package/dist/runtime/llamacpp/args.js.map +1 -1
  132. package/dist/runtime/llamacpp/devices.d.ts +11 -0
  133. package/dist/runtime/llamacpp/devices.js +22 -0
  134. package/dist/runtime/llamacpp/devices.js.map +1 -1
  135. package/dist/runtime/llamacpp/errors.d.ts +34 -4
  136. package/dist/runtime/llamacpp/errors.js +105 -22
  137. package/dist/runtime/llamacpp/errors.js.map +1 -1
  138. package/dist/runtime/llamacpp/index.d.ts +1 -0
  139. package/dist/runtime/llamacpp/index.js +1 -0
  140. package/dist/runtime/llamacpp/index.js.map +1 -1
  141. package/dist/runtime/llamacpp/load-failure.d.ts +52 -0
  142. package/dist/runtime/llamacpp/load-failure.js +105 -0
  143. package/dist/runtime/llamacpp/load-failure.js.map +1 -0
  144. package/dist/runtime/llamacpp/load-plan.d.ts +5 -0
  145. package/dist/runtime/llamacpp/load-plan.js +34 -4
  146. package/dist/runtime/llamacpp/load-plan.js.map +1 -1
  147. package/dist/runtime/llamacpp/runtime.d.ts +24 -1
  148. package/dist/runtime/llamacpp/runtime.js +116 -27
  149. package/dist/runtime/llamacpp/runtime.js.map +1 -1
  150. package/dist/runtime/shared/env.js +13 -15
  151. package/dist/runtime/shared/env.js.map +1 -1
  152. package/dist/server/public/errors.d.ts +2 -0
  153. package/dist/server/public/errors.js +6 -2
  154. package/dist/server/public/errors.js.map +1 -1
  155. package/dist/server/public/forward.js +22 -18
  156. package/dist/server/public/forward.js.map +1 -1
  157. package/dist/settings/store.js +1 -1
  158. package/dist/settings/store.js.map +1 -1
  159. package/dist/telemetry/diagnostics.d.ts +14 -0
  160. package/dist/telemetry/diagnostics.js +289 -0
  161. package/dist/telemetry/diagnostics.js.map +1 -0
  162. package/dist/telemetry/envelope.d.ts +1 -1
  163. package/dist/telemetry/envelope.js +57 -28
  164. package/dist/telemetry/envelope.js.map +1 -1
  165. package/dist/telemetry/index.d.ts +1 -0
  166. package/dist/telemetry/index.js +1 -0
  167. package/dist/telemetry/index.js.map +1 -1
  168. package/dist/telemetry/policy.d.ts +1 -1
  169. package/dist/telemetry/policy.js +45 -2
  170. package/dist/telemetry/policy.js.map +1 -1
  171. package/dist/telemetry/reporter.d.ts +1 -0
  172. package/dist/telemetry/reporter.js +0 -0
  173. package/dist/telemetry/reporter.js.map +1 -1
  174. package/dist/telemetry/reports.d.ts +2 -7
  175. package/dist/telemetry/reports.js +34 -29
  176. package/dist/telemetry/reports.js.map +1 -1
  177. package/dist/telemetry/stack.d.ts +1 -1
  178. package/dist/telemetry/stack.js +8 -1
  179. package/dist/telemetry/stack.js.map +1 -1
  180. package/dist/telemetry/subscribe.d.ts +1 -1
  181. package/dist/telemetry/subscribe.js +7 -5
  182. package/dist/telemetry/subscribe.js.map +1 -1
  183. package/dist/telemetry/types.d.ts +3 -2
  184. package/dist/version.d.ts +1 -1
  185. package/dist/version.js +1 -1
  186. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/downloads/archive.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/downloads/archive.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,24 @@ import type { DiskErrorTag } from '../contracts/index.js';
14
14
  export declare function classifyIoError(error: unknown): DiskErrorTag;
15
15
  /** `Error: [<tag>] <message>` — the shape the frontend parses. */
16
16
  export declare function diskErrToString(error: unknown): string;
17
+ /** The largest file a FAT/FAT32 volume can hold: 4 GiB minus one byte. */
18
+ export declare const FAT32_MAX_FILE_BYTES: number;
19
+ /**
20
+ * The tag of a failed write of `length` bytes at `offset`. FAT32 refuses exactly the write that takes
21
+ * a file past 4 GiB − 1, and Windows words that refusal as a full disk (or an error libuv has no name
22
+ * for): a write that crosses that line and fails as anything but a permission or a lock is the
23
+ * volume's file-size limit. Every other failed write is tagged as `classifyIoError` tags it.
24
+ */
25
+ export declare function writeFaultTag(error: unknown, offset: number, length: number): DiskErrorTag;
26
+ /** `diskErrToString` for a failed write, with the FAT32 rule of `writeFaultTag`. */
27
+ export declare function diskWriteErrToString(error: unknown, offset: number, length: number): string;
28
+ /**
29
+ * The tag of a rename or removal that still failed after `retryTransientFs` waited. On Windows a
30
+ * denial on a directory this process has just written is a handle someone else holds (antivirus,
31
+ * the indexer, a server running from the old copy), not a missing permission: the process could
32
+ * write there a moment ago. Elsewhere, and for every other code, `classifyIoError` decides.
33
+ */
34
+ export declare function heldFileFaultTag(error: unknown, platform: NodeJS.Platform | string): DiskErrorTag;
17
35
  /** Same shape for a preflight refusal that has no fs error behind it. */
18
36
  export declare function diskFaultMessage(tag: DiskErrorTag, detail: string): string;
19
37
  /** Bytes never consumed on top of the download itself (a volume at zero free bytes kills the app). */
@@ -9,10 +9,12 @@
9
9
  * already maps Win32 codes (ERROR_DISK_FULL → ENOSPC, ERROR_SHARING_VIOLATION → EBUSY, …), so one
10
10
  * table covers both sides of the Rust `cfg(unix)` / `cfg(windows)` split.
11
11
  */
12
+ import { isTransientFsError } from './fs-retry.js';
12
13
  const CODE_TO_TAG = {
13
14
  ENOSPC: 'disk_full',
14
15
  EDQUOT: 'disk_full',
15
- EFBIG: 'disk_full',
16
+ // "File too large": the volume's own size limit for one file (FAT32's 4 GiB), not a full disk.
17
+ EFBIG: 'disk_fs_limit',
16
18
  EACCES: 'disk_permission',
17
19
  EPERM: 'disk_permission',
18
20
  EROFS: 'disk_permission',
@@ -36,6 +38,35 @@ export function diskErrToString(error) {
36
38
  const message = error instanceof Error ? error.message : String(error);
37
39
  return `Error: [${classifyIoError(error)}] ${message}`;
38
40
  }
41
+ /** The largest file a FAT/FAT32 volume can hold: 4 GiB minus one byte. */
42
+ export const FAT32_MAX_FILE_BYTES = 2 ** 32 - 1;
43
+ /**
44
+ * The tag of a failed write of `length` bytes at `offset`. FAT32 refuses exactly the write that takes
45
+ * a file past 4 GiB − 1, and Windows words that refusal as a full disk (or an error libuv has no name
46
+ * for): a write that crosses that line and fails as anything but a permission or a lock is the
47
+ * volume's file-size limit. Every other failed write is tagged as `classifyIoError` tags it.
48
+ */
49
+ export function writeFaultTag(error, offset, length) {
50
+ const tag = classifyIoError(error);
51
+ const crosses = offset <= FAT32_MAX_FILE_BYTES && offset + length > FAT32_MAX_FILE_BYTES;
52
+ return crosses && (tag === 'disk_full' || tag === 'disk_io' || tag === 'disk_fs_limit')
53
+ ? 'disk_fs_limit'
54
+ : tag;
55
+ }
56
+ /** `diskErrToString` for a failed write, with the FAT32 rule of `writeFaultTag`. */
57
+ export function diskWriteErrToString(error, offset, length) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ return `Error: [${writeFaultTag(error, offset, length)}] ${message}`;
60
+ }
61
+ /**
62
+ * The tag of a rename or removal that still failed after `retryTransientFs` waited. On Windows a
63
+ * denial on a directory this process has just written is a handle someone else holds (antivirus,
64
+ * the indexer, a server running from the old copy), not a missing permission: the process could
65
+ * write there a moment ago. Elsewhere, and for every other code, `classifyIoError` decides.
66
+ */
67
+ export function heldFileFaultTag(error, platform) {
68
+ return platform === 'win32' && isTransientFsError(error) ? 'disk_file_locked' : classifyIoError(error);
69
+ }
39
70
  /** Same shape for a preflight refusal that has no fs error behind it. */
40
71
  export function diskFaultMessage(tag, detail) {
41
72
  return `Error: [${tag}] ${detail}`;
@@ -1 +1 @@
1
- {"version":3,"file":"disk.js","sourceRoot":"","sources":["../../src/downloads/disk.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,GAAiC;IAChD,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,WAAW;IAClB,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE,iBAAiB;IACxB,KAAK,EAAE,iBAAiB;IACxB,OAAO,EAAE,kBAAkB;IAC3B,KAAK,EAAE,kBAAkB;IACzB,YAAY,EAAE,oBAAoB;IAClC,MAAM,EAAE,kBAAkB;IAC1B,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,kBAAkB;IAC1B,GAAG,EAAE,kBAAkB;IACvB,yFAAyF;IACzF,MAAM,EAAE,kBAAkB;CAC3B,CAAA;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,IAAI,GAAI,KAA2C,EAAE,IAAI,CAAA;IAC/D,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAA;AAC/D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtE,OAAO,WAAW,eAAe,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAA;AACxD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,gBAAgB,CAAC,GAAiB,EAAE,MAAc;IAChE,OAAO,WAAW,GAAG,KAAK,MAAM,EAAE,CAAA;AACpC,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAA;AAEpD,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,YAAsB;IACtE,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IACvD,OAAO,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AACtD,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAC7B,MAAM,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;IACtB,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;IACvD,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAA;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,cAAkC,EAAE,MAAc;IAC/E,IAAI,MAAM,KAAK,CAAC,IAAI,cAAc,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAClE,MAAM,QAAQ,GAAG,MAAM,GAAG,mBAAmB,CAAA;IAC7C,IAAI,cAAc,IAAI,QAAQ;QAAE,OAAO,SAAS,CAAA;IAChD,OAAO,gBAAgB,CACrB,WAAW,EACX,+BAA+B,WAAW,CAAC,QAAQ,CAAC,YAAY,WAAW,CAAC,cAAc,CAAC,YAAY,CACxG,CAAA;AACH,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAA;AAEnC;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,QAAyB;IAC9E,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,SAAS,CAAA;IAC1C,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAA;IACpD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC7D,IAAI,SAAS,GAAG,gBAAgB;QAAE,OAAO,SAAS,CAAA;IAClD,OAAO,gBAAgB,CACrB,oBAAoB,EACpB,gBAAgB,SAAS,yBAAyB,gBAAgB,wFAAwF,CAC3J,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"disk.js","sourceRoot":"","sources":["../../src/downloads/disk.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,4 @@
1
- /**
2
- * Resumable multi-file downloader. Port of `_download_files_internal` / `download_single_file` in
3
- * `src-tauri/src/core/downloads/helpers.rs` and the task registry in `commands.rs`.
4
- *
5
- * Behaviour that is a contract with the app (PLAN.md §8.2 "Downloads"):
6
- * - `save_path` is relative to `<data>` and must stay inside it (symlinked prefixes compared resolved)
7
- * - `.tmp` + `.url` sidecars; resume only when `resume` is set, the `.tmp` exists and `.url` matches
8
- * - `Range: bytes=N-` → 206 + validated `Content-Range`; 200/416 → restart from 0; 408/429/5xx retry
9
- * - 5 retries per stall, counter reset after every 1 MiB of fresh progress
10
- * - combined progress `{transferred,total}` after resume, every 10 MiB per file, per file end, task end
11
- * - verification (size, sha256) after all files; on failure the file and its directory (non-recursive)
12
- * are removed and the task fails; cancel keeps every partial and finished file
13
- * - preflight: Windows path limit, free space with 512 MiB headroom (skipped when unknown)
14
- * - every fs error is rendered `Error: [disk_*] …`
15
- *
16
- * I/O is injected (`fetch`, fs, free-space probe, sleep) so the whole flow is testable against a
17
- * scripted HTTP server without touching the network or the real data folder.
18
- */
1
+ import type { FailureObserver } from '../contracts/index.js';
19
2
  import type { CoreEvents, DownloadProgress } from '../contracts/index.js';
20
3
  import type { ProxyConfig } from './protocol.js';
21
4
  import type { VerifyDeps } from './verify.js';
@@ -34,6 +17,7 @@ export interface DownloadOptions {
34
17
  }
35
18
  export declare const DOWNLOAD_CANCELLED = "Download cancelled";
36
19
  export interface DownloaderDeps {
20
+ onFailure?: FailureObserver;
37
21
  dataFolder: string;
38
22
  platform: NodeJS.Platform;
39
23
  fetch: typeof fetch;
@@ -19,11 +19,67 @@
19
19
  import { createWriteStream } from 'node:fs';
20
20
  import { mkdir, readFile, realpath, rename, rm, rmdir, stat, statfs, writeFile } from 'node:fs/promises';
21
21
  import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
22
- import { checkFreeSpace, checkPathWithinLimit, diskErrToString, remainingBytes } from './disk.js';
22
+ import { checkFreeSpace, checkPathWithinLimit, diskErrToString, diskWriteErrToString, remainingBytes, } from './disk.js';
23
23
  import { classifyDownloadStatus, classifyResumeStatus, DownloadRequestError, downloadStage, expectedDownloadSize, HEAD_TIMEOUT_MS, MAX_STREAM_RETRIES, PROGRESS_EMIT_INTERVAL_BYTES, RETRY_RESET_PROGRESS_BYTES, retryDelayMs, shouldBypassProxy, sidecarPath, validateContentRange, validateProxyConfig, } from './protocol.js';
24
24
  import { policyFetchFor } from './proxy-fetch.js';
25
25
  import { verifyDownloadedFile } from './verify.js';
26
26
  export const DOWNLOAD_CANCELLED = 'Download cancelled';
27
+ /**
28
+ * Open a `.tmp` write stream with an error listener attached before `open` settles on the threadpool,
29
+ * and resolve `close()` only once the underlying file descriptor has closed.
30
+ */
31
+ async function openWriteStream(path, flags, disk) {
32
+ const writer = createWriteStream(path, { flags });
33
+ let streamError;
34
+ writer.on('error', (err) => {
35
+ streamError ??= err;
36
+ });
37
+ await new Promise((ok, fail) => {
38
+ const onOpen = () => {
39
+ writer.off('error', onError);
40
+ ok();
41
+ };
42
+ const onError = (err) => {
43
+ writer.off('open', onOpen);
44
+ fail(disk(err));
45
+ };
46
+ writer.once('open', onOpen);
47
+ writer.once('error', onError);
48
+ });
49
+ let closing;
50
+ const close = () => {
51
+ if (closing)
52
+ return closing;
53
+ closing = new Promise((ok, fail) => {
54
+ const finish = () => (streamError ? fail(disk(streamError)) : ok());
55
+ if (writer.closed)
56
+ return finish();
57
+ writer.once('close', finish);
58
+ if (!writer.destroyed) {
59
+ writer.end((err) => {
60
+ if (err)
61
+ streamError ??= err;
62
+ });
63
+ }
64
+ });
65
+ return closing;
66
+ };
67
+ const write = (chunk, offset) => new Promise((ok, fail) => {
68
+ if (streamError)
69
+ return fail(disk(streamError));
70
+ writer.write(chunk, (err) => {
71
+ if (err) {
72
+ streamError ??= err;
73
+ fail(offset === undefined
74
+ ? disk(err)
75
+ : new Error(diskWriteErrToString(err, offset, chunk.byteLength), { cause: err }));
76
+ }
77
+ else
78
+ ok();
79
+ });
80
+ });
81
+ return { write, close };
82
+ }
27
83
  export async function defaultAvailableSpace(path) {
28
84
  let probe = path;
29
85
  for (;;) {
@@ -77,6 +133,18 @@ const isInside = (child, parent) => {
77
133
  const rel = relative(parent, child);
78
134
  return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
79
135
  };
136
+ // Keep the historical Error and message while allowing every observing boundary to classify it.
137
+ function preflightFailure(message, reason) {
138
+ return Object.defineProperty(new Error(message), 'diagnostic', {
139
+ value: {
140
+ component: 'downloads',
141
+ operation: 'download',
142
+ stage: 'validate',
143
+ reason,
144
+ category: reason === 'invalid_request' ? 'expected' : 'operational',
145
+ },
146
+ });
147
+ }
80
148
  export class Downloader {
81
149
  tasks = new Map();
82
150
  deps;
@@ -125,6 +193,11 @@ export class Downloader {
125
193
  try {
126
194
  await this.run(taskId, items, options, task.controller.signal);
127
195
  }
196
+ catch (error) {
197
+ if (!task.controller.signal.aborted)
198
+ this.deps.onFailure?.(error, { component: 'downloads', operation: 'download' });
199
+ throw error;
200
+ }
128
201
  finally {
129
202
  if (this.tasks.get(taskId) === task)
130
203
  this.tasks.delete(taskId);
@@ -141,7 +214,7 @@ export class Downloader {
141
214
  if (item.proxy) {
142
215
  const problem = validateProxyConfig(item.proxy);
143
216
  if (problem)
144
- throw new Error(`Error: ${problem}`);
217
+ throw preflightFailure(`Error: ${problem}`, 'invalid_request');
145
218
  }
146
219
  }
147
220
  // Preflight sizes (catalog size or HEAD; HEAD failures degrade to unknown).
@@ -157,9 +230,9 @@ export class Downloader {
157
230
  const savePath = resolve(dataFolder, item.save_path);
158
231
  const limit = checkPathWithinLimit(savePath, platform);
159
232
  if (limit)
160
- throw new Error(limit);
233
+ throw preflightFailure(limit, 'disk_path_too_long');
161
234
  if (!isInside(await canonicalizeExistingPrefix(savePath), resolvedRoot)) {
162
- throw new Error(`Path ${savePath} is outside of Jan data folder ${dataFolder}`);
235
+ throw preflightFailure(`Path ${savePath} is outside of Jan data folder ${dataFolder}`, 'invalid_request');
163
236
  }
164
237
  savePaths.push(savePath);
165
238
  if (resume) {
@@ -173,7 +246,7 @@ export class Downloader {
173
246
  }
174
247
  const space = checkFreeSpace(await this.deps.availableSpace(dataFolder), remainingBytes(totalSize, partialSizes));
175
248
  if (space)
176
- throw new Error(space);
249
+ throw preflightFailure(space, 'disk_full');
177
250
  const progress = new Map();
178
251
  const emitProgress = () => {
179
252
  const transferred = [...progress.values()].reduce((a, b) => a + b, 0);
@@ -184,14 +257,28 @@ export class Downloader {
184
257
  task.progress = current;
185
258
  this.deps.emit('download:progress', current);
186
259
  };
187
- const results = await Promise.all(items.map((item, i) => this.downloadOne(item, savePaths[i], `${taskId}-${i}`, sizes.get(item.url) ?? 0, {
260
+ const batch = new AbortController();
261
+ const batchSignal = AbortSignal.any([signal, batch.signal]);
262
+ let firstError;
263
+ let failed = false;
264
+ const settled = await Promise.allSettled(items.map((item, i) => this.downloadOne(item, savePaths[i], `${taskId}-${i}`, sizes.get(item.url) ?? 0, {
188
265
  headers,
189
266
  resume,
190
- signal,
267
+ signal: batchSignal,
191
268
  progress,
192
269
  emitProgress,
193
270
  reportStage,
271
+ }).catch((error) => {
272
+ if (!failed) {
273
+ failed = true;
274
+ firstError = error;
275
+ batch.abort();
276
+ }
277
+ throw error;
194
278
  })));
279
+ if (failed)
280
+ throw firstError;
281
+ const results = settled.map((outcome) => outcome.value);
195
282
  if (items.some((it) => it.sha256 != null || it.size != null)) {
196
283
  const modelId = items.find((it) => it.model_id != null)?.model_id ??
197
284
  (items[0] ? (dirname(items[0].save_path).split(/[\\/]/).pop() ?? 'unknown') : 'unknown');
@@ -260,7 +347,7 @@ export class Downloader {
260
347
  catch (e) {
261
348
  if (signal.aborted)
262
349
  throw new Error(DOWNLOAD_CANCELLED);
263
- throw new DownloadRequestError('retryable', e.message);
350
+ throw new DownloadRequestError('retryable', e.message, { cause: e });
264
351
  }
265
352
  if (startBytes > 0) {
266
353
  if (res.status === 206) {
@@ -298,7 +385,7 @@ export class Downloader {
298
385
  }
299
386
  async downloadOne(item, savePath, fileId, fileSize, ctx) {
300
387
  const { signal, headers, progress, emitProgress, reportStage } = ctx;
301
- const disk = (e) => new Error(diskErrToString(e));
388
+ const disk = (e) => new Error(diskErrToString(e), { cause: e });
302
389
  const fetchImpl = this.deps.fetchFor(item, this.deps.fetch);
303
390
  if (item.proxy && shouldBypassProxy(item.url, item.proxy.no_proxy ?? []))
304
391
  this.deps.log('info', `Bypassing proxy for URL ${item.url}`);
@@ -355,111 +442,135 @@ export class Downloader {
355
442
  else {
356
443
  res = await this.requestWithRetry(fetchImpl, item, headers, 0, expectedSize, signal, reportStage).catch(rethrowAsString);
357
444
  }
358
- let writer = createWriteStream(tmpPath, { flags: shouldResume ? 'a' : 'w' });
359
- const write = (chunk) => new Promise((ok, fail) => {
360
- writer.write(chunk, (e) => (e ? fail(disk(e)) : ok()));
445
+ if (signal.aborted) {
446
+ await res.body?.cancel().catch(() => { });
447
+ throw new Error(DOWNLOAD_CANCELLED);
448
+ }
449
+ let writer = await openWriteStream(tmpPath, shouldResume ? 'a' : 'w', disk).catch(async (e) => {
450
+ await res.body?.cancel().catch(() => { });
451
+ throw e;
361
452
  });
362
- const close = () => new Promise((ok, fail) => writer.end((e) => (e ? fail(disk(e)) : ok())));
363
453
  let body = res.body ?? new ReadableStream({ start: (c) => c.close() });
364
454
  let reader = body.getReader();
365
455
  let delta = 0;
366
456
  let retryCount = 0;
367
457
  let sinceReset = 0;
368
- for (;;) {
369
- let streamError;
370
- try {
371
- const { done, value } = await reader.read();
372
- if (done) {
373
- if (expectedSize > 0 && totalTransferred < expectedSize) {
374
- streamError = `stream ended after ${totalTransferred} of ${expectedSize} bytes`;
375
- }
376
- else
377
- break;
378
- }
379
- else if (value) {
380
- if (signal.aborted) {
381
- await close().catch(() => { });
382
- this.deps.log('info', `Download cancelled: ${item.url}`);
383
- throw new Error(DOWNLOAD_CANCELLED);
384
- }
385
- await write(value);
386
- delta += value.byteLength;
387
- totalTransferred += value.byteLength;
388
- sinceReset += value.byteLength;
389
- if (sinceReset >= RETRY_RESET_PROGRESS_BYTES) {
390
- retryCount = 0;
391
- sinceReset = 0;
458
+ try {
459
+ for (;;) {
460
+ let streamError;
461
+ try {
462
+ const { done, value } = await reader.read();
463
+ if (done) {
464
+ if (expectedSize > 0 && totalTransferred < expectedSize) {
465
+ streamError = `stream ended after ${totalTransferred} of ${expectedSize} bytes`;
466
+ }
467
+ else
468
+ break;
392
469
  }
393
- if (delta >= PROGRESS_EMIT_INTERVAL_BYTES) {
394
- progress.set(fileId, totalTransferred);
395
- emitProgress();
396
- delta = 0;
470
+ else if (value) {
471
+ if (signal.aborted) {
472
+ await writer.close().catch(() => { });
473
+ this.deps.log('info', `Download cancelled: ${item.url}`);
474
+ throw new Error(DOWNLOAD_CANCELLED);
475
+ }
476
+ // Writes are awaited one at a time, so `totalTransferred` is where this chunk starts.
477
+ await writer.write(value, totalTransferred);
478
+ delta += value.byteLength;
479
+ totalTransferred += value.byteLength;
480
+ sinceReset += value.byteLength;
481
+ if (sinceReset >= RETRY_RESET_PROGRESS_BYTES) {
482
+ retryCount = 0;
483
+ sinceReset = 0;
484
+ }
485
+ if (delta >= PROGRESS_EMIT_INTERVAL_BYTES) {
486
+ progress.set(fileId, totalTransferred);
487
+ emitProgress();
488
+ delta = 0;
489
+ }
397
490
  }
398
491
  }
399
- }
400
- catch (e) {
401
- if (e.message === DOWNLOAD_CANCELLED || e.message.startsWith('Error: ['))
402
- throw e;
403
- if (signal.aborted)
404
- throw new Error(DOWNLOAD_CANCELLED);
405
- streamError = e.message;
406
- }
407
- if (streamError === undefined)
408
- continue;
409
- await close().catch((e) => {
410
- throw new Error(`${e.message} (failed to flush partial download before retrying '${item.url}')`);
411
- });
412
- const durable = (await stat(tmpPath).catch((e) => {
413
- throw disk(e);
414
- })).size;
415
- if (durable !== totalTransferred) {
416
- throw new Error(`Partial download size mismatch for '${item.url}': tracked ${totalTransferred} bytes but persisted ${durable} bytes`);
417
- }
418
- for (;;) {
419
- if (retryCount >= MAX_STREAM_RETRIES) {
420
- throw new Error(`Download failed after ${MAX_STREAM_RETRIES} retries at byte ${durable}: ${streamError}`);
492
+ catch (e) {
493
+ if (e.message === DOWNLOAD_CANCELLED || e.message.startsWith('Error: ['))
494
+ throw e;
495
+ if (signal.aborted)
496
+ throw new Error(DOWNLOAD_CANCELLED);
497
+ streamError = e.message;
421
498
  }
422
- if (signal.aborted)
423
- throw new Error(DOWNLOAD_CANCELLED);
424
- this.deps.log('warn', `Stream error at byte ${durable} for '${item.url}': ${streamError}. Retry ${retryCount + 1}/${MAX_STREAM_RETRIES}`);
425
- await this.deps.sleep(retryDelayMs(retryCount, this.deps.retryBaseMs), signal);
426
- retryCount++;
427
- try {
428
- res = await this.request(fetchImpl, item, headers, durable, expectedSize, signal);
429
- writer = createWriteStream(tmpPath, { flags: 'a' });
430
- break;
499
+ if (streamError === undefined)
500
+ continue;
501
+ await writer.close().catch((e) => {
502
+ throw new Error(`${e.message} (failed to flush partial download before retrying '${item.url}')`);
503
+ });
504
+ const durable = (await stat(tmpPath).catch((e) => {
505
+ throw disk(e);
506
+ })).size;
507
+ if (durable !== totalTransferred) {
508
+ throw new Error(`Partial download size mismatch for '${item.url}': tracked ${totalTransferred} bytes but persisted ${durable} bytes`);
431
509
  }
432
- catch (e) {
433
- if (e instanceof DownloadRequestError && e.kind === 'restart') {
434
- try {
435
- res = await this.request(fetchImpl, item, headers, 0, expectedSize, signal);
436
- writer = createWriteStream(tmpPath, { flags: 'w' });
437
- progress.set(fileId, 0);
438
- totalTransferred = 0;
439
- delta = 0;
440
- sinceReset = 0;
441
- this.deps.log('warn', `Server cannot resume '${item.url}' (${e.message}); restarted from byte 0`);
442
- break;
510
+ for (;;) {
511
+ if (retryCount >= MAX_STREAM_RETRIES) {
512
+ throw new Error(`Download failed after ${MAX_STREAM_RETRIES} retries at byte ${durable}: ${streamError}`, { cause: streamError });
513
+ }
514
+ if (signal.aborted)
515
+ throw new Error(DOWNLOAD_CANCELLED);
516
+ this.deps.log('warn', `Stream error at byte ${durable} for '${item.url}': ${streamError}. Retry ${retryCount + 1}/${MAX_STREAM_RETRIES}`);
517
+ await this.deps.sleep(retryDelayMs(retryCount, this.deps.retryBaseMs), signal);
518
+ retryCount++;
519
+ try {
520
+ res = await this.request(fetchImpl, item, headers, durable, expectedSize, signal);
521
+ if (signal.aborted) {
522
+ await res.body?.cancel().catch(() => { });
523
+ throw new Error(DOWNLOAD_CANCELLED);
443
524
  }
444
- catch (e2) {
445
- if (e2 instanceof DownloadRequestError && e2.kind === 'retryable') {
446
- this.deps.log('warn', `Full-download reconnect for '${item.url}' failed: ${e2.message}`);
447
- continue;
525
+ writer = await openWriteStream(tmpPath, 'a', disk).catch(async (e) => {
526
+ await res.body?.cancel().catch(() => { });
527
+ throw e;
528
+ });
529
+ break;
530
+ }
531
+ catch (e) {
532
+ if (e instanceof DownloadRequestError && e.kind === 'restart') {
533
+ try {
534
+ res = await this.request(fetchImpl, item, headers, 0, expectedSize, signal);
535
+ if (signal.aborted) {
536
+ await res.body?.cancel().catch(() => { });
537
+ throw new Error(DOWNLOAD_CANCELLED);
538
+ }
539
+ writer = await openWriteStream(tmpPath, 'w', disk).catch(async (e2) => {
540
+ await res.body?.cancel().catch(() => { });
541
+ throw e2;
542
+ });
543
+ progress.set(fileId, 0);
544
+ totalTransferred = 0;
545
+ delta = 0;
546
+ sinceReset = 0;
547
+ this.deps.log('warn', `Server cannot resume '${item.url}' (${e.message}); restarted from byte 0`);
548
+ break;
549
+ }
550
+ catch (e2) {
551
+ if (e2 instanceof DownloadRequestError && e2.kind === 'retryable') {
552
+ this.deps.log('warn', `Full-download reconnect for '${item.url}' failed: ${e2.message}`);
553
+ continue;
554
+ }
555
+ throw rethrowAsString(e2);
448
556
  }
449
- throw rethrowAsString(e2);
450
557
  }
558
+ if (e instanceof DownloadRequestError && e.kind === 'retryable') {
559
+ this.deps.log('warn', `Range reconnect at byte ${durable} for '${item.url}' failed: ${e.message}`);
560
+ continue;
561
+ }
562
+ throw rethrowAsString(e);
451
563
  }
452
- if (e instanceof DownloadRequestError && e.kind === 'retryable') {
453
- this.deps.log('warn', `Range reconnect at byte ${durable} for '${item.url}' failed: ${e.message}`);
454
- continue;
455
- }
456
- throw rethrowAsString(e);
457
564
  }
565
+ body = res.body ?? new ReadableStream({ start: (c) => c.close() });
566
+ reader = body.getReader();
458
567
  }
459
- body = res.body ?? new ReadableStream({ start: (c) => c.close() });
460
- reader = body.getReader();
568
+ await writer.close();
569
+ }
570
+ finally {
571
+ await writer.close().catch(() => { });
572
+ await reader.cancel().catch(() => { });
461
573
  }
462
- await close();
463
574
  const persisted = (await stat(tmpPath).catch((e) => {
464
575
  throw disk(e);
465
576
  })).size;
@@ -484,7 +595,7 @@ export class Downloader {
484
595
  /** Request errors reach the caller as plain `Error`s with the Rust message text. */
485
596
  function rethrowAsString(e) {
486
597
  if (e instanceof DownloadRequestError)
487
- throw new Error(e.message);
598
+ throw new Error(e.message, { cause: e });
488
599
  throw e;
489
600
  }
490
601
  //# sourceMappingURL=downloader.js.map