comfyui-mcp 0.48.21 → 0.48.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/comfyui/client.js +46 -6
- package/dist/comfyui/client.js.map +1 -1
- package/dist/config.js +15 -0
- package/dist/config.js.map +1 -1
- package/dist/orchestrator/error-text.js +29 -1
- package/dist/orchestrator/error-text.js.map +1 -1
- package/dist/orchestrator/error-text.test.js +28 -0
- package/dist/orchestrator/error-text.test.js.map +1 -1
- package/dist/orchestrator/index.js +151 -50
- package/dist/orchestrator/index.js.map +1 -1
- package/dist/orchestrator/panel-agent.js +21 -4
- package/dist/orchestrator/panel-agent.js.map +1 -1
- package/dist/orchestrator/panel-tools.js +1098 -168
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/orchestrator/ready-banner.js +70 -0
- package/dist/orchestrator/ready-banner.js.map +1 -0
- package/dist/services/api-nodes.js +5 -7
- package/dist/services/api-nodes.js.map +1 -1
- package/dist/services/download-cache.js +126 -18
- package/dist/services/download-cache.js.map +1 -1
- package/dist/services/download-jobs.js +463 -14
- package/dist/services/download-jobs.js.map +1 -1
- package/dist/services/download-progress.js +247 -2
- package/dist/services/download-progress.js.map +1 -1
- package/dist/services/env-capabilities.js +80 -9
- package/dist/services/env-capabilities.js.map +1 -1
- package/dist/services/generate-audio.js +16 -0
- package/dist/services/generate-audio.js.map +1 -1
- package/dist/services/local-models-fallback.js +7 -3
- package/dist/services/local-models-fallback.js.map +1 -1
- package/dist/services/manifest.js +180 -65
- package/dist/services/manifest.js.map +1 -1
- package/dist/services/model-resolver.js +267 -11
- package/dist/services/model-resolver.js.map +1 -1
- package/dist/services/node-management.js +38 -27
- package/dist/services/node-management.js.map +1 -1
- package/dist/services/output-dir.js +33 -3
- package/dist/services/output-dir.js.map +1 -1
- package/dist/services/panel-secrets.js +19 -7
- package/dist/services/panel-secrets.js.map +1 -1
- package/dist/services/queue-monitor.js +45 -2
- package/dist/services/queue-monitor.js.map +1 -1
- package/dist/services/queue-monitor.stall.test.js +78 -0
- package/dist/services/queue-monitor.stall.test.js.map +1 -0
- package/dist/services/secure-bridge.js +84 -0
- package/dist/services/secure-bridge.js.map +1 -1
- package/dist/services/storage/azure-blob.js +8 -3
- package/dist/services/storage/azure-blob.js.map +1 -1
- package/dist/services/storage/index.js +3 -3
- package/dist/services/storage/index.js.map +1 -1
- package/dist/services/storage/s3.js +9 -3
- package/dist/services/storage/s3.js.map +1 -1
- package/dist/services/ui-bridge.js +294 -24
- package/dist/services/ui-bridge.js.map +1 -1
- package/dist/services/workflow-converter.js +767 -72
- package/dist/services/workflow-converter.js.map +1 -1
- package/dist/services/workflow-lock.js +127 -27
- package/dist/services/workflow-lock.js.map +1 -1
- package/dist/services/workspace-env.js +48 -0
- package/dist/services/workspace-env.js.map +1 -1
- package/dist/tools/generate-audio.js +44 -0
- package/dist/tools/generate-audio.js.map +1 -1
- package/dist/tools/model-extras.js +24 -4
- package/dist/tools/model-extras.js.map +1 -1
- package/dist/tools/model-management.js +124 -14
- package/dist/tools/model-management.js.map +1 -1
- package/dist/tools/report-issue.js +220 -66
- package/dist/tools/report-issue.js.map +1 -1
- package/dist/tools/report-issue.test.js +223 -83
- package/dist/tools/report-issue.test.js.map +1 -1
- package/dist/tools/skills-access.js +7 -2
- package/dist/tools/skills-access.js.map +1 -1
- package/dist/tools/template-schema.js +5 -5
- package/dist/tools/template-schema.js.map +1 -1
- package/dist/tools/workflow-compose.js +18 -3
- package/dist/tools/workflow-compose.js.map +1 -1
- package/package.json +1 -1
- package/packs/anima/install-runpod.sh +0 -1
- package/packs/anima/install-windows.bat +0 -1
- package/packs/anima/manifest.yaml +0 -1
- package/packs/anima-img2img/install-runpod.sh +0 -1
- package/packs/anima-img2img/install-windows.bat +0 -1
- package/packs/anima-img2img/manifest.yaml +0 -1
- package/packs/anima-inpaint/install-runpod.sh +0 -1
- package/packs/anima-inpaint/install-windows.bat +0 -1
- package/packs/anima-inpaint/manifest.yaml +0 -1
- package/packs/anima-txt2img/install-runpod.sh +0 -1
- package/packs/anima-txt2img/install-windows.bat +0 -1
- package/packs/anima-txt2img/manifest.yaml +0 -1
- package/packs/artokun-flow/install-runpod.sh +0 -1
- package/packs/artokun-flow/install-windows.bat +0 -1
- package/packs/artokun-flow/manifest.yaml +0 -1
- package/packs/ernie/install-runpod.sh +0 -1
- package/packs/ernie/install-windows.bat +0 -1
- package/packs/ernie/manifest.yaml +0 -1
- package/packs/ernie-combo/install-runpod.sh +0 -1
- package/packs/ernie-combo/install-windows.bat +0 -1
- package/packs/ernie-combo/manifest.yaml +0 -1
- package/packs/ernie-img2img/install-runpod.sh +0 -1
- package/packs/ernie-img2img/install-windows.bat +0 -1
- package/packs/ernie-img2img/manifest.yaml +0 -1
- package/packs/ernie-txt2img/install-runpod.sh +0 -1
- package/packs/ernie-txt2img/install-windows.bat +0 -1
- package/packs/ernie-txt2img/manifest.yaml +0 -1
- package/packs/ideogram/install-runpod.sh +0 -1
- package/packs/ideogram/install-windows.bat +0 -1
- package/packs/ideogram/manifest.yaml +0 -1
- package/packs/ideogram-img2img/install-runpod.sh +0 -1
- package/packs/ideogram-img2img/install-windows.bat +0 -1
- package/packs/ideogram-img2img/manifest.yaml +0 -1
- package/packs/ideogram-txt2img/install-runpod.sh +0 -1
- package/packs/ideogram-txt2img/install-windows.bat +0 -1
- package/packs/ideogram-txt2img/manifest.yaml +0 -1
- package/packs/ltx-2.3/install-runpod.sh +0 -1
- package/packs/ltx-2.3/install-windows.bat +0 -1
- package/packs/ltx-2.3/manifest.yaml +0 -1
- package/packs/ltx-2.3-extender/install-runpod.sh +0 -1
- package/packs/ltx-2.3-extender/install-windows.bat +0 -1
- package/packs/ltx-2.3-extender/manifest.yaml +0 -1
- package/packs/ltx-2.3-extender-no-audio/install-runpod.sh +0 -1
- package/packs/ltx-2.3-extender-no-audio/install-windows.bat +0 -1
- package/packs/ltx-2.3-extender-no-audio/manifest.yaml +0 -1
- package/packs/ltx-2.3-flf/install-runpod.sh +0 -1
- package/packs/ltx-2.3-flf/install-windows.bat +0 -1
- package/packs/ltx-2.3-flf/manifest.yaml +0 -1
- package/packs/ltx-2.3-img2vid/install-runpod.sh +0 -1
- package/packs/ltx-2.3-img2vid/install-windows.bat +0 -1
- package/packs/ltx-2.3-img2vid/manifest.yaml +3 -4
- package/packs/ltx-2.3-txt2vid/install-runpod.sh +0 -1
- package/packs/ltx-2.3-txt2vid/install-windows.bat +0 -1
- package/packs/ltx-2.3-txt2vid/manifest.yaml +3 -4
- package/packs/ltx-2.3-xy-plot/install-runpod.sh +0 -1
- package/packs/ltx-2.3-xy-plot/install-windows.bat +0 -1
- package/packs/ltx-2.3-xy-plot/manifest.yaml +0 -1
- package/packs/ltx23-distill-3stage/install-runpod.sh +0 -1
- package/packs/ltx23-distill-3stage/install-windows.bat +0 -1
- package/packs/ltx23-distill-3stage/manifest.yaml +0 -1
- package/packs/qwen-image/install-runpod.sh +0 -1
- package/packs/qwen-image/install-windows.bat +0 -1
- package/packs/qwen-image/manifest.yaml +0 -1
- package/packs/qwen-image-edit/install-runpod.sh +0 -1
- package/packs/qwen-image-edit/install-windows.bat +0 -1
- package/packs/qwen-image-edit/manifest.yaml +0 -1
- package/packs/qwen-image-edit-edit/install-runpod.sh +0 -1
- package/packs/qwen-image-edit-edit/install-windows.bat +0 -1
- package/packs/qwen-image-edit-edit/manifest.yaml +0 -1
- package/packs/wan-animate/install-runpod.sh +0 -1
- package/packs/wan-animate/install-windows.bat +0 -1
- package/packs/wan-animate/manifest.yaml +0 -1
- package/packs/wan-animate-character/install-runpod.sh +0 -1
- package/packs/wan-animate-character/install-windows.bat +0 -1
- package/packs/wan-animate-character/manifest.yaml +0 -1
- package/packs/wan-animate-ofm/install-runpod.sh +0 -1
- package/packs/wan-animate-ofm/install-windows.bat +0 -1
- package/packs/wan-animate-ofm/manifest.yaml +0 -1
- package/packs/wan-longer-videos/install-runpod.sh +0 -1
- package/packs/wan-longer-videos/install-windows.bat +0 -1
- package/packs/wan-longer-videos/manifest.yaml +0 -1
- package/packs/wan-longer-videos-i2v/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-i2v/install-windows.bat +0 -1
- package/packs/wan-longer-videos-i2v/manifest.yaml +0 -1
- package/packs/wan-longer-videos-i2v-96gb/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-i2v-96gb/install-windows.bat +0 -1
- package/packs/wan-longer-videos-i2v-96gb/manifest.yaml +0 -1
- package/packs/wan-longer-videos-t2v/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-t2v/install-windows.bat +0 -1
- package/packs/wan-longer-videos-t2v/manifest.yaml +0 -1
- package/packs/wan-longer-videos-t2v-96gb/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-t2v-96gb/install-windows.bat +0 -1
- package/packs/wan-longer-videos-t2v-96gb/manifest.yaml +0 -1
- package/packs/wan-longer-videos-v2v/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-v2v/install-windows.bat +0 -1
- package/packs/wan-longer-videos-v2v/manifest.yaml +0 -1
- package/packs/wan-longer-videos-v2v-96gb/install-runpod.sh +0 -1
- package/packs/wan-longer-videos-v2v-96gb/install-windows.bat +0 -1
- package/packs/wan-longer-videos-v2v-96gb/manifest.yaml +0 -1
- package/packs/wan-multitalk/install-runpod.sh +0 -1
- package/packs/wan-multitalk/install-windows.bat +0 -1
- package/packs/wan-multitalk/manifest.yaml +0 -1
- package/packs/wan-pusa-extend/install-runpod.sh +0 -1
- package/packs/wan-pusa-extend/install-windows.bat +0 -1
- package/packs/wan-pusa-extend/manifest.yaml +0 -1
- package/packs/wan-transparent/install-runpod.sh +0 -1
- package/packs/wan-transparent/install-windows.bat +0 -1
- package/packs/wan-transparent/manifest.yaml +0 -1
- package/packs/wan-transparent-img2vid/install-runpod.sh +0 -1
- package/packs/wan-transparent-img2vid/install-windows.bat +0 -1
- package/packs/wan-transparent-img2vid/manifest.yaml +0 -1
- package/packs/wan-transparent-img2vid-96gb/install-runpod.sh +0 -1
- package/packs/wan-transparent-img2vid-96gb/install-windows.bat +0 -1
- package/packs/wan-transparent-img2vid-96gb/manifest.yaml +0 -1
- package/packs/z-image-base/install-runpod.sh +0 -1
- package/packs/z-image-base/install-windows.bat +0 -1
- package/packs/z-image-base/manifest.yaml +0 -1
- package/packs/z-image-base-combo/install-runpod.sh +0 -1
- package/packs/z-image-base-combo/install-windows.bat +0 -1
- package/packs/z-image-base-combo/manifest.yaml +0 -1
- package/packs/z-image-base-controlnet/install-runpod.sh +0 -1
- package/packs/z-image-base-controlnet/install-windows.bat +0 -1
- package/packs/z-image-base-controlnet/manifest.yaml +0 -1
- package/packs/z-image-base-img2img/install-runpod.sh +0 -1
- package/packs/z-image-base-img2img/install-windows.bat +0 -1
- package/packs/z-image-base-img2img/manifest.yaml +0 -1
- package/packs/z-image-base-inpaint/install-runpod.sh +0 -1
- package/packs/z-image-base-inpaint/install-windows.bat +0 -1
- package/packs/z-image-base-inpaint/manifest.yaml +0 -1
- package/packs/z-image-base-txt2img/install-runpod.sh +0 -1
- package/packs/z-image-base-txt2img/install-windows.bat +0 -1
- package/packs/z-image-base-txt2img/manifest.yaml +0 -1
- package/packs/z-image-turbo/install-runpod.sh +0 -1
- package/packs/z-image-turbo/install-windows.bat +0 -1
- package/packs/z-image-turbo/manifest.yaml +0 -1
- package/packs/z-image-turbo-combo/install-runpod.sh +0 -1
- package/packs/z-image-turbo-combo/install-windows.bat +0 -1
- package/packs/z-image-turbo-combo/manifest.yaml +0 -1
- package/packs/z-image-turbo-controlnet/install-runpod.sh +0 -1
- package/packs/z-image-turbo-controlnet/install-windows.bat +0 -1
- package/packs/z-image-turbo-controlnet/manifest.yaml +0 -1
- package/packs/z-image-turbo-detail-daemon/install-runpod.sh +0 -1
- package/packs/z-image-turbo-detail-daemon/install-windows.bat +0 -1
- package/packs/z-image-turbo-detail-daemon/manifest.yaml +0 -1
- package/packs/z-image-turbo-img2img/install-runpod.sh +0 -1
- package/packs/z-image-turbo-img2img/install-windows.bat +0 -1
- package/packs/z-image-turbo-img2img/manifest.yaml +0 -1
- package/packs/z-image-turbo-inpainting/install-runpod.sh +0 -1
- package/packs/z-image-turbo-inpainting/install-windows.bat +0 -1
- package/packs/z-image-turbo-inpainting/manifest.yaml +0 -1
- package/packs/z-image-turbo-txt2img/install-runpod.sh +0 -1
- package/packs/z-image-turbo-txt2img/install-windows.bat +0 -1
- package/packs/z-image-turbo-txt2img/manifest.yaml +0 -1
- package/packs/z-image-xy-plot/install-runpod.sh +0 -1
- package/packs/z-image-xy-plot/install-windows.bat +0 -1
- package/packs/z-image-xy-plot/manifest.yaml +0 -1
- package/scripts/test-packs.sh +8 -3
|
@@ -17,7 +17,18 @@ import { createHash } from "node:crypto";
|
|
|
17
17
|
import { realpath } from "node:fs/promises";
|
|
18
18
|
import { basename, dirname, join } from "node:path";
|
|
19
19
|
import { downloadModel, resolveDownloadTarget, shouldDispatchDownloadToManager, } from "./model-resolver.js";
|
|
20
|
+
import { ModelError } from "../utils/errors.js";
|
|
21
|
+
import { persistDownloadJob, readPersistedDownloadJob, listPersistedDownloadJobs, findPersistedDownloadJob, clearDownloadProgress, persistedRecordsEnabled, PERSIST_OWNER, PERSISTED_INFLIGHT_STALE_MS, } from "./download-progress.js";
|
|
20
22
|
import { logger } from "../utils/logger.js";
|
|
23
|
+
/** How often an in-flight job re-persists its record (liveness heartbeat). Must stay
|
|
24
|
+
* comfortably below PERSISTED_INFLIGHT_STALE_MS so a live download is always fresh. */
|
|
25
|
+
const HEARTBEAT_MS = 15_000;
|
|
26
|
+
/** Cap on heartbeat retries of a transiently-failing TERMINAL persist. Chosen so the
|
|
27
|
+
* total window (attempts × HEARTBEAT_MS) exceeds PERSISTED_INFLIGHT_STALE_MS — by then
|
|
28
|
+
* the last-successful (in-flight) record has already aged out via the stale reap, so
|
|
29
|
+
* giving up can't leave a fresh, adoptable record. Prevents a permanently-unwritable
|
|
30
|
+
* progress store from keeping a COMPLETED job's interval doing filesystem work forever. */
|
|
31
|
+
const TERMINAL_PERSIST_MAX_ATTEMPTS = 6; // 6 × 15s = 90s > 60s stale window
|
|
21
32
|
// The in-flight registry is indexed under MULTIPLE keys per job so dedup is
|
|
22
33
|
// ROUTE-INDEPENDENT: a repeated request finds the in-flight job whether or not the
|
|
23
34
|
// Manager↔local route flipped between calls (#420 codex round 2). One Entry object
|
|
@@ -281,6 +292,57 @@ onComplete) {
|
|
|
281
292
|
});
|
|
282
293
|
return adopted;
|
|
283
294
|
}
|
|
295
|
+
// #529 double-writer guard: no in-flight job in THIS process, but ANOTHER session may
|
|
296
|
+
// already be running this EXACT download (same public id) — e.g. a reconnect reissued
|
|
297
|
+
// the same URL/destination. Adopt its persisted in-flight record instead of starting a
|
|
298
|
+
// SECOND physical writer for one file. Only a FRESH in-flight record from a DIFFERENT
|
|
299
|
+
// owner counts (the scan below filters stale via the heartbeat window; and a terminal
|
|
300
|
+
// record — done/cancelled — is NOT "downloading", so a finished/failed prior download
|
|
301
|
+
// correctly falls through to a fresh re-download). This
|
|
302
|
+
// process's own live jobs were already checked above. The adopted view is READ-ONLY (we
|
|
303
|
+
// hold no handle on the other session's writer): it is NOT registered in this registry,
|
|
304
|
+
// runs no writer/heartbeat/AbortController, and its `settled` resolves immediately — the
|
|
305
|
+
// tool then reports it as in-flight and the caller polls download_status (which reads
|
|
306
|
+
// the live persisted record) for the resolved state.
|
|
307
|
+
//
|
|
308
|
+
// SCOPE: this dedup is BEST-EFFORT and covers the reported case — a SEQUENTIAL reconnect
|
|
309
|
+
// that reissues after another session already published its record. It is a
|
|
310
|
+
// filesystem-level read-then-start, NOT an atomic cross-process claim, so two DISTINCT
|
|
311
|
+
// processes reissuing the SAME download at the SAME instant (both reading before either
|
|
312
|
+
// publishes) can still both start writers. That is not a regression (it is the
|
|
313
|
+
// pre-existing behavior the adoption improves for the common case) and is NON-CORRUPTING:
|
|
314
|
+
// the #467 machinery materializes each writer through its OWN O_EXCL temp + atomic rename
|
|
315
|
+
// (last-writer-wins on the destination only, never a shared cache inode) and validates
|
|
316
|
+
// the payload (#473), so the only cost of that rare race is a duplicate download — never
|
|
317
|
+
// a corrupt file. A full distributed lease is deliberately out of scope (its stale-claim
|
|
318
|
+
// / crash-cleanup failure modes would be worse than a rare duplicate transfer).
|
|
319
|
+
// Scan ROUTE-INDEPENDENTLY (#420): match a foreign fresh in-flight record by the public
|
|
320
|
+
// `id` OR the route-independent request key `reqKey`, so a reconnect whose route flipped
|
|
321
|
+
// local↔Manager (which changes the id from a destination hash to a request hash) still
|
|
322
|
+
// finds the in-flight record instead of starting a second writer. Require the SAME source
|
|
323
|
+
// URL (trayId): a foreign live download of a DIFFERENT url to the same dest+auth (same
|
|
324
|
+
// id, different trayId) is a distinct logical download whose bytes may differ — adopting
|
|
325
|
+
// it would report the WRONG job, so it is declined (we proceed with our own request). A
|
|
326
|
+
// reqKey match already implies the same url (reqKey embeds it), so trayId is consistent.
|
|
327
|
+
const nowForAdopt = Date.now();
|
|
328
|
+
const foreign = listPersistedDownloadJobs().find((rec) => rec.owner !== PERSIST_OWNER &&
|
|
329
|
+
rec.status === "downloading" &&
|
|
330
|
+
nowForAdopt - (rec.updated ?? 0) < PERSISTED_INFLIGHT_STALE_MS &&
|
|
331
|
+
rec.trayId === trayId &&
|
|
332
|
+
(rec.id === id || (rec.req_key !== undefined && rec.req_key === reqKey)));
|
|
333
|
+
if (foreign) {
|
|
334
|
+
logger.info(`Adopting a cross-session in-flight download (no second writer): ${foreign.id}`, {
|
|
335
|
+
url,
|
|
336
|
+
target_subfolder: targetSubfolder,
|
|
337
|
+
filename,
|
|
338
|
+
});
|
|
339
|
+
return {
|
|
340
|
+
job: jobFromPersisted(foreign),
|
|
341
|
+
settled: Promise.resolve(),
|
|
342
|
+
keys: [],
|
|
343
|
+
controller: new AbortController(),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
284
346
|
// No in-flight match. Retire any superseded (done/error) entries shadowing our keys
|
|
285
347
|
// — entry-scoped, so we only clear rows still pointing at that finished entry and
|
|
286
348
|
// never delete a row now owned by a different, live writer (rule 2).
|
|
@@ -300,7 +362,17 @@ onComplete) {
|
|
|
300
362
|
filename,
|
|
301
363
|
status: "downloading",
|
|
302
364
|
started_at: Date.now(),
|
|
365
|
+
destKey: serializeKey,
|
|
366
|
+
reqKey,
|
|
367
|
+
viaManager: dispatchToManager,
|
|
303
368
|
};
|
|
369
|
+
// Per-download abort handle (#515). The signal is threaded through downloadModel
|
|
370
|
+
// into the fetch + stream pipeline, so cancel_download aborts exactly THIS job.
|
|
371
|
+
const controller = new AbortController();
|
|
372
|
+
// The liveness heartbeat timer (assigned below, after the settled closure). Hoisted
|
|
373
|
+
// here so the settled closure's finally can clear it once the terminal state is durably
|
|
374
|
+
// persisted. Runs async — assigned before it ever fires or the finally runs.
|
|
375
|
+
let heartbeat;
|
|
304
376
|
// Serialize behind any in-flight job writing the SAME destination (#467 P1-C) so
|
|
305
377
|
// this job's download+materialize+onComplete run without a concurrent different-
|
|
306
378
|
// auth writer swapping the destination out from under its callback.
|
|
@@ -309,16 +381,51 @@ onComplete) {
|
|
|
309
381
|
// would take down the process on a simple 404.
|
|
310
382
|
// The physical download reports its resume decision straight onto THIS job — no
|
|
311
383
|
// shared keyed map, so it can never be misattributed to another job (#467).
|
|
384
|
+
// Commit the DONE state. Invoked SYNCHRONOUSLY the instant the file is renamed into
|
|
385
|
+
// its destination (via the onLanded callback below) — before any later await — so
|
|
386
|
+
// there is NO window where the file exists at the destination yet the job still reads
|
|
387
|
+
// "downloading" (which a cancel would otherwise flip to "cancelled"). Idempotent and
|
|
388
|
+
// only advances a still-"downloading" job, so it never overrides a real terminal
|
|
389
|
+
// state. Reads status as the full union to dodge the closure's "downloading" narrowing.
|
|
390
|
+
const commitDone = (landedPath) => {
|
|
391
|
+
if (job.status !== "downloading")
|
|
392
|
+
return;
|
|
393
|
+
job.path = landedPath;
|
|
394
|
+
job.status = "done";
|
|
395
|
+
job.finished_at = Date.now();
|
|
396
|
+
persistJobRecord(job);
|
|
397
|
+
};
|
|
312
398
|
const settled = (async () => {
|
|
313
399
|
// Wait for the prior same-destination job to fully finish (never fail THIS job
|
|
314
400
|
// because that one errored — swallow its result).
|
|
315
401
|
if (priorSameDest)
|
|
316
402
|
await priorSameDest.catch(() => undefined);
|
|
317
403
|
try {
|
|
404
|
+
// A cancel that arrived before (or while waiting for) our turn makes downloadModel
|
|
405
|
+
// throw at its up-front abort guard → the catch records the cancellation. So there
|
|
406
|
+
// is no separate pre-start branch: the download either runs to a materialized file
|
|
407
|
+
// (done) or is aborted before the file lands (cancelled).
|
|
318
408
|
const path = await downloadModel(url, targetSubfolder, filename, auth, dispatchToManager, (d) => {
|
|
319
409
|
job.resume = d;
|
|
320
|
-
})
|
|
321
|
-
|
|
410
|
+
}, controller.signal, (progressId) => {
|
|
411
|
+
// Record the id the tray rows are ACTUALLY written under (post-auth/HF
|
|
412
|
+
// rewrite) as job.progressId — WITHOUT touching job.trayId, which must stay
|
|
413
|
+
// the stable original-URL hash so URL reconnect adoption (#529) still
|
|
414
|
+
// resolves. download_status byte display and cancel cleanup key on
|
|
415
|
+
// progressId (falling back to trayId); it only differs for query-auth /
|
|
416
|
+
// mirror-rewritten URLs. Persist so a reconnecting session reads live bytes.
|
|
417
|
+
if (progressId && progressId !== job.progressId) {
|
|
418
|
+
job.progressId = progressId;
|
|
419
|
+
persistJobRecord(job);
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
// onLanded: fires the moment the local file is renamed into place → commit done
|
|
423
|
+
// synchronously, closing the rename→return window.
|
|
424
|
+
commitDone);
|
|
425
|
+
// Local paths already committed done via onLanded at the rename. The remote Manager
|
|
426
|
+
// dispatch has no local rename, so commit done here when it returns (dispatch
|
|
427
|
+
// accepted — the viaManager flag marks it as unverified in the tools). Idempotent.
|
|
428
|
+
commitDone(path);
|
|
322
429
|
if (onComplete) {
|
|
323
430
|
// Post-processing must not turn a landed file into a failed download —
|
|
324
431
|
// the bytes are on disk either way, and reporting "error" here would
|
|
@@ -332,13 +439,42 @@ onComplete) {
|
|
|
332
439
|
];
|
|
333
440
|
}
|
|
334
441
|
}
|
|
335
|
-
job.status = "done";
|
|
336
|
-
job.finished_at = Date.now();
|
|
337
442
|
}
|
|
338
443
|
catch (err) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
job.
|
|
444
|
+
// If the file ALREADY landed (onLanded committed done) a later throw — e.g. an LRU
|
|
445
|
+
// eviction hiccup after the rename — must NOT override a real completed download.
|
|
446
|
+
if (job.status === "done") {
|
|
447
|
+
// keep done
|
|
448
|
+
}
|
|
449
|
+
else if (controller.signal.aborted) {
|
|
450
|
+
// An abort that stopped the transfer BEFORE the file landed surfaces here as a
|
|
451
|
+
// rejected fetch/pipeline (or a guard throw) — a clean cancellation, never an
|
|
452
|
+
// "error" and never a false success.
|
|
453
|
+
finalizeCancelled(job);
|
|
454
|
+
// …but if the cancellation cleanup threw a recovery-critical ModelError (e.g. the
|
|
455
|
+
// Windows backup of the PREVIOUS destination file could not be restored, so it's
|
|
456
|
+
// preserved under a random .bak path), surface that message on the job so
|
|
457
|
+
// download_status shows the recoverable path instead of masking it behind a plain
|
|
458
|
+
// "cancelled, resumable partial". (Ordinary cancellation throws an AbortError,
|
|
459
|
+
// which is NOT a ModelError, so it never sets this.)
|
|
460
|
+
if (err instanceof ModelError)
|
|
461
|
+
job.error = err.message;
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
job.status = "error";
|
|
465
|
+
job.error = err instanceof Error ? err.message : String(err);
|
|
466
|
+
job.finished_at = Date.now();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
finally {
|
|
470
|
+
// Persist the terminal state so a reconnecting session sees the resolved
|
|
471
|
+
// outcome (#529) instead of a forever-"downloading" record. If this atomic
|
|
472
|
+
// replace transiently fails (rare), the heartbeat below KEEPS retrying until the
|
|
473
|
+
// terminal state is durable — so a done/cancelled job can't linger as a
|
|
474
|
+
// fresh-and-adoptable "downloading" record (beyond the stale reap that already
|
|
475
|
+
// bounds it). Only once the terminal record is durable does the heartbeat stop.
|
|
476
|
+
if (persistJobRecord(job) && heartbeat)
|
|
477
|
+
clearInterval(heartbeat);
|
|
342
478
|
}
|
|
343
479
|
})();
|
|
344
480
|
// Make THIS job the tail of its destination's serialization chain, and prune the
|
|
@@ -351,31 +487,344 @@ onComplete) {
|
|
|
351
487
|
// Index under EVERY key (deduped) so any of them adopts this one writer. Uses the
|
|
352
488
|
// entry-scoped registerKey guard so a fresh registration can never overwrite a row
|
|
353
489
|
// still owned by a different, live writer (rule 3).
|
|
354
|
-
const entry = { job, settled, keys: [] };
|
|
490
|
+
const entry = { job, settled, keys: [], controller };
|
|
355
491
|
for (const k of new Set(lookupKeys))
|
|
356
492
|
registerKey(entry, k);
|
|
493
|
+
// Persist the (downloading) record so a session that reconnects while this is in
|
|
494
|
+
// flight can still resolve/adopt it by id or URL/destination (#529).
|
|
495
|
+
persistJobRecord(job);
|
|
496
|
+
// Liveness heartbeat: while in flight, refresh the persisted record's `updated`
|
|
497
|
+
// stamp so ANOTHER session can distinguish this LIVE download from a crashed one
|
|
498
|
+
// (its heartbeat stops) when deciding whether to preserve a shared tray row. Cheap
|
|
499
|
+
// (a small write every 15s, only under the panel where persistence is active) and
|
|
500
|
+
// unref'd so it never keeps the process alive.
|
|
501
|
+
// Only run the heartbeat when the persisted store is actually active (panel). Without a
|
|
502
|
+
// channel dir there is nothing to persist and no reader to serve — an interval there
|
|
503
|
+
// would just leak, retrying a no-op forever (persistJobRecord returns false, so the
|
|
504
|
+
// terminal cleanup below would never clear it). Plain non-panel downloads install none.
|
|
505
|
+
if (persistedRecordsEnabled()) {
|
|
506
|
+
let terminalPersistAttempts = 0;
|
|
507
|
+
heartbeat = setInterval(() => {
|
|
508
|
+
// In-flight: refresh liveness so another session can tell this live download from a
|
|
509
|
+
// crashed one. Terminal (only reached when the settled finally's terminal persist
|
|
510
|
+
// transiently FAILED to atomically replace): keep retrying until it's durable, then
|
|
511
|
+
// stop — so a done/cancelled job never lingers as a fresh, adoptable "downloading".
|
|
512
|
+
const durable = persistJobRecord(job);
|
|
513
|
+
if (job.status !== "downloading") {
|
|
514
|
+
// Stop the interval once the terminal state is durable, OR the retry budget is
|
|
515
|
+
// spent (by which point the stale record is already reaped), OR persistence went
|
|
516
|
+
// inactive — never let a completed job's interval do filesystem work forever.
|
|
517
|
+
if ((durable ||
|
|
518
|
+
++terminalPersistAttempts >= TERMINAL_PERSIST_MAX_ATTEMPTS ||
|
|
519
|
+
!persistedRecordsEnabled()) &&
|
|
520
|
+
heartbeat) {
|
|
521
|
+
clearInterval(heartbeat);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}, HEARTBEAT_MS);
|
|
525
|
+
if (typeof heartbeat.unref === "function")
|
|
526
|
+
heartbeat.unref();
|
|
527
|
+
entry.heartbeat = heartbeat;
|
|
528
|
+
}
|
|
357
529
|
return entry;
|
|
358
530
|
}
|
|
531
|
+
/** Mark a job cancelled: never a false-complete, and drop its tray row. The
|
|
532
|
+
* resumable .partial is deliberately LEFT on disk (a later download resumes it). */
|
|
533
|
+
function finalizeCancelled(job) {
|
|
534
|
+
job.status = "cancelled";
|
|
535
|
+
if (job.finished_at === undefined)
|
|
536
|
+
job.finished_at = Date.now();
|
|
537
|
+
// Remove the panel tray row so a cancelled download doesn't linger — but clear it
|
|
538
|
+
// ONLY when this job exclusively owns that physical row. Two subtleties:
|
|
539
|
+
// - A job with no progressId never wrote a row (the writer reports progressId
|
|
540
|
+
// BEFORE the first row), so there is nothing to clear.
|
|
541
|
+
// - Same-URL siblings can SHARE one physical stream/row: a coalesced consumer (same
|
|
542
|
+
// URL+auth, different destination) or a serialized same-auth sibling observes the
|
|
543
|
+
// OWNER's progressId. Clearing it while ANOTHER in-flight job still uses it would
|
|
544
|
+
// wipe that active job's live display. So skip the clear when any other in-flight
|
|
545
|
+
// job shares this progressId; the last one out clears it. (trayId is deliberately
|
|
546
|
+
// NOT a fallback — it's the original-URL hash siblings share even more broadly.)
|
|
547
|
+
if (!job.progressId)
|
|
548
|
+
return;
|
|
549
|
+
const sharedByLocal = [...new Set(jobs.values())].some((e) => e.job !== job && e.job.status === "downloading" && e.job.progressId === job.progressId);
|
|
550
|
+
// Also honor a live sibling in ANOTHER session (#529): a persisted in-flight record
|
|
551
|
+
// written by a DIFFERENT session (owner ≠ this process's PERSIST_OWNER) that shares
|
|
552
|
+
// this progressId is another session's active download of the same URL — its tray row
|
|
553
|
+
// must not be wiped. Comparing by OWNER (not id) catches the case two sessions run the
|
|
554
|
+
// SAME logical download (identical deterministic id): they persist distinct
|
|
555
|
+
// owner-scoped files, so the other session's record is still seen here. This process's
|
|
556
|
+
// OWN persisted records (same owner) are excluded — they always correspond to an
|
|
557
|
+
// in-memory job already covered by the local scan above. If any live sibling exists in
|
|
558
|
+
// either store, leave the row for the last one out (or the orchestrator's dead-writer
|
|
559
|
+
// prune) to clear.
|
|
560
|
+
const now = Date.now();
|
|
561
|
+
const sharedByPersisted = listPersistedDownloadJobs().some((rec) => rec.owner !== PERSIST_OWNER &&
|
|
562
|
+
rec.status === "downloading" &&
|
|
563
|
+
rec.progressId === job.progressId &&
|
|
564
|
+
// Only a FRESH record counts as a live sibling — a crashed session's heartbeat
|
|
565
|
+
// stops, so its record goes stale and must NOT permanently suppress this sole
|
|
566
|
+
// job's cleanup (its tray row would otherwise linger). Bounded by the heartbeat
|
|
567
|
+
// interval so a genuinely-live foreign download is always seen as fresh.
|
|
568
|
+
now - (rec.updated ?? 0) < PERSISTED_INFLIGHT_STALE_MS);
|
|
569
|
+
if (!sharedByLocal && !sharedByPersisted)
|
|
570
|
+
clearDownloadProgress(job.progressId);
|
|
571
|
+
}
|
|
572
|
+
/** Persist a job record to the cross-session store (progress dir), redacting the
|
|
573
|
+
* URL. No-op outside the panel. Keeps the persisted copy in step with the job.
|
|
574
|
+
* Returns whether the record was DURABLY replaced (so the heartbeat can retry a
|
|
575
|
+
* transiently-failing terminal persist). */
|
|
576
|
+
function persistJobRecord(job) {
|
|
577
|
+
return persistDownloadJob({
|
|
578
|
+
id: job.id,
|
|
579
|
+
trayId: job.trayId,
|
|
580
|
+
progressId: job.progressId,
|
|
581
|
+
url: job.url,
|
|
582
|
+
target_subfolder: job.target_subfolder,
|
|
583
|
+
filename: job.filename,
|
|
584
|
+
status: job.status,
|
|
585
|
+
path: job.path,
|
|
586
|
+
error: job.error,
|
|
587
|
+
started_at: job.started_at,
|
|
588
|
+
finished_at: job.finished_at,
|
|
589
|
+
notes: job.notes,
|
|
590
|
+
dest_key: job.destKey,
|
|
591
|
+
req_key: job.reqKey,
|
|
592
|
+
via_manager: job.viaManager,
|
|
593
|
+
resume: job.resume,
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
/** Rebuild an in-memory DownloadJob view from a persisted record (#529 adoption
|
|
597
|
+
* after a reconnect). It is a read-only snapshot — there is no live AbortController
|
|
598
|
+
* in THIS process for a job another/previous session started, so it can be polled
|
|
599
|
+
* by download_status but not cancelled from here. */
|
|
600
|
+
function jobFromPersisted(rec) {
|
|
601
|
+
return {
|
|
602
|
+
id: rec.id,
|
|
603
|
+
trayId: rec.trayId,
|
|
604
|
+
progressId: rec.progressId,
|
|
605
|
+
url: rec.url,
|
|
606
|
+
target_subfolder: rec.target_subfolder,
|
|
607
|
+
filename: rec.filename,
|
|
608
|
+
status: rec.status,
|
|
609
|
+
path: rec.path,
|
|
610
|
+
error: rec.error,
|
|
611
|
+
started_at: rec.started_at,
|
|
612
|
+
finished_at: rec.finished_at,
|
|
613
|
+
notes: rec.notes,
|
|
614
|
+
destKey: rec.dest_key,
|
|
615
|
+
reqKey: rec.req_key,
|
|
616
|
+
viaManager: rec.via_manager,
|
|
617
|
+
resume: rec.resume,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
/** True when a FRESH foreign in-flight persisted record shares `id` but carries a
|
|
621
|
+
* DIFFERENT trayId — a distinct concurrent physical download in ANOTHER session (two
|
|
622
|
+
* distinct URLs resolving to the same dest+auth). The id alone can't disambiguate, so
|
|
623
|
+
* a by-id lookup/cancel must decline rather than silently act on the local one.
|
|
624
|
+
* Excludes this process's own records (same owner) and stale/dead ones (heartbeat). */
|
|
625
|
+
function hasAmbiguousForeignSibling(id, localTrayId) {
|
|
626
|
+
const now = Date.now();
|
|
627
|
+
return listPersistedDownloadJobs().some((rec) => rec.id === id &&
|
|
628
|
+
rec.trayId !== localTrayId &&
|
|
629
|
+
rec.owner !== PERSIST_OWNER &&
|
|
630
|
+
rec.status === "downloading" &&
|
|
631
|
+
now - (rec.updated ?? 0) < PERSISTED_INFLIGHT_STALE_MS);
|
|
632
|
+
}
|
|
359
633
|
export function getDownloadJob(id) {
|
|
360
634
|
// The registry indexes each job under its request key and (when local) its
|
|
361
635
|
// destination key; the public id is one of those, so a direct get resolves it.
|
|
362
|
-
|
|
636
|
+
const live = jobs.get(id)?.job;
|
|
637
|
+
// A LIVE in-flight job in THIS process is authoritative (it's actively writing here) —
|
|
638
|
+
// but decline if a concurrent live FOREIGN session shares the id with a different trayId.
|
|
639
|
+
if (live && live.status === "downloading") {
|
|
640
|
+
if (hasAmbiguousForeignSibling(id, live.trayId))
|
|
641
|
+
return undefined;
|
|
642
|
+
return live;
|
|
643
|
+
}
|
|
644
|
+
// Otherwise resolve across this session's TERMINAL in-memory record AND the persisted
|
|
645
|
+
// store (#529), honoring the INTEGRITY TRUTH: a validated DONE (file landed) — from
|
|
646
|
+
// ANY session, in-memory or persisted — must WIN over a cancelled/error record for the
|
|
647
|
+
// same id. A cancel/error never lands a file, so it must never mask another session's
|
|
648
|
+
// validated-complete file (cancelled-over-complete), and this holds whether the
|
|
649
|
+
// cancelled/error record is in-memory or persisted.
|
|
650
|
+
if (live && live.status === "done")
|
|
651
|
+
return live;
|
|
652
|
+
const now = Date.now();
|
|
653
|
+
const matches = listPersistedDownloadJobs().filter((r) => r.id === id);
|
|
654
|
+
const persistedDone = matches
|
|
655
|
+
.filter((r) => r.status === "done")
|
|
656
|
+
.sort((a, b) => (b.updated ?? 0) - (a.updated ?? 0))[0];
|
|
657
|
+
if (persistedDone)
|
|
658
|
+
return jobFromPersisted(persistedDone);
|
|
659
|
+
// No DONE anywhere. Prefer a fresh live foreign in-flight download (it's still running
|
|
660
|
+
// elsewhere) — declining if ambiguous by trayId — then this session's own terminal
|
|
661
|
+
// record, then the newest persisted terminal.
|
|
662
|
+
const foreignLive = matches.filter((r) => r.status === "downloading" && now - (r.updated ?? 0) < PERSISTED_INFLIGHT_STALE_MS);
|
|
663
|
+
if (foreignLive.length > 0) {
|
|
664
|
+
if (new Set(foreignLive.map((r) => r.trayId)).size > 1)
|
|
665
|
+
return undefined; // ambiguous live
|
|
666
|
+
return jobFromPersisted(foreignLive.sort((a, b) => (b.updated ?? 0) - (a.updated ?? 0))[0]);
|
|
667
|
+
}
|
|
668
|
+
if (live)
|
|
669
|
+
return live; // this session's terminal (cancelled/error), no DONE to prefer
|
|
670
|
+
const terminal = matches.sort((a, b) => (b.updated ?? 0) - (a.updated ?? 0))[0];
|
|
671
|
+
return terminal ? jobFromPersisted(terminal) : undefined;
|
|
672
|
+
}
|
|
673
|
+
/** Adopt an in-flight download by URL or destination after a reconnect (#529) —
|
|
674
|
+
* so a caller can confirm a download is still running (and not start a duplicate)
|
|
675
|
+
* even without the id. Prefers a LIVE in-memory job, then the persisted store.
|
|
676
|
+
*
|
|
677
|
+
* URL matching is EXACT (query included): in-memory by raw url, persisted by the
|
|
678
|
+
* trayId hash of the full url — so two distinct signed/versioned URLs are never
|
|
679
|
+
* conflated (the persisted url is credential-redacted and can't be compared safely). */
|
|
680
|
+
export function findDownloadJob(query) {
|
|
681
|
+
const trayId = query.url ? downloadIdFor(query.url) : undefined;
|
|
682
|
+
const destKey = query.destKey;
|
|
683
|
+
if (!trayId && !destKey)
|
|
684
|
+
return undefined;
|
|
685
|
+
// Gather candidate IN-FLIGHT jobs from BOTH this process's registry AND the cross-
|
|
686
|
+
// session persisted store, deduped by id (a live in-memory copy wins over its
|
|
687
|
+
// persisted snapshot). The ambiguity guard must span BOTH stores: one session's live
|
|
688
|
+
// job for URL→destA plus another session's persisted in-flight job for URL→destB are
|
|
689
|
+
// two DISTINCT jobs for the same URL, and adopting either by URL alone would be a
|
|
690
|
+
// guess — so decline (the caller must use the exact id).
|
|
691
|
+
// Key candidates by (id, trayId): two distinct URLs to one dest+auth share an id but
|
|
692
|
+
// differ in trayId (distinct physical downloads), so id alone would wrongly collapse
|
|
693
|
+
// them and mask the ambiguity. A live in-memory copy wins over its persisted snapshot
|
|
694
|
+
// (same id+trayId key).
|
|
695
|
+
const keyOf = (id, tray) => `${id}\n${tray}`;
|
|
696
|
+
const now = Date.now();
|
|
697
|
+
const inflightByKey = new Map();
|
|
698
|
+
for (const e of new Set(jobs.values())) {
|
|
699
|
+
if (e.job.status !== "downloading")
|
|
700
|
+
continue;
|
|
701
|
+
if ((query.url && e.job.url === query.url) || (destKey && e.job.destKey === destKey)) {
|
|
702
|
+
inflightByKey.set(keyOf(e.job.id, e.job.trayId), e.job);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
for (const rec of listPersistedDownloadJobs()) {
|
|
706
|
+
// Only FRESH in-flight records count as live candidates — a stale/dead record
|
|
707
|
+
// (crashed session, never reaped) must not inflate the ambiguity count and force a
|
|
708
|
+
// false "no download" (matching the persisted helpers' fresh-in-flight rule).
|
|
709
|
+
if (rec.status !== "downloading" || now - (rec.updated ?? 0) >= PERSISTED_INFLIGHT_STALE_MS) {
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
const key = keyOf(rec.id, rec.trayId);
|
|
713
|
+
if (inflightByKey.has(key))
|
|
714
|
+
continue;
|
|
715
|
+
if ((trayId && rec.trayId === trayId) || (destKey && rec.dest_key === destKey)) {
|
|
716
|
+
inflightByKey.set(key, jobFromPersisted(rec));
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (inflightByKey.size > 1)
|
|
720
|
+
return undefined; // ambiguous across both stores
|
|
721
|
+
if (inflightByKey.size === 1)
|
|
722
|
+
return [...inflightByKey.values()][0];
|
|
723
|
+
// No in-flight match anywhere — fall back to a single unambiguous SETTLED persisted
|
|
724
|
+
// record (for status reporting); findPersistedDownloadJob declines if ambiguous.
|
|
725
|
+
const persisted = findPersistedDownloadJob({ trayId, destKey });
|
|
726
|
+
return persisted ? jobFromPersisted(persisted) : undefined;
|
|
363
727
|
}
|
|
364
728
|
export function listDownloadJobs() {
|
|
365
|
-
// One Entry is indexed under multiple keys — dedup by identity so a job appears
|
|
366
|
-
//
|
|
729
|
+
// One Entry is indexed under multiple keys — dedup by identity so a job appears once
|
|
730
|
+
// regardless of how many keys point at it. Identity is (id, trayId), NOT id alone:
|
|
731
|
+
// two distinct URLs to one dest+auth share an id but are distinct physical downloads
|
|
732
|
+
// (different trayId), and both must be listed — download_status with no selector
|
|
733
|
+
// promises EVERY tracked download.
|
|
367
734
|
const seen = new Set();
|
|
368
|
-
const
|
|
735
|
+
const keyOf = (j) => `${j.id}\n${j.trayId}`;
|
|
736
|
+
const byKey = new Map();
|
|
369
737
|
for (const e of jobs.values()) {
|
|
370
738
|
if (seen.has(e))
|
|
371
739
|
continue;
|
|
372
740
|
seen.add(e);
|
|
373
|
-
|
|
741
|
+
const cur = byKey.get(keyOf(e.job));
|
|
742
|
+
// Among this process's own entries for one key (rare), prefer a DONE.
|
|
743
|
+
if (!cur || (e.job.status === "done" && cur.status !== "done"))
|
|
744
|
+
byKey.set(keyOf(e.job), e.job);
|
|
374
745
|
}
|
|
375
|
-
|
|
746
|
+
// #529: fold in persisted records for jobs THIS session's registry doesn't hold
|
|
747
|
+
// (started before a reconnect), so download_status still lists in-flight downloads.
|
|
748
|
+
// INTEGRITY TRUTH: a validated DONE (file landed) WINS over a cancelled/error record for
|
|
749
|
+
// the SAME (id, trayId) — whether that other record is a persisted counterpart OR this
|
|
750
|
+
// session's own in-memory cancelled/error. So a persisted DONE overrides any current
|
|
751
|
+
// entry that is neither DONE nor a LIVE in-memory download (which stays visible as the
|
|
752
|
+
// user's active action). The list never shows a cancelled in place of a validated file.
|
|
753
|
+
for (const rec of listPersistedDownloadJobs()) {
|
|
754
|
+
const job = jobFromPersisted(rec);
|
|
755
|
+
const k = keyOf(job);
|
|
756
|
+
const cur = byKey.get(k);
|
|
757
|
+
if (!cur) {
|
|
758
|
+
byKey.set(k, job);
|
|
759
|
+
}
|
|
760
|
+
else if (job.status === "done" && cur.status !== "done" && cur.status !== "downloading") {
|
|
761
|
+
byKey.set(k, job);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return [...byKey.values()].sort((a, b) => b.started_at - a.started_at);
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Cancel an in-flight download by id (#515): abort its stream and mark it
|
|
768
|
+
* cancelled. The abort unwinds the fetch + pipeline; the .partial is left on disk
|
|
769
|
+
* (resumable) and NEVER renamed to the destination, so nothing is reported as
|
|
770
|
+
* complete. Idempotent — cancelling an already-settled job just reports its state.
|
|
771
|
+
* Returns the resulting status plus whether this call performed the abort.
|
|
772
|
+
*
|
|
773
|
+
* Only a download owned by THIS process can be aborted (its AbortController lives
|
|
774
|
+
* here). A job resolvable only via the persisted store (started by another/previous
|
|
775
|
+
* session after a reconnect) cannot be aborted from here — reported as not-owned.
|
|
776
|
+
*/
|
|
777
|
+
export function cancelDownloadJob(id) {
|
|
778
|
+
const entry = jobs.get(id);
|
|
779
|
+
if (entry) {
|
|
780
|
+
const { job, controller } = entry;
|
|
781
|
+
// Cross-session ambiguity: a live foreign download shares this id with a DIFFERENT
|
|
782
|
+
// trayId. Aborting by id could act on the wrong logical download — decline so a
|
|
783
|
+
// cancel-by-id can never hit an unintended concurrent download (a #515 invariant).
|
|
784
|
+
if (job.status === "downloading" && hasAmbiguousForeignSibling(id, job.trayId)) {
|
|
785
|
+
return { found: true, owned: true, aborted: false, ambiguous: true, status: job.status, job };
|
|
786
|
+
}
|
|
787
|
+
if (job.status !== "downloading") {
|
|
788
|
+
// Already settled (done/error/cancelled) — idempotent no-op.
|
|
789
|
+
return { found: true, owned: true, aborted: false, status: job.status, job };
|
|
790
|
+
}
|
|
791
|
+
// Request the abort ONLY — do NOT set a synchronous terminal state here. The FINAL
|
|
792
|
+
// state is decided by the settled closure based on what actually happened on disk:
|
|
793
|
+
// - the file already landed (its destination rename completed, so onLanded →
|
|
794
|
+
// commitDone marks it DONE) — a validated complete file must never read
|
|
795
|
+
// "cancelled"; OR
|
|
796
|
+
// - the transfer was stopped before the file landed (downloadModel THROWS via the
|
|
797
|
+
// stream abort / pre-materialize / pre-rename guards → the catch marks it
|
|
798
|
+
// CANCELLED and cleans up the tray row + resumable partial).
|
|
799
|
+
// Setting "cancelled" synchronously here would LOSE the race where a rename has
|
|
800
|
+
// physically completed but its promise continuation (→ onLanded) hasn't run yet:
|
|
801
|
+
// commitDone only advances a still-"downloading" job, so a synchronous "cancelled"
|
|
802
|
+
// would strand a landed file as cancelled (#515 codex). The tool reports this as a
|
|
803
|
+
// best-effort request and points the caller at download_status for the resolved state.
|
|
804
|
+
if (!controller.signal.aborted)
|
|
805
|
+
controller.abort();
|
|
806
|
+
return { found: true, owned: true, aborted: true, status: "downloading", job };
|
|
807
|
+
}
|
|
808
|
+
// Not in THIS process's registry. It may still exist in the persisted store
|
|
809
|
+
// (another/previous session owns the AbortController), which we can't abort here.
|
|
810
|
+
const persisted = readPersistedDownloadJob(id);
|
|
811
|
+
if (persisted) {
|
|
812
|
+
return {
|
|
813
|
+
found: true,
|
|
814
|
+
owned: false,
|
|
815
|
+
aborted: false,
|
|
816
|
+
status: persisted.status,
|
|
817
|
+
job: jobFromPersisted(persisted),
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
return { found: false, owned: false, aborted: false };
|
|
376
821
|
}
|
|
377
822
|
/** Test seam — the registry is process-global otherwise. */
|
|
378
823
|
export function resetDownloadJobs() {
|
|
824
|
+
for (const e of new Set(jobs.values())) {
|
|
825
|
+
if (e.heartbeat)
|
|
826
|
+
clearInterval(e.heartbeat);
|
|
827
|
+
}
|
|
379
828
|
jobs.clear();
|
|
380
829
|
destChains.clear();
|
|
381
830
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download-jobs.js","sourceRoot":"","sources":["../../src/services/download-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,+BAA+B,GAChC,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AA2C5C,4EAA4E;AAC5E,mFAAmF;AACnF,mFAAmF;AACnF,6BAA6B;AAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;AAEtC,gFAAgF;AAChF,iFAAiF;AACjF,kFAAkF;AAClF,kFAAkF;AAClF,mFAAmF;AACnF,oFAAoF;AACpF,+EAA+E;AAC/E,oFAAoF;AACpF,2EAA2E;AAC3E,iFAAiF;AACjF,iFAAiF;AACjF,MAAM,UAAU,GAAG,IAAI,GAAG,EAAyB,CAAC;AAEpD;;;sFAGsF;AACtF,SAAS,qBAAqB,CAAC,GAAW;IACxC,OAAO,OAAO,CAAC,QAAQ,KAAK,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAClE,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE;QACnB,CAAC,CAAC,GAAG,CAAC;AACV,CAAC;AAED;;;;wFAIwF;AACxF,KAAK,UAAU,uBAAuB,CAAC,CAAS;IAC9C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,SAAS,CAAC;QACR,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5D,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,GAAI,GAA6B,EAAE,IAAI,CAAC;YAClD,yEAAyE;YACzE,0EAA0E;YAC1E,8EAA8E;YAC9E,4EAA4E;YAC5E,6EAA6E;YAC7E,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS;gBAAE,MAAM,GAAG,CAAC;YACvD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,MAAM,KAAK,OAAO;gBAAE,OAAO,CAAC,CAAC,CAAC,+CAA+C;YACjF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7B,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;2EAE2E;AAC3E,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACjD,MAAM,IAAI,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACvD,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;;;;oEAKoE;AACpE,SAAS,kBAAkB,CAAC,GAAW,EAAE,eAAuB,EAAE,QAAiB;IACjF,IAAI,IAAI,GAAG,QAAQ,CAAC;IACpB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,CAAC;YACH,IAAI,GAAG,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IACD,gFAAgF;IAChF,yEAAyE;IACzE,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC;SACtC,IAAI,EAAE;SACN,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,UAAU,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAY,EAAE,GAAW;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,KAAK,aAAa;QAAE,OAAO;IACrE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACvB,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,KAAY;IAC/B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;;;;GAQG;AACH;;;;;;;;6EAQ6E;AAC7E,SAAS,YAAY,CAAC,IAAmB;IACvC,OAAO,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAClG,CAAC;AAED,SAAS,kBAAkB,CACzB,GAAW,EACX,eAAuB,EACvB,QAAiB,EACjB,IAAmB;IAEnB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAC/B,GAAG;QACH,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACpC,QAAQ,IAAI,IAAI;QAChB,YAAY,CAAC,IAAI,CAAC;KACnB,CAAC,CAAC;IACH,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,eAAuB,EACvB,QAAiB,EACjB,IAAmB;AACnB;4EAC4E;AAC5E,UAAgD;IAEhD,6EAA6E;IAC7E,iFAAiF;IACjF,+EAA+E;IAC/E,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,gFAAgF;IAChF,2EAA2E;IAC3E,gFAAgF;IAChF,4EAA4E;IAC5E,gFAAgF;IAChF,EAAE;IACF,6EAA6E;IAC7E,gFAAgF;IAChF,iFAAiF;IACjF,8EAA8E;IAC9E,kEAAkE;IAClE,MAAM,iBAAiB,GAAG,MAAM,+BAA+B,EAAE,CAAC;IAElE,kFAAkF;IAClF,iFAAiF;IACjF,iFAAiF;IACjF,kFAAkF;IAClF,iFAAiF;IACjF,4EAA4E;IAC5E,8EAA8E;IAC9E,6EAA6E;IAC7E,+CAA+C;IAC/C,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxE,IAAI,OAA2B,CAAC;IAChC,kFAAkF;IAClF,yEAAyE;IACzE,iFAAiF;IACjF,kFAAkF;IAClF,4EAA4E;IAC5E,mFAAmF;IACnF,8EAA8E;IAC9E,kEAAkE;IAClE,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC3E,8EAA8E;QAC9E,2EAA2E;QAC3E,wEAAwE;QACxE,OAAO,GAAG,gBAAgB,CAAC,GAAG,MAAM,CAAC,UAAU,KAAK,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1E,YAAY,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;IACD,+EAA+E;IAC/E,4EAA4E;IAC5E,MAAM,EAAE,GAAG,OAAO,IAAI,MAAM,CAAC;IAC7B,gFAAgF;IAChF,qDAAqD;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAElC,+EAA+E;IAC/E,oFAAoF;IACpF,qFAAqF;IACrF,gDAAgD;IAChD,IAAI,OAA0B,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YACxC,OAAO,GAAG,CAAC,CAAC;YACZ,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,iFAAiF;QACjF,+EAA+E;QAC/E,8EAA8E;QAC9E,+EAA+E;QAC/E,mFAAmF;QACnF,KAAK,MAAM,CAAC,IAAI,UAAU;YAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,4CAA4C,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE;YACxE,GAAG;YACH,gBAAgB,EAAE,eAAe;YACjC,QAAQ;SACT,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,oFAAoF;IACpF,kFAAkF;IAClF,qEAAqE;IACrE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAS,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,CAAC,CAAC,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAgB;QACvB,EAAE;QACF,MAAM;QACN,GAAG;QACH,gBAAgB,EAAE,eAAe;QACjC,QAAQ;QACR,MAAM,EAAE,aAAa;QACrB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;KACvB,CAAC;IAEF,iFAAiF;IACjF,iFAAiF;IACjF,oEAAoE;IACpE,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAEnD,2EAA2E;IAC3E,+CAA+C;IAC/C,gFAAgF;IAChF,4EAA4E;IAC5E,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;QAC1B,+EAA+E;QAC/E,kDAAkD;QAClD,IAAI,aAAa;YAAE,MAAM,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC9F,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACjB,CAAC,CAAC,CAAC;YACH,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAChB,IAAI,UAAU,EAAE,CAAC;gBACf,uEAAuE;gBACvE,qEAAqE;gBACrE,sDAAsD;gBACtD,IAAI,CAAC;oBACH,GAAG,CAAC,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,KAAK,GAAG;wBACV,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,qCAAqC;qBACrH,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;YACpB,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC;YACrB,GAAG,CAAC,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7D,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IAEL,iFAAiF;IACjF,8DAA8D;IAC9D,UAAU,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACtC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;QACxB,IAAI,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,OAAO;YAAE,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,kFAAkF;IAClF,mFAAmF;IACnF,oDAAoD;IACpD,MAAM,KAAK,GAAU,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC;QAAE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,2EAA2E;IAC3E,+EAA+E;IAC/E,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,gFAAgF;IAChF,gDAAgD;IAChD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAS,CAAC;IAC9B,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,SAAS;QAC1B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,UAAU,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
|
|
1
|
+
{"version":3,"file":"download-jobs.js","sourceRoot":"","sources":["../../src/services/download-jobs.ts"],"names":[],"mappings":"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"}
|