@camstack/addon-pipeline 1.2.286 → 1.2.288

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/audio-analyzer/index.js +2 -2
  2. package/dist/audio-analyzer/index.mjs +2 -2
  3. package/dist/{default-detection-model-B9sgmjNE.js → default-detection-model-D5kMByfZ.js} +1 -1
  4. package/dist/{default-detection-model-BbaeqJWd.mjs → default-detection-model-DTvsx_iX.mjs} +1 -1
  5. package/dist/detection-pipeline/index.js +4 -4
  6. package/dist/detection-pipeline/index.mjs +4 -4
  7. package/dist/{dist-bAVvh6zw.js → dist-CegiJ2Pw.js} +700 -9
  8. package/dist/{dist-L6fspiMs.mjs → dist-mEtwupOP.mjs} +689 -10
  9. package/dist/motion-wasm/index.js +1 -1
  10. package/dist/motion-wasm/index.mjs +1 -1
  11. package/dist/{node-BKSzm60G.mjs → node-B8p-rV9H.mjs} +1 -1
  12. package/dist/{node-BAHXRXps.js → node-C8jhiPW2.js} +1 -1
  13. package/dist/pipeline-runner/index.js +3 -3
  14. package/dist/pipeline-runner/index.mjs +3 -3
  15. package/dist/{process-memory-gIGkgoj7.mjs → process-memory-C5bRH8-t.mjs} +1 -1
  16. package/dist/{process-memory-B5Enn1QL.js → process-memory-lPbJ1ta2.js} +1 -1
  17. package/dist/recorder/index.js +201 -69
  18. package/dist/recorder/index.mjs +201 -69
  19. package/dist/{segment-demux-js-DIMPKsLl.mjs → segment-demux-js-BP5vqRPY.mjs} +1 -1
  20. package/dist/{segment-demux-js-BCxiqxMJ.js → segment-demux-js-Dv1EPPdH.js} +1 -1
  21. package/dist/stream-broker/_stub.js +2 -2
  22. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BQppCOBh.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BqjkSRCu.mjs} +2 -2
  23. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DqcT4fRG.mjs +26 -0
  24. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DCbVs3IC.mjs +26 -0
  25. package/dist/stream-broker/demux-worker-child.js +1 -1
  26. package/dist/stream-broker/demux-worker-child.mjs +1 -1
  27. package/dist/stream-broker/{hostInit-BMoj1Wh2.mjs → hostInit-C4EuFQ_w.mjs} +2 -2
  28. package/dist/stream-broker/index.js +53 -60
  29. package/dist/stream-broker/index.mjs +53 -60
  30. package/dist/stream-broker/remoteEntry.js +1 -1
  31. package/package.json +1 -1
  32. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BxqJbWC8.mjs +0 -26
  33. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DWcIgV47.mjs +0 -26
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-bAVvh6zw.js");
5
+ const require_dist = require("../dist-CegiJ2Pw.js");
6
6
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
7
7
  let node_fs = require("node:fs");
8
8
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { an as DeviceType, dn as hydrateSchema, it as evaluateZoneRules, tn as BaseAddon, xt as motionDetectionCapability } from "../dist-L6fspiMs.mjs";
1
+ import { Ct as motionDetectionCapability, ot as evaluateZoneRules, pn as hydrateSchema, rn as BaseAddon, sn as DeviceType } from "../dist-mEtwupOP.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 { $t as isSoftwareDecode, Jt as errMsg, Xt as Fmp4BoxSplitter, Zt as buildFfmpegArgs } from "./dist-L6fspiMs.mjs";
1
+ import { $t as buildFfmpegArgs, Qt as Fmp4BoxSplitter, Xt as errMsg, tn as isSoftwareDecode } from "./dist-mEtwupOP.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { realpathSync } from "node:fs";
4
4
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-bAVvh6zw.js");
2
+ const require_dist = require("./dist-CegiJ2Pw.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_fs = require("node:fs");
5
5
  node_fs = require_chunk.__toESM(node_fs, 1);
@@ -3,9 +3,9 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-emK7D4bc.js");
6
- const require_dist = require("../dist-bAVvh6zw.js");
7
- const require_node = require("../node-BAHXRXps.js");
8
- const require_default_detection_model = require("../default-detection-model-B9sgmjNE.js");
6
+ const require_dist = require("../dist-CegiJ2Pw.js");
7
+ const require_node = require("../node-C8jhiPW2.js");
8
+ const require_default_detection_model = require("../default-detection-model-D5kMByfZ.js");
9
9
  const require_worker_protocol = require("../worker-protocol-B2MfQLlu.js");
10
10
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
11
11
  const require_lazy_sharp = require("../lazy-sharp-BuwKlQLR.js");
@@ -1,6 +1,6 @@
1
- import { An as string, D as NativeLeaseSettingsSchema, Dn as object, Dt as pickNativeLeaseOverride, E as NativeLeaseAdmissionSchema, En as number, Et as pickDetailCropConvention, Jt as errMsg, Mn as EventCategory, S as FailureCounters, Sn as boolean, T as MOTION_CLOSE_AFTER_MS, Tn as literal, Z as deriveDetailCropRect, _ as DEVICE_BACKEND_TO_FORMAT, bn as _enum, cn as customAction, ct as failureContributionCapability, g as DEFAULT_NATIVE_LEASE_SETTINGS, hn as nodePin, kt as pipelineRunnerCapability, ln as defineCustomActions, p as DEFAULT_DETAIL_CROP_CONVENTION, pt as loadContributionCapability, sn as createEvent, tn as BaseAddon, wn as lazy, xn as array } from "../dist-L6fspiMs.mjs";
2
- import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-BKSzm60G.mjs";
3
- import { a as localFrameRegistry, d as getStepDefinition, i as rootObjectGate, o as resolveFrameViewGeometry, r as macroGateVerdict } from "../default-detection-model-BbaeqJWd.mjs";
1
+ import { $ as deriveDetailCropRect, C as FailureCounters, Cn as array, D as NativeLeaseAdmissionSchema, Dn as literal, E as MOTION_CLOSE_AFTER_MS, En as lazy, Mn as string, O as NativeLeaseSettingsSchema, On as number, Ot as pickDetailCropConvention, Pn as EventCategory, Sn as _enum, Xt as errMsg, _ as DEFAULT_NATIVE_LEASE_SETTINGS, _n as nodePin, dn as defineCustomActions, ht as loadContributionCapability, jt as pipelineRunnerCapability, kn as object, kt as pickNativeLeaseOverride, ln as createEvent, m as DEFAULT_DETAIL_CROP_CONVENTION, rn as BaseAddon, un as customAction, ut as failureContributionCapability, v as DEVICE_BACKEND_TO_FORMAT, wn as boolean } from "../dist-mEtwupOP.mjs";
2
+ import { i as NO_COST_CLAIM, t as ChildCostRegistry } from "../node-B8p-rV9H.mjs";
3
+ import { a as localFrameRegistry, d as getStepDefinition, i as rootObjectGate, o as resolveFrameViewGeometry, r as macroGateVerdict } from "../default-detection-model-DTvsx_iX.mjs";
4
4
  import { t as isWorkerReply } from "../worker-protocol-C_W-P_g-.mjs";
5
5
  import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
6
6
  import { t as getSharp } from "../lazy-sharp-DXsqwpph.mjs";
@@ -1,4 +1,4 @@
1
- import { Ct as parseProcStatus } from "./dist-L6fspiMs.mjs";
1
+ import { Tt as parseProcStatus } from "./dist-mEtwupOP.mjs";
2
2
  import * as fs from "node:fs";
3
3
  import { execFile } from "node:child_process";
4
4
  //#region src/shared/node-topology-platform.ts
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-emK7D4bc.js");
2
- const require_dist = require("./dist-bAVvh6zw.js");
2
+ const require_dist = require("./dist-CegiJ2Pw.js");
3
3
  let node_fs = require("node:fs");
4
4
  node_fs = require_chunk.__toESM(node_fs);
5
5
  let node_child_process = require("node:child_process");
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../chunk-emK7D4bc.js");
6
- const require_dist = require("../dist-bAVvh6zw.js");
7
- const require_node = require("../node-BAHXRXps.js");
6
+ const require_dist = require("../dist-CegiJ2Pw.js");
7
+ const require_node = require("../node-C8jhiPW2.js");
8
8
  const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
9
9
  const require_restream_intent = require("../restream-intent-7uDNqMKs.js");
10
10
  const require_retire_root_keys = require("../retire-root-keys-Csb8z2f3.js");
@@ -6129,20 +6129,6 @@ function errnoCode(raw) {
6129
6129
  }
6130
6130
  //#endregion
6131
6131
  //#region src/recorder/addon/export-engine.ts
6132
- /**
6133
- * How long an operator's authorised wake stays spendable.
6134
- *
6135
- * One authorised yes is ONE wake (D558 § 5.2 rule 3), and the two ways a job
6136
- * outlives its yes without anybody meaning it are both real here: it can sit
6137
- * behind {@link EXPORT_MAX_CONCURRENT} long renders, and it can be re-queued
6138
- * after a restart. Five minutes is generous against a job measured at 4–6 s
6139
- * end to end and short enough that a camera is never woken for a tap the
6140
- * operator has forgotten making.
6141
- *
6142
- * Past it the export FAILS with `wake-expired` — a named row the operator can
6143
- * retry with one tap, which re-asks for the authorisation — rather than
6144
- * silently waking the camera on a yes from an hour ago.
6145
- */
6146
6132
  var CLIP_WAKE_TTL_MS = 5 * 6e4;
6147
6133
  /** Stderr lines retained for the failure LOG. ffmpeg prints one line per failed
6148
6134
  * segment before the decisive "Error opening input" summary, so a short tail can
@@ -6338,9 +6324,11 @@ var ExportEngine = class {
6338
6324
  await this.fail(id, require_dist.clipExportFailure("wake-expired", `queued ${Math.round(waitedMs / 1e3)}s ago, past the ${Math.round(CLIP_WAKE_TTL_MS / 1e3)}s an authorised wake stays spendable — ask again to wake the camera`));
6339
6325
  return;
6340
6326
  }
6327
+ const fetchClipToFile = this.deps.fetchClipToFile;
6341
6328
  const fetchClipBytes = this.deps.fetchClipBytes;
6342
6329
  const writeExportFile = this.deps.writeExportFile;
6343
- if (fetchClipBytes === void 0 || writeExportFile === void 0) {
6330
+ const inlineWired = fetchClipBytes !== void 0 && writeExportFile !== void 0;
6331
+ if (fetchClipToFile === void 0 && !inlineWired) {
6344
6332
  this.deps.logger.error("clip export refused: this recorder has no clip byte reader wired", {
6345
6333
  tags,
6346
6334
  meta: {
@@ -6363,18 +6351,53 @@ var ExportEngine = class {
6363
6351
  source: subject.source,
6364
6352
  provider: subject.provider,
6365
6353
  profile: subject.profile,
6366
- wake: subject.wake ?? "none"
6354
+ wake: subject.wake ?? "none",
6355
+ transport: fetchClipToFile !== void 0 ? "peer-bytes" : "inline"
6367
6356
  }
6368
6357
  });
6369
- let answer;
6370
- try {
6371
- answer = await fetchClipBytes({
6372
- deviceId: subject.deviceId,
6373
- clipId: subject.clipId,
6374
- provider: subject.provider,
6375
- profile: subject.profile,
6376
- maxBytes: require_dist.RECORDING_EXPORT_MAX_READ_BYTES,
6377
- ...subject.wake !== void 0 ? { wake: subject.wake } : {}
6358
+ const outPath = this.deps.outPath(rec);
6359
+ const request = {
6360
+ deviceId: subject.deviceId,
6361
+ clipId: subject.clipId,
6362
+ provider: subject.provider,
6363
+ profile: subject.profile,
6364
+ maxBytes: require_dist.RECORDING_EXPORT_MAX_READ_BYTES,
6365
+ ...subject.wake !== void 0 ? { wake: subject.wake } : {}
6366
+ };
6367
+ /** What actually landed, whichever transport landed it. */
6368
+ let delivered = null;
6369
+ if (fetchClipToFile !== void 0) try {
6370
+ const answer = await fetchClipToFile({
6371
+ ...request,
6372
+ outPath,
6373
+ maxBytes: require_dist.VIDEOCLIPS_MAX_OFFER_BYTES
6374
+ });
6375
+ if (answer.kind === "written") delivered = {
6376
+ bytes: answer.bytes,
6377
+ served: answer.served,
6378
+ durationMs: answer.durationMs
6379
+ };
6380
+ else if (!inlineWired) {
6381
+ this.deps.logger.error("clip export refused: the provider offers no byte handle", {
6382
+ tags,
6383
+ meta: {
6384
+ exportId: id,
6385
+ clipId: subject.clipId,
6386
+ detail: answer.detail
6387
+ }
6388
+ });
6389
+ await this.fail(id, require_dist.clipExportFailure("fetch-failed", answer.detail));
6390
+ return;
6391
+ } else this.deps.logger.warn("clip export falling back to the inline read — this provider predates the byte transport", {
6392
+ tags,
6393
+ meta: {
6394
+ exportId: id,
6395
+ clipId: subject.clipId,
6396
+ provider: subject.provider,
6397
+ detail: answer.detail,
6398
+ inlineBound: require_dist.RECORDING_EXPORT_MAX_READ_BYTES,
6399
+ hint: `camstack deploy ${subject.provider}`
6400
+ }
6378
6401
  });
6379
6402
  } catch (err) {
6380
6403
  const detail = err instanceof Error ? err.message : String(err);
@@ -6385,85 +6408,123 @@ var ExportEngine = class {
6385
6408
  exportId: id,
6386
6409
  clipId: subject.clipId,
6387
6410
  reason: code,
6388
- error: detail
6411
+ error: detail,
6412
+ transport: "peer-bytes"
6389
6413
  }
6390
6414
  });
6415
+ await this.deps.removeFile(outPath);
6391
6416
  await this.fail(id, require_dist.clipExportFailure(code, detail));
6392
6417
  return;
6393
6418
  }
6419
+ if (delivered === null) {
6420
+ let answer;
6421
+ if (fetchClipBytes === void 0 || writeExportFile === void 0) {
6422
+ await this.fail(id, require_dist.clipExportFailure("fetch-failed", "this recorder has no clip byte reader wired"));
6423
+ return;
6424
+ }
6425
+ try {
6426
+ answer = await fetchClipBytes(request);
6427
+ } catch (err) {
6428
+ const detail = err instanceof Error ? err.message : String(err);
6429
+ const code = classifyClipFetchFailure(detail);
6430
+ this.deps.logger.warn("clip export fetch failed", {
6431
+ tags,
6432
+ meta: {
6433
+ exportId: id,
6434
+ clipId: subject.clipId,
6435
+ reason: code,
6436
+ error: detail,
6437
+ transport: "inline"
6438
+ }
6439
+ });
6440
+ await this.fail(id, require_dist.clipExportFailure(code, detail));
6441
+ return;
6442
+ }
6443
+ if (this.cancelled.has(id)) {
6444
+ this.cancelled.delete(id);
6445
+ await this.fail(id, "cancelled");
6446
+ return;
6447
+ }
6448
+ const bytes = Buffer.from(answer.base64, "base64");
6449
+ if (bytes.byteLength > 52428800) {
6450
+ this.deps.logger.warn("clip export refused: the answer exceeded the transfer bound", {
6451
+ tags,
6452
+ meta: {
6453
+ exportId: id,
6454
+ bytes: bytes.byteLength,
6455
+ maxBytes: require_dist.RECORDING_EXPORT_MAX_READ_BYTES
6456
+ }
6457
+ });
6458
+ await this.fail(id, require_dist.clipExportFailure("too-large-to-transfer", `${bytes.byteLength} > ${require_dist.RECORDING_EXPORT_MAX_READ_BYTES} bytes`));
6459
+ return;
6460
+ }
6461
+ try {
6462
+ await writeExportFile(outPath, bytes);
6463
+ } catch (err) {
6464
+ const detail = err instanceof Error ? err.message : String(err);
6465
+ this.deps.logger.error("clip export could not be written", {
6466
+ tags,
6467
+ meta: {
6468
+ exportId: id,
6469
+ outPath,
6470
+ error: detail
6471
+ }
6472
+ });
6473
+ await this.deps.removeFile(outPath);
6474
+ await this.fail(id, require_dist.clipExportFailure("fetch-failed", `could not write the export: ${detail}`));
6475
+ return;
6476
+ }
6477
+ delivered = {
6478
+ bytes: bytes.byteLength,
6479
+ served: answer.served,
6480
+ durationMs: answer.durationMs ?? null
6481
+ };
6482
+ }
6394
6483
  if (this.cancelled.has(id)) {
6395
6484
  this.cancelled.delete(id);
6485
+ await this.deps.removeFile(outPath);
6396
6486
  await this.fail(id, "cancelled");
6397
6487
  return;
6398
6488
  }
6399
- const bytes = Buffer.from(answer.base64, "base64");
6400
- if (bytes.byteLength > 52428800) {
6401
- this.deps.logger.warn("clip export refused: the answer exceeded the transfer bound", {
6402
- tags,
6403
- meta: {
6404
- exportId: id,
6405
- bytes: bytes.byteLength,
6406
- maxBytes: require_dist.RECORDING_EXPORT_MAX_READ_BYTES
6407
- }
6408
- });
6409
- await this.fail(id, require_dist.clipExportFailure("too-large-to-transfer", `${bytes.byteLength} > ${require_dist.RECORDING_EXPORT_MAX_READ_BYTES} bytes`));
6410
- return;
6411
- }
6412
- if (bytes.byteLength < 1024) {
6489
+ if (delivered.bytes < 1024) {
6413
6490
  this.deps.logger.error("clip export produced no video", {
6414
6491
  tags,
6415
6492
  meta: {
6416
6493
  exportId: id,
6417
6494
  clipId: subject.clipId,
6418
- bytes: bytes.byteLength,
6495
+ bytes: delivered.bytes,
6419
6496
  minBytes: EXPORT_MIN_PLAUSIBLE_BYTES
6420
6497
  }
6421
6498
  });
6422
- await this.fail(id, require_dist.clipExportFailure("fetch-failed", `the source answered ${bytes.byteLength} bytes, under the ${EXPORT_MIN_PLAUSIBLE_BYTES} a playable MP4 needs`));
6423
- return;
6424
- }
6425
- const outPath = this.deps.outPath(rec);
6426
- try {
6427
- await writeExportFile(outPath, bytes);
6428
- } catch (err) {
6429
- const detail = err instanceof Error ? err.message : String(err);
6430
- this.deps.logger.error("clip export could not be written", {
6431
- tags,
6432
- meta: {
6433
- exportId: id,
6434
- outPath,
6435
- error: detail
6436
- }
6437
- });
6438
6499
  await this.deps.removeFile(outPath);
6439
- await this.fail(id, require_dist.clipExportFailure("fetch-failed", `could not write the export: ${detail}`));
6500
+ await this.fail(id, require_dist.clipExportFailure("fetch-failed", `the source answered ${delivered.bytes} bytes, under the ${EXPORT_MIN_PLAUSIBLE_BYTES} a playable MP4 needs`));
6440
6501
  return;
6441
6502
  }
6442
- const servedPatch = answer.served !== rec.profile ? { profile: answer.served } : {};
6443
- if (answer.served !== rec.profile) this.deps.logger.warn("clip export served a different twin than the catalog projected", {
6503
+ const servedPatch = delivered.served !== rec.profile ? { profile: delivered.served } : {};
6504
+ if (delivered.served !== rec.profile) this.deps.logger.warn("clip export served a different twin than the catalog projected", {
6444
6505
  tags,
6445
6506
  meta: {
6446
6507
  exportId: id,
6447
6508
  clipId: subject.clipId,
6448
6509
  asked: subject.profile,
6449
6510
  projected: rec.profile,
6450
- served: answer.served
6511
+ served: delivered.served
6451
6512
  }
6452
6513
  });
6453
6514
  const claimedMs = rec.toMs - rec.fromMs;
6454
- if (answer.durationMs !== void 0 && Math.abs(answer.durationMs - claimedMs) > CLIP_DURATION_TOLERANCE_MS) this.deps.logger.warn("clip export duration disagrees with the catalog row", {
6515
+ if (delivered.durationMs !== null && Math.abs(delivered.durationMs - claimedMs) > CLIP_DURATION_TOLERANCE_MS) this.deps.logger.warn("clip export duration disagrees with the catalog row", {
6455
6516
  tags,
6456
6517
  meta: {
6457
6518
  exportId: id,
6458
6519
  clipId: subject.clipId,
6459
6520
  catalogSpanMs: claimedMs,
6460
- deliveredMs: answer.durationMs
6521
+ deliveredMs: delivered.durationMs
6461
6522
  }
6462
6523
  });
6463
6524
  await patchExport(this.deps.state, id, {
6464
6525
  state: "ready",
6465
6526
  progressPct: 100,
6466
- fileBytes: bytes.byteLength,
6527
+ fileBytes: delivered.bytes,
6467
6528
  error: null,
6468
6529
  ...servedPatch
6469
6530
  });
@@ -6473,13 +6534,13 @@ var ExportEngine = class {
6473
6534
  exportId: id,
6474
6535
  clipId: subject.clipId,
6475
6536
  outPath,
6476
- bytes: bytes.byteLength,
6477
- served: answer.served
6537
+ bytes: delivered.bytes,
6538
+ served: delivered.served
6478
6539
  }
6479
6540
  });
6480
6541
  this.deps.emit(require_dist.EventCategory.RecordingExportCompleted, {
6481
6542
  exportId: id,
6482
- fileBytes: bytes.byteLength,
6543
+ fileBytes: delivered.bytes,
6483
6544
  deviceId: rec.deviceId,
6484
6545
  ...rec.options.title !== void 0 ? { title: rec.options.title } : {},
6485
6546
  ...rec.options.notifyTargetIds !== void 0 && rec.options.notifyTargetIds.length > 0 ? { notifyTargetIds: rec.options.notifyTargetIds } : {}
@@ -19701,6 +19762,77 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
19701
19762
  maxBytes: req.maxBytes,
19702
19763
  ...req.wake !== void 0 ? { wake: req.wake } : {}
19703
19764
  }),
19765
+ fetchClipToFile: async (req) => {
19766
+ const peerBytes = this.ctx.peerBytes;
19767
+ if (peerBytes === void 0) return {
19768
+ kind: "unsupported",
19769
+ detail: "this recorder has no addon-to-addon byte transport wired"
19770
+ };
19771
+ let offered;
19772
+ try {
19773
+ offered = await this.ctx.api.videoclips.offerClipBytes.query({
19774
+ deviceId: req.deviceId,
19775
+ clipId: req.clipId,
19776
+ provider: req.provider,
19777
+ addonId: req.provider,
19778
+ profile: req.profile,
19779
+ maxBytes: req.maxBytes,
19780
+ ...req.wake !== void 0 ? { wake: req.wake } : {}
19781
+ });
19782
+ } catch (err) {
19783
+ const detail = err instanceof Error ? err.message : String(err);
19784
+ if (/NOT_IMPLEMENTED|not implemented|is not a function/i.test(detail)) return {
19785
+ kind: "unsupported",
19786
+ detail: `${req.provider} does not serve videoclips.offerClipBytes: ${detail}`
19787
+ };
19788
+ throw err;
19789
+ }
19790
+ const opened = await peerBytes.open(offered.ticket);
19791
+ if (opened.kind === "refused") {
19792
+ this.ctx.logger.warn("clip export: the byte offer could not be opened", {
19793
+ tags: { deviceId: req.deviceId },
19794
+ meta: {
19795
+ clipId: req.clipId,
19796
+ provider: req.provider,
19797
+ branch: opened.code,
19798
+ detail: opened.detail,
19799
+ mintedOn: offered.ticket.hostNodeId
19800
+ }
19801
+ });
19802
+ throw new Error(require_dist.clipExportFailure("fetch-failed", `${opened.code}: ${opened.detail}`));
19803
+ }
19804
+ const written = await opened.body.writeToFile(req.outPath, { maxBytes: req.maxBytes });
19805
+ if (written.kind === "refused") {
19806
+ this.ctx.logger.warn("clip export: the byte transfer did not complete", {
19807
+ tags: { deviceId: req.deviceId },
19808
+ meta: {
19809
+ clipId: req.clipId,
19810
+ provider: req.provider,
19811
+ branch: written.code,
19812
+ detail: written.detail,
19813
+ bytes: written.bytes,
19814
+ maxBytes: req.maxBytes
19815
+ }
19816
+ });
19817
+ throw new Error(require_dist.clipExportFailure(written.code === "too-large" ? "too-large-to-transfer" : "fetch-failed", written.detail));
19818
+ }
19819
+ this.ctx.logger.info("clip export: bytes streamed by handle", {
19820
+ tags: { deviceId: req.deviceId },
19821
+ meta: {
19822
+ clipId: req.clipId,
19823
+ provider: req.provider,
19824
+ bytes: written.bytes,
19825
+ declaredBytes: offered.ticket.declaredBytes,
19826
+ served: offered.served
19827
+ }
19828
+ });
19829
+ return {
19830
+ kind: "written",
19831
+ bytes: written.bytes,
19832
+ served: offered.served,
19833
+ durationMs: offered.durationMs ?? null
19834
+ };
19835
+ },
19704
19836
  writeExportFile: async (p, bytes) => {
19705
19837
  await node_fs.promises.mkdir(node_path.default.dirname(p), { recursive: true });
19706
19838
  await node_fs.promises.writeFile(p, bytes);