@camstack/addon-pipeline 1.2.151 → 1.2.152
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +2 -2
- package/dist/detection-pipeline/index.js +5 -5
- package/dist/detection-pipeline/index.mjs +4 -4
- package/dist/{dist-hmG3nfuW.js → dist-BpofTthV.js} +54 -7
- package/dist/{dist-BjzcUac4.mjs → dist-DoaR6NDJ.mjs} +54 -7
- package/dist/{lazy-sharp-RLE6klOt.js → lazy-sharp-D6sSNL-G.js} +1 -1
- package/dist/{local-frame-registry-Ct2vQ7Dp.js → local-frame-registry-4MCvZQ2t.js} +1 -1
- package/dist/{local-frame-registry-BFaxbRtK.mjs → local-frame-registry-Dr8irbU_.mjs} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/{node-U9fJ-bQN.mjs → node-CeSZTDKV.mjs} +1 -1
- package/dist/{node-BwXwfrvA.js → node-DG_kTYFM.js} +1 -1
- package/dist/pipeline-runner/index.js +5 -5
- package/dist/pipeline-runner/index.mjs +4 -4
- package/dist/{process-memory-4WDUPavu.mjs → process-memory-DJoquJSu.mjs} +1 -1
- package/dist/{process-memory-DR9jSxpX.js → process-memory-DglWLA3J.js} +1 -1
- package/dist/recorder/index.js +167 -28
- package/dist/recorder/index.mjs +167 -28
- package/dist/{segment-demux-js-kUN5AQVv.mjs → segment-demux-js-Clx6DzLe.mjs} +1 -1
- package/dist/{segment-demux-js-zqUNh3pj.js → segment-demux-js-DUSMkFTq.js} +1 -1
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BOXQSR0X.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BntoKYim.mjs} +3 -3
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CyIaTPRY.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-C-HJX19g.mjs} +1 -1
- package/dist/stream-broker/demux-worker-child.js +1 -1
- package/dist/stream-broker/demux-worker-child.mjs +1 -1
- package/dist/stream-broker/{hostInit-CnUhcNPG.mjs → hostInit--5tl1XaO.mjs} +3 -3
- package/dist/stream-broker/index.js +3 -3
- package/dist/stream-broker/index.mjs +3 -3
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-BzlEZ56r.mjs → worker-protocol-Ar0-GAh5.mjs} +1 -1
- package/dist/{worker-protocol-DE_jjbFA.js → worker-protocol-C8bHw-bu.js} +1 -1
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_process_memory = require("../process-memory-
|
|
5
|
+
const require_dist = require("../dist-BpofTthV.js");
|
|
6
|
+
const require_process_memory = require("../process-memory-DglWLA3J.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_dist.__toESM(node_fs);
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-
|
|
3
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
2
|
+
import { A as audioAnalysisCapability, It as hydrateSchema, S as PoolMemoryWatchdog, _t as resolvePoolMemoryPolicy, j as audioAnalyzerCapability, jt as BaseAddon, n as AUDIO_BACKEND_CHOICES, nt as mapAudioLabelToMacro, s as DEFAULT_AUDIO_ANALYZER_CONFIG, v as HF_BASE_URL, wt as errMsg } from "../dist-DoaR6NDJ.mjs";
|
|
3
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DJoquJSu.mjs";
|
|
4
4
|
import * as fs from "node:fs";
|
|
5
5
|
import * as path$1 from "node:path";
|
|
6
6
|
import { downloadFile } from "@camstack/system/addon-utils";
|
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node-
|
|
7
|
-
const require_local_frame_registry = require("../local-frame-registry-
|
|
8
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
5
|
+
const require_dist = require("../dist-BpofTthV.js");
|
|
6
|
+
const require_node = require("../node-DG_kTYFM.js");
|
|
7
|
+
const require_local_frame_registry = require("../local-frame-registry-4MCvZQ2t.js");
|
|
8
|
+
const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
|
|
9
9
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
10
|
-
const require_process_memory = require("../process-memory-
|
|
10
|
+
const require_process_memory = require("../process-memory-DglWLA3J.js");
|
|
11
11
|
let node_fs = require("node:fs");
|
|
12
12
|
node_fs = require_dist.__toESM(node_fs);
|
|
13
13
|
let node_path = require("node:path");
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as __require } from "../chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-
|
|
3
|
-
import { a as readProcessCost } from "../node-
|
|
4
|
-
import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-
|
|
2
|
+
import { Bt as nodePin, Ft as createEvent, It as hydrateSchema, Kt as array, O as YAMNET_TO_MACRO, Q as inferModelProvider, Qt as object, S as PoolMemoryWatchdog, St as supportedRuntimes$1, Vt as parseJsonUnknown, W as detectionPipelineCapability, Wt as sleep, Y as evaluateZoneRules, _t as resolvePoolMemoryPolicy, at as overlayClusterStepSettings, c as DEFAULT_CLUSTER_STEP_MODELS, ct as pickClusterStepSettings, dt as pipelineExecutorCapability, en as string, et as loadContributionCapability, ht as resolveClusterStepModelId, jt as BaseAddon, l as DEFAULT_CLUSTER_STEP_SETTINGS, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, q as enumerateInferenceDevices, st as pickClusterStepModels, t as APPLE_SA_TO_MACRO, tn as union, wt as errMsg, yt as runtimeDevices$1, z as defaultDeviceFor$1 } from "../dist-DoaR6NDJ.mjs";
|
|
3
|
+
import { a as readProcessCost } from "../node-CeSZTDKV.mjs";
|
|
4
|
+
import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep, t as localFrameRegistry, u as landmarkPrecisionVerdict } from "../local-frame-registry-Dr8irbU_.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
6
6
|
import { n as startEventLoopStallMonitor } from "../event-loop-stall-monitor-DXLNBMkY.mjs";
|
|
7
|
-
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-
|
|
7
|
+
import { n as pickNodePlatformArch, t as readProcessMemory } from "../process-memory-DJoquJSu.mjs";
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import * as path$1 from "node:path";
|
|
10
10
|
import { spawn } from "node:child_process";
|
|
@@ -9338,6 +9338,21 @@ var RelocateJobSchema = object({
|
|
|
9338
9338
|
bytesMoved: number().int(),
|
|
9339
9339
|
/** Total files discovered up front; null while (or when) unknown. */
|
|
9340
9340
|
filesTotal: number().int().nullable(),
|
|
9341
|
+
/**
|
|
9342
|
+
* Rows this run CORRECTED while moving them — a durable mutation the move
|
|
9343
|
+
* made that nobody asked for, so it is reported where the operator reads the
|
|
9344
|
+
* job rather than only in a log line.
|
|
9345
|
+
*
|
|
9346
|
+
* A footage segment records its byte count in its own NAME, and the durable
|
|
9347
|
+
* hour row derives its aggregates from those names. A file that does not
|
|
9348
|
+
* match its name therefore makes the ledger's sums — and with them quota and
|
|
9349
|
+
* pressure eviction — wrong by the difference, and only a rename can fix it.
|
|
9350
|
+
* On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
|
|
9351
|
+
*
|
|
9352
|
+
* Absent on lanes where the question has no meaning: a media blob's size is
|
|
9353
|
+
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
9354
|
+
*/
|
|
9355
|
+
rowsReconciled: number().int().nonnegative().optional(),
|
|
9341
9356
|
startedAt: number(),
|
|
9342
9357
|
finishedAt: number().nullable(),
|
|
9343
9358
|
error: string().nullable()
|
|
@@ -9406,14 +9421,42 @@ var RelocateMediaInputSchema = object({
|
|
|
9406
9421
|
/** Omitted = `move`, the pre-existing behaviour. */
|
|
9407
9422
|
mode: MediaRelocateModeSchema.optional()
|
|
9408
9423
|
});
|
|
9409
|
-
/**
|
|
9410
|
-
*
|
|
9411
|
-
*
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
|
|
9424
|
+
/**
|
|
9425
|
+
* The unstamped population of ONE collection — split, because the gate and the
|
|
9426
|
+
* operator ask two different questions and only one of them has to be cheap.
|
|
9427
|
+
*
|
|
9428
|
+
* `present` is the GATE: "is there at least one row that would be orphaned by a
|
|
9429
|
+
* repoint". It is a single indexed seek to the first matching row, so it stays
|
|
9430
|
+
* answerable on a saturated disk and answers in O(log n) precisely in the state
|
|
9431
|
+
* that matters — after a seal, when the population is empty.
|
|
9432
|
+
*
|
|
9433
|
+
* `rows` is the NUMBER, for the refusal message and the operator's sense of
|
|
9434
|
+
* scale. It is a second, indexed `COUNT(*)`, and `null` means **not
|
|
9435
|
+
* measurable** — never zero. `{ present: true, rows: null }` is a legitimate
|
|
9436
|
+
* and useful answer: "there are some, and this read could not say how many"
|
|
9437
|
+
* still refuses the cutover, which is the whole job.
|
|
9438
|
+
*/
|
|
9439
|
+
var UnstampedRowsSchema = object({
|
|
9440
|
+
present: boolean(),
|
|
9441
|
+
rows: number().int().nonnegative().nullable()
|
|
9416
9442
|
});
|
|
9443
|
+
/**
|
|
9444
|
+
* How many rows still carry NO `locationId` — the population a repoint would
|
|
9445
|
+
* silently re-aim at a disk that does not hold their bytes.
|
|
9446
|
+
*
|
|
9447
|
+
* **`null` = the count could not be taken**, and it is NOT permission to cut
|
|
9448
|
+
* over. The gate opens on a measured absence and on nothing else; an unread
|
|
9449
|
+
* collection and an empty one are different facts, and this repo has already
|
|
9450
|
+
* paid for conflating them (`RelocateResidueSchema`, D295).
|
|
9451
|
+
*/
|
|
9452
|
+
var UnstampedEventMediaCountSchema = object({
|
|
9453
|
+
media: UnstampedRowsSchema,
|
|
9454
|
+
retrainFrames: UnstampedRowsSchema,
|
|
9455
|
+
/** True when EITHER collection holds one. The refusal reads this. */
|
|
9456
|
+
anyPresent: boolean(),
|
|
9457
|
+
/** Sum across both, or `null` when either lane could not be counted. */
|
|
9458
|
+
total: number().int().nonnegative().nullable()
|
|
9459
|
+
}).nullable();
|
|
9417
9460
|
var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
|
|
9418
9461
|
/** The independently selectable logical storage classes — every class
|
|
9419
9462
|
* `storage.listLocationDeclarations` reports, so an operator never meets a
|
|
@@ -9524,6 +9567,10 @@ var StorageMigrationMoveProgressSchema = object({
|
|
|
9524
9567
|
/** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
|
|
9525
9568
|
filesTotal: number().int().nonnegative().nullable(),
|
|
9526
9569
|
bytesMoved: number().int().nonnegative(),
|
|
9570
|
+
/** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
|
|
9571
|
+
* a lane that cannot reconcile. A migration that silently rewrote durable
|
|
9572
|
+
* rows would be the same failure as one that silently skipped them. */
|
|
9573
|
+
rowsReconciled: number().int().nonnegative().optional(),
|
|
9527
9574
|
/** The MOVER's start, not the migration's: a drain restarted after an addon
|
|
9528
9575
|
* crash gets a new mover, and a rate computed from the migration's start
|
|
9529
9576
|
* would silently average in the time nothing was running. */
|
|
@@ -9315,6 +9315,21 @@ var RelocateJobSchema = object({
|
|
|
9315
9315
|
bytesMoved: number().int(),
|
|
9316
9316
|
/** Total files discovered up front; null while (or when) unknown. */
|
|
9317
9317
|
filesTotal: number().int().nullable(),
|
|
9318
|
+
/**
|
|
9319
|
+
* Rows this run CORRECTED while moving them — a durable mutation the move
|
|
9320
|
+
* made that nobody asked for, so it is reported where the operator reads the
|
|
9321
|
+
* job rather than only in a log line.
|
|
9322
|
+
*
|
|
9323
|
+
* A footage segment records its byte count in its own NAME, and the durable
|
|
9324
|
+
* hour row derives its aggregates from those names. A file that does not
|
|
9325
|
+
* match its name therefore makes the ledger's sums — and with them quota and
|
|
9326
|
+
* pressure eviction — wrong by the difference, and only a rename can fix it.
|
|
9327
|
+
* On 2026-08-30 one such row also stalled a 110 749-file drain permanently.
|
|
9328
|
+
*
|
|
9329
|
+
* Absent on lanes where the question has no meaning: a media blob's size is
|
|
9330
|
+
* in its row, not in its name, so `MediaRelocateEngine` never reconciles one.
|
|
9331
|
+
*/
|
|
9332
|
+
rowsReconciled: number().int().nonnegative().optional(),
|
|
9318
9333
|
startedAt: number(),
|
|
9319
9334
|
finishedAt: number().nullable(),
|
|
9320
9335
|
error: string().nullable()
|
|
@@ -9383,14 +9398,42 @@ var RelocateMediaInputSchema = object({
|
|
|
9383
9398
|
/** Omitted = `move`, the pre-existing behaviour. */
|
|
9384
9399
|
mode: MediaRelocateModeSchema.optional()
|
|
9385
9400
|
});
|
|
9386
|
-
/**
|
|
9387
|
-
*
|
|
9388
|
-
*
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9401
|
+
/**
|
|
9402
|
+
* The unstamped population of ONE collection — split, because the gate and the
|
|
9403
|
+
* operator ask two different questions and only one of them has to be cheap.
|
|
9404
|
+
*
|
|
9405
|
+
* `present` is the GATE: "is there at least one row that would be orphaned by a
|
|
9406
|
+
* repoint". It is a single indexed seek to the first matching row, so it stays
|
|
9407
|
+
* answerable on a saturated disk and answers in O(log n) precisely in the state
|
|
9408
|
+
* that matters — after a seal, when the population is empty.
|
|
9409
|
+
*
|
|
9410
|
+
* `rows` is the NUMBER, for the refusal message and the operator's sense of
|
|
9411
|
+
* scale. It is a second, indexed `COUNT(*)`, and `null` means **not
|
|
9412
|
+
* measurable** — never zero. `{ present: true, rows: null }` is a legitimate
|
|
9413
|
+
* and useful answer: "there are some, and this read could not say how many"
|
|
9414
|
+
* still refuses the cutover, which is the whole job.
|
|
9415
|
+
*/
|
|
9416
|
+
var UnstampedRowsSchema = object({
|
|
9417
|
+
present: boolean(),
|
|
9418
|
+
rows: number().int().nonnegative().nullable()
|
|
9393
9419
|
});
|
|
9420
|
+
/**
|
|
9421
|
+
* How many rows still carry NO `locationId` — the population a repoint would
|
|
9422
|
+
* silently re-aim at a disk that does not hold their bytes.
|
|
9423
|
+
*
|
|
9424
|
+
* **`null` = the count could not be taken**, and it is NOT permission to cut
|
|
9425
|
+
* over. The gate opens on a measured absence and on nothing else; an unread
|
|
9426
|
+
* collection and an empty one are different facts, and this repo has already
|
|
9427
|
+
* paid for conflating them (`RelocateResidueSchema`, D295).
|
|
9428
|
+
*/
|
|
9429
|
+
var UnstampedEventMediaCountSchema = object({
|
|
9430
|
+
media: UnstampedRowsSchema,
|
|
9431
|
+
retrainFrames: UnstampedRowsSchema,
|
|
9432
|
+
/** True when EITHER collection holds one. The refusal reads this. */
|
|
9433
|
+
anyPresent: boolean(),
|
|
9434
|
+
/** Sum across both, or `null` when either lane could not be counted. */
|
|
9435
|
+
total: number().int().nonnegative().nullable()
|
|
9436
|
+
}).nullable();
|
|
9394
9437
|
var StorageMigrationMediaMoveInputSchema = RelocateMediaInputSchema.extend({ leaseId: string().min(1) });
|
|
9395
9438
|
/** The independently selectable logical storage classes — every class
|
|
9396
9439
|
* `storage.listLocationDeclarations` reports, so an operator never meets a
|
|
@@ -9501,6 +9544,10 @@ var StorageMigrationMoveProgressSchema = object({
|
|
|
9501
9544
|
/** The archive census — the **M** of "N of M" (D295). `null` = unknowable. */
|
|
9502
9545
|
filesTotal: number().int().nonnegative().nullable(),
|
|
9503
9546
|
bytesMoved: number().int().nonnegative(),
|
|
9547
|
+
/** Rows the mover corrected while moving them — see `RelocateJob`. Absent on
|
|
9548
|
+
* a lane that cannot reconcile. A migration that silently rewrote durable
|
|
9549
|
+
* rows would be the same failure as one that silently skipped them. */
|
|
9550
|
+
rowsReconciled: number().int().nonnegative().optional(),
|
|
9504
9551
|
/** The MOVER's start, not the migration's: a drain restarted after an addon
|
|
9505
9552
|
* crash gets a new mover, and a rate computed from the migration's start
|
|
9506
9553
|
* would silently average in the time nothing was running. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-
|
|
1
|
+
import { M as audioKindId, Z as hfModelUrl, a as COCO_80_LABELS, o as COCO_TO_MACRO, r as AUDIO_MACRO_LABELS } from "./dist-DoaR6NDJ.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
4
4
|
var HF_REPO = "camstack/camstack-models";
|
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
5
|
+
const require_dist = require("../dist-BpofTthV.js");
|
|
6
|
+
const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
let node_path = require("node:path");
|
|
9
9
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-
|
|
1
|
+
import { It as hydrateSchema, Pt as DeviceType, Y as evaluateZoneRules, it as motionDetectionCapability, jt as BaseAddon } from "../dist-DoaR6NDJ.mjs";
|
|
2
2
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-
|
|
1
|
+
import { Dt as buildFfmpegArgs, Et as Fmp4BoxSplitter, kt as isSoftwareDecode, wt as errMsg } from "./dist-DoaR6NDJ.mjs";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import "node:fs";
|
|
4
4
|
import "node:path";
|
|
@@ -2,12 +2,12 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_node = require("../node-
|
|
7
|
-
const require_local_frame_registry = require("../local-frame-registry-
|
|
8
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
5
|
+
const require_dist = require("../dist-BpofTthV.js");
|
|
6
|
+
const require_node = require("../node-DG_kTYFM.js");
|
|
7
|
+
const require_local_frame_registry = require("../local-frame-registry-4MCvZQ2t.js");
|
|
8
|
+
const require_worker_protocol = require("../worker-protocol-C8bHw-bu.js");
|
|
9
9
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
10
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
10
|
+
const require_lazy_sharp = require("../lazy-sharp-D6sSNL-G.js");
|
|
11
11
|
const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
|
|
12
12
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
13
13
|
const require_remote_restream = require("../remote-restream-CO36Sr30.js");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-
|
|
2
|
-
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-
|
|
3
|
-
import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-
|
|
4
|
-
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-
|
|
1
|
+
import { B as defineCustomActions, Bt as nodePin, Ft as createEvent, Gt as _enum, H as deriveDetailCropRect, Kt as array, L as customAction, Qt as object, X as failureContributionCapability, Xt as literal, Yt as lazy, Zt as number, _ as FailureCounters, en as string, et as loadContributionCapability, ft as pipelineRunnerCapability, jt as BaseAddon, lt as pickDetailCropConvention, m as DEVICE_BACKEND_TO_FORMAT, nn as EventCategory, p as DEFAULT_NATIVE_LEASE_SETTINGS, qt as boolean, u as DEFAULT_DETAIL_CROP_CONVENTION, ut as pickNativeLeaseOverride, wt as errMsg } from "../dist-DoaR6NDJ.mjs";
|
|
2
|
+
import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-CeSZTDKV.mjs";
|
|
3
|
+
import { c as getStepDefinition, n as resolveFrameViewGeometry, t as localFrameRegistry } from "../local-frame-registry-Dr8irbU_.mjs";
|
|
4
|
+
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-Ar0-GAh5.mjs";
|
|
5
5
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
6
6
|
import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
|
|
7
7
|
import { n as withDetectionIntent } from "../restream-intent-B4BXZra7.mjs";
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_dist = require("../dist-
|
|
2
|
-
const require_node = require("../node-
|
|
1
|
+
const require_dist = require("../dist-BpofTthV.js");
|
|
2
|
+
const require_node = require("../node-DG_kTYFM.js");
|
|
3
3
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
4
4
|
const require_restream_intent = require("../restream-intent-Cv9x3jmu.js");
|
|
5
5
|
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-DaUBcb13.js");
|
|
@@ -1621,32 +1621,73 @@ function snapshot(j) {
|
|
|
1621
1621
|
filesMoved: j.filesMoved,
|
|
1622
1622
|
bytesMoved: j.bytesMoved,
|
|
1623
1623
|
filesTotal: j.filesTotal,
|
|
1624
|
+
rowsReconciled: j.rowsReconciled,
|
|
1624
1625
|
startedAt: j.startedAt,
|
|
1625
1626
|
finishedAt: j.finishedAt,
|
|
1626
1627
|
error: j.error
|
|
1627
1628
|
};
|
|
1628
1629
|
}
|
|
1629
1630
|
/**
|
|
1630
|
-
*
|
|
1631
|
+
* The row's source file is not on disk.
|
|
1632
|
+
*
|
|
1633
|
+
* Carries `code: 'ENOENT'` because that is how every caller here already tells
|
|
1634
|
+
* a ghost row from a real failure, and {@link copyVerified} now discovers the
|
|
1635
|
+
* absence with a `stat` rather than by letting `copyFile` raise it.
|
|
1636
|
+
*/
|
|
1637
|
+
var RelocateSourceMissingError = class extends Error {
|
|
1638
|
+
code = "ENOENT";
|
|
1639
|
+
constructor(src) {
|
|
1640
|
+
super(`relocate source missing: ${src}`);
|
|
1641
|
+
this.name = "RelocateSourceMissingError";
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
/**
|
|
1645
|
+
* One file's COPY: copy-if-absent → verify the destination against the SOURCE'S
|
|
1646
|
+
* OWN SIZE. The source is left in place.
|
|
1631
1647
|
*
|
|
1632
1648
|
* Split out of {@link moveFile} because the durable index re-point has to
|
|
1633
1649
|
* happen while BOTH locations still hold the bytes — see
|
|
1634
|
-
* `SegmentHourLedger.repointSegments`.
|
|
1635
|
-
*
|
|
1650
|
+
* `SegmentHourLedger.repointSegments`.
|
|
1651
|
+
*
|
|
1652
|
+
* **`recordedBytes` is never the verify's reference.** It used to be, and it
|
|
1653
|
+
* cannot be: `fs.copyFile` truncates and replaces, so the destination always
|
|
1654
|
+
* equals the source, and comparing that result against a number the LEDGER
|
|
1655
|
+
* remembers can only ever fail when the ledger is wrong. On 2026-08-30 that
|
|
1656
|
+
* reported a byte-perfect copy as corruption and killed a 110 749-file drain
|
|
1657
|
+
* on its 12 440th file:
|
|
1658
|
+
*
|
|
1659
|
+
* relocate verify failed: …/1787926410000-9966-274432.m4s
|
|
1660
|
+
* is 783801B, expected 274432B
|
|
1661
|
+
*
|
|
1662
|
+
* Both files measured 783801 B on the hub. What is faithful is "the
|
|
1663
|
+
* destination equals the source", and that is what is asserted here; the
|
|
1664
|
+
* recorded number survives only as the reference for a destination whose
|
|
1665
|
+
* source is already GONE, where there is nothing else left to compare against.
|
|
1636
1666
|
*/
|
|
1637
|
-
async function copyVerified(src, dst,
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
dstBytes
|
|
1643
|
-
}
|
|
1644
|
-
if (
|
|
1667
|
+
async function copyVerified(src, dst, recordedBytes) {
|
|
1668
|
+
const dstBytes = await fileSize(dst);
|
|
1669
|
+
const srcBytes = await fileSize(src);
|
|
1670
|
+
if (dstBytes !== null && dstBytes === (srcBytes ?? recordedBytes)) return {
|
|
1671
|
+
copied: 0,
|
|
1672
|
+
srcBytes: dstBytes
|
|
1673
|
+
};
|
|
1674
|
+
if (srcBytes === null) throw new RelocateSourceMissingError(src);
|
|
1645
1675
|
await node_fs.promises.mkdir(node_path.default.dirname(dst), { recursive: true });
|
|
1646
1676
|
await node_fs.promises.copyFile(src, dst);
|
|
1647
1677
|
const after = await node_fs.promises.stat(dst);
|
|
1648
1678
|
if (after.size !== srcBytes) throw new Error(`relocate verify failed: ${dst} is ${after.size}B, expected ${srcBytes}B`);
|
|
1649
|
-
return
|
|
1679
|
+
return {
|
|
1680
|
+
copied: srcBytes,
|
|
1681
|
+
srcBytes
|
|
1682
|
+
};
|
|
1683
|
+
}
|
|
1684
|
+
/** A file's size, or `null` when it is not there. */
|
|
1685
|
+
async function fileSize(p) {
|
|
1686
|
+
try {
|
|
1687
|
+
return (await node_fs.promises.stat(p)).size;
|
|
1688
|
+
} catch {
|
|
1689
|
+
return null;
|
|
1690
|
+
}
|
|
1650
1691
|
}
|
|
1651
1692
|
var RelocateEngine = class {
|
|
1652
1693
|
deps;
|
|
@@ -1700,6 +1741,14 @@ var RelocateEngine = class {
|
|
|
1700
1741
|
if (!to) throw new Error(`unknown target location: ${input.toLocationId}`);
|
|
1701
1742
|
if (from.id === to.id) throw new Error("source and target locations are identical");
|
|
1702
1743
|
if (to.readOnly) throw new Error(`target location is read-only: ${to.id}`);
|
|
1744
|
+
if (to.enabled === false) this.deps.logger.warn("relocate: target location is DISABLED (standby) — moving to it because the operator named it; placement still never chooses it for new writes", {
|
|
1745
|
+
...input.deviceId !== void 0 ? { tags: { deviceId: input.deviceId } } : {},
|
|
1746
|
+
meta: {
|
|
1747
|
+
fromLocationId: from.id,
|
|
1748
|
+
toLocationId: to.id,
|
|
1749
|
+
footageClass: input.footageClass ?? null
|
|
1750
|
+
}
|
|
1751
|
+
});
|
|
1703
1752
|
const job = {
|
|
1704
1753
|
jobId: this.deps.newId(),
|
|
1705
1754
|
state: "queued",
|
|
@@ -1714,6 +1763,7 @@ var RelocateEngine = class {
|
|
|
1714
1763
|
filesMoved: 0,
|
|
1715
1764
|
bytesMoved: 0,
|
|
1716
1765
|
filesTotal: null,
|
|
1766
|
+
rowsReconciled: 0,
|
|
1717
1767
|
startedAt: this.deps.now(),
|
|
1718
1768
|
finishedAt: null,
|
|
1719
1769
|
error: null,
|
|
@@ -1867,7 +1917,8 @@ var RelocateEngine = class {
|
|
|
1867
1917
|
toLocationId: job.toLocationId,
|
|
1868
1918
|
archiveSegments: job.filesTotal,
|
|
1869
1919
|
seen,
|
|
1870
|
-
moved: job.filesMoved
|
|
1920
|
+
moved: job.filesMoved,
|
|
1921
|
+
rowsReconciled: job.rowsReconciled
|
|
1871
1922
|
};
|
|
1872
1923
|
if (archive === null) {
|
|
1873
1924
|
this.deps.logger.warn("relocate: coverage UNKNOWN — with no durable ledger this node cannot say what the source still holds", {
|
|
@@ -1962,6 +2013,56 @@ var RelocateEngine = class {
|
|
|
1962
2013
|
return `${DESTINATION_FULL_PREFIX}: ${to.id} has ${(Math.round(free * 100) / 100).toString()}% free, below its ${floor.toString()}% floor — everything not yet moved is still readable at ${job.fromLocationId}`;
|
|
1963
2014
|
}
|
|
1964
2015
|
/**
|
|
2016
|
+
* The row as the TARGET should record it, given what the source file
|
|
2017
|
+
* actually measured.
|
|
2018
|
+
*
|
|
2019
|
+
* Equal sizes — every ordinary segment — hand the row straight back. A
|
|
2020
|
+
* disagreement is reconciled rather than carried over, and reconciling it
|
|
2021
|
+
* means RENAMING: a segment's byte count is part of its name
|
|
2022
|
+
* (`segmentRelPath`), the durable hour row derives `bytes` from those names
|
|
2023
|
+
* (`hourAggregate`), and those sums are what `StorageEvictableProvider` reads
|
|
2024
|
+
* when a disk fills. Copying the file under its wrong name would carry the
|
|
2025
|
+
* wrong number to the new disk and leave nothing able to correct it — a disk
|
|
2026
|
+
* walk re-parses the same name and agrees with itself.
|
|
2027
|
+
*
|
|
2028
|
+
* The rename happens at the DESTINATION, before the ledger is touched, so a
|
|
2029
|
+
* crash here leaves the source wholly authoritative and untouched: the next
|
|
2030
|
+
* run re-copies under the old name and re-renames. Nothing is dropped
|
|
2031
|
+
* silently — every re-stamp is one `warn` with `tags: { deviceId }` and both
|
|
2032
|
+
* numbers, and the count rides the job record to the operator.
|
|
2033
|
+
*/
|
|
2034
|
+
async reconciled(job, row, to, srcBytes) {
|
|
2035
|
+
if (srcBytes === row.bytes) return row;
|
|
2036
|
+
const fixed = restampSegmentBytes(row, srcBytes);
|
|
2037
|
+
if (fixed === null) {
|
|
2038
|
+
this.deps.logger.warn("relocate: the recorded size disagrees with the file, and the path is not a canonical segment name — moved as-is, the durable byte count stays WRONG", {
|
|
2039
|
+
tags: { deviceId: row.deviceId },
|
|
2040
|
+
meta: {
|
|
2041
|
+
jobId: job.jobId,
|
|
2042
|
+
path: row.path,
|
|
2043
|
+
recordedBytes: row.bytes,
|
|
2044
|
+
actualBytes: srcBytes
|
|
2045
|
+
}
|
|
2046
|
+
});
|
|
2047
|
+
return row;
|
|
2048
|
+
}
|
|
2049
|
+
await node_fs.promises.rename(node_path.default.join(to.root, row.path), node_path.default.join(to.root, fixed.path));
|
|
2050
|
+
job.rowsReconciled += 1;
|
|
2051
|
+
this.deps.logger.warn("relocate: RECONCILED a row whose recorded size disagreed with the file — the file is the fact, the name and the durable row now say so", {
|
|
2052
|
+
tags: { deviceId: row.deviceId },
|
|
2053
|
+
meta: {
|
|
2054
|
+
jobId: job.jobId,
|
|
2055
|
+
fromPath: row.path,
|
|
2056
|
+
toPath: fixed.path,
|
|
2057
|
+
recordedBytes: row.bytes,
|
|
2058
|
+
actualBytes: srcBytes,
|
|
2059
|
+
deltaBytes: srcBytes - row.bytes,
|
|
2060
|
+
toLocationId: to.id
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
return fixed;
|
|
2064
|
+
}
|
|
2065
|
+
/**
|
|
1965
2066
|
* Move ONE hour of one (device, profile): copy+verify every file, re-point
|
|
1966
2067
|
* the durable hour row, delete the sources, re-point the RAM index.
|
|
1967
2068
|
*
|
|
@@ -1980,9 +2081,12 @@ var RelocateEngine = class {
|
|
|
1980
2081
|
if (job.cancelRequested) return;
|
|
1981
2082
|
const src = node_path.default.join(from.root, row.path);
|
|
1982
2083
|
const dst = node_path.default.join(to.root, row.path);
|
|
2084
|
+
let pacedBytes = row.bytes;
|
|
1983
2085
|
try {
|
|
1984
|
-
|
|
1985
|
-
|
|
2086
|
+
const outcome = await copyVerified(src, dst, row.bytes);
|
|
2087
|
+
pacedBytes = outcome.srcBytes;
|
|
2088
|
+
copiedBytes += outcome.copied;
|
|
2089
|
+
movable.push(await this.reconciled(job, row, to, outcome.srcBytes));
|
|
1986
2090
|
} catch (err) {
|
|
1987
2091
|
if (!isEnoent(err)) throw err;
|
|
1988
2092
|
this.deps.index.removeSegments([row.path]);
|
|
@@ -1994,7 +2098,7 @@ var RelocateEngine = class {
|
|
|
1994
2098
|
}
|
|
1995
2099
|
});
|
|
1996
2100
|
}
|
|
1997
|
-
await sleep(
|
|
2101
|
+
await sleep(pacedBytes / bytesPerMs);
|
|
1998
2102
|
}
|
|
1999
2103
|
if (movable.length === 0) return;
|
|
2000
2104
|
if (job.cancelRequested) return;
|
|
@@ -2017,11 +2121,16 @@ var RelocateEngine = class {
|
|
|
2017
2121
|
});
|
|
2018
2122
|
return;
|
|
2019
2123
|
}
|
|
2020
|
-
if (!samePhysicalRoot) for (const row of movable) await node_fs.promises.rm(node_path.default.join(from.root, row.path), { force: true });
|
|
2124
|
+
if (!samePhysicalRoot) for (const row of movable) await node_fs.promises.rm(node_path.default.join(from.root, row.fromPath ?? row.path), { force: true });
|
|
2021
2125
|
for (const row of movable) {
|
|
2022
|
-
this.deps.index.removeSegments([row.path]);
|
|
2126
|
+
this.deps.index.removeSegments([row.fromPath ?? row.path]);
|
|
2023
2127
|
this.deps.index.addSegment({
|
|
2024
|
-
|
|
2128
|
+
deviceId: row.deviceId,
|
|
2129
|
+
profile: row.profile,
|
|
2130
|
+
startMs: row.startMs,
|
|
2131
|
+
durMs: row.durMs,
|
|
2132
|
+
bytes: row.bytes,
|
|
2133
|
+
path: row.path,
|
|
2025
2134
|
locationId: to.id
|
|
2026
2135
|
});
|
|
2027
2136
|
}
|
|
@@ -2031,6 +2140,25 @@ var RelocateEngine = class {
|
|
|
2031
2140
|
}
|
|
2032
2141
|
};
|
|
2033
2142
|
/**
|
|
2143
|
+
* The same segment, recorded at its REAL size — or `null` when this path is not
|
|
2144
|
+
* one this repo names, in which case nothing here may rename it.
|
|
2145
|
+
*
|
|
2146
|
+
* The refusal is a round-trip, not a shape guess: the canonical name for the
|
|
2147
|
+
* row's own fields must reproduce `row.path` exactly before the corrected name
|
|
2148
|
+
* is trusted. A path that fails it came from somewhere else (a hand-placed
|
|
2149
|
+
* file, a future layout), and renaming it would move footage to a name no
|
|
2150
|
+
* reader derives.
|
|
2151
|
+
*/
|
|
2152
|
+
function restampSegmentBytes(row, actualBytes) {
|
|
2153
|
+
if (segmentRelPath(row.deviceId, row.profile, row.startMs, row.durMs, row.bytes) !== row.path) return null;
|
|
2154
|
+
return {
|
|
2155
|
+
...row,
|
|
2156
|
+
bytes: actualBytes,
|
|
2157
|
+
path: segmentRelPath(row.deviceId, row.profile, row.startMs, row.durMs, actualBytes),
|
|
2158
|
+
fromPath: row.path
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2034
2162
|
* The archive slice this job moves, or `null` when it selects nothing at all.
|
|
2035
2163
|
*
|
|
2036
2164
|
* ONE derivation for the census and for the stream. Deriving them separately
|
|
@@ -8630,6 +8758,13 @@ var SegmentHourLedger = class SegmentHourLedger {
|
|
|
8630
8758
|
* the index `hydrated`: nothing would ever walk that hour again, and the
|
|
8631
8759
|
* segment would sit on disk permanently unreachable.
|
|
8632
8760
|
*
|
|
8761
|
+
* **Two path sets, not one.** A path can arrive at the target under a
|
|
8762
|
+
* DIFFERENT name than it leaves the source under: a mover that found a file
|
|
8763
|
+
* larger than its recorded size reconciles the row, and the byte count is
|
|
8764
|
+
* part of the name. So the source row is shrunk by what is LEAVING it and the
|
|
8765
|
+
* target row grows by what is ARRIVING — conflating them would leave the
|
|
8766
|
+
* source row naming a file the caller is about to delete.
|
|
8767
|
+
*
|
|
8633
8768
|
* Returns `false` when NOTHING was repointed and the caller must delete
|
|
8634
8769
|
* nothing. An hour whose detail could not be read decides nothing (D49) —
|
|
8635
8770
|
* the same refusal {@link dropSegments} makes for eviction.
|
|
@@ -8642,11 +8777,15 @@ var SegmentHourLedger = class SegmentHourLedger {
|
|
|
8642
8777
|
const entry = byHour.get(key);
|
|
8643
8778
|
if (entry === void 0) byHour.set(key, {
|
|
8644
8779
|
row,
|
|
8645
|
-
|
|
8780
|
+
leaving: new Set([row.fromPath ?? row.path]),
|
|
8781
|
+
arriving: new Set([row.path])
|
|
8646
8782
|
});
|
|
8647
|
-
else
|
|
8783
|
+
else {
|
|
8784
|
+
entry.leaving.add(row.fromPath ?? row.path);
|
|
8785
|
+
entry.arriving.add(row.path);
|
|
8786
|
+
}
|
|
8648
8787
|
}
|
|
8649
|
-
for (const [sourceKey, { row,
|
|
8788
|
+
for (const [sourceKey, { row, leaving, arriving }] of byHour) {
|
|
8650
8789
|
const held = await this.resident(sourceKey, row.deviceId);
|
|
8651
8790
|
if (held === null) {
|
|
8652
8791
|
this.logger.warn("recorder: hour detail unavailable — this relocation is REFUSED and nothing is deleted; the segments stay where they are", {
|
|
@@ -8654,7 +8793,7 @@ var SegmentHourLedger = class SegmentHourLedger {
|
|
|
8654
8793
|
meta: {
|
|
8655
8794
|
key: sourceKey,
|
|
8656
8795
|
toLocationId,
|
|
8657
|
-
paths:
|
|
8796
|
+
paths: leaving.size
|
|
8658
8797
|
}
|
|
8659
8798
|
});
|
|
8660
8799
|
return false;
|
|
@@ -8667,12 +8806,12 @@ var SegmentHourLedger = class SegmentHourLedger {
|
|
|
8667
8806
|
meta: {
|
|
8668
8807
|
key: targetKey,
|
|
8669
8808
|
fromLocationId: row.locationId,
|
|
8670
|
-
paths:
|
|
8809
|
+
paths: arriving.size
|
|
8671
8810
|
}
|
|
8672
8811
|
});
|
|
8673
8812
|
return false;
|
|
8674
8813
|
}
|
|
8675
|
-
const merged = uniquePaths([...target?.paths ?? [], ...
|
|
8814
|
+
const merged = uniquePaths([...target?.paths ?? [], ...arriving]);
|
|
8676
8815
|
await this.ledger.put(segmentHourRow({
|
|
8677
8816
|
key: targetKey,
|
|
8678
8817
|
deviceId: row.deviceId,
|
|
@@ -8681,7 +8820,7 @@ var SegmentHourLedger = class SegmentHourLedger {
|
|
|
8681
8820
|
hourStartMs: held.hourStartMs,
|
|
8682
8821
|
paths: merged
|
|
8683
8822
|
}));
|
|
8684
|
-
const next = held.paths.filter((p) => !
|
|
8823
|
+
const next = held.paths.filter((p) => !leaving.has(p));
|
|
8685
8824
|
if (next.length === 0) await this.ledger.forget(sourceKey);
|
|
8686
8825
|
else await this.ledger.put(segmentHourRow({
|
|
8687
8826
|
...held,
|