@camstack/system 1.2.180 → 1.2.182
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/addon-runner.js +2 -2
- package/dist/addon-runner.mjs +2 -2
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +235 -89
- package/dist/builtins/device-manager/device-manager.addon.mjs +235 -89
- package/dist/builtins/device-manager/device-meta-actions.d.ts +7 -18
- package/dist/builtins/device-manager/device-provider-context.d.ts +4 -0
- package/dist/builtins/device-manager/migrate-device.d.ts +14 -3
- package/dist/builtins/device-manager/migrate-guard.d.ts +39 -0
- package/dist/builtins/device-manager/migrate-reload.d.ts +8 -0
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +0 -0
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +0 -0
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-DqNTelT4.mjs → dist-CVPtxkvV.mjs} +64 -2
- package/dist/{dist-TEwQZL3g.js → dist-D8VIyu_0.js} +64 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{manifest-system-deps-BVIr3MYJ.js → manifest-system-deps-BbP419V1.js} +1 -1
- package/dist/{manifest-system-deps-Ci-jhrxY.mjs → manifest-system-deps-Bdezdcd5.mjs} +1 -1
- package/dist/{retired-settings-keys-CeSITpIX.mjs → retired-settings-keys-qZHMIuI5.mjs} +1 -1
- package/dist/{retired-settings-keys-DauPtbFR.js → retired-settings-keys-wakiINPT.js} +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $t as isDeviceConfigCap, Bt as DeviceRole, Ft as BaseAddon, H as deviceManagerCapability, J as enumerateSchemaFields, P as buildStreamParamsConfigSchema, Pt as errMsg, U as deviceStateCapability, Vt as DeviceType, W as deviceStatusCapability, Wt as WELL_KNOWN_TAB_MAP, a as CAMERA_SWITCH_ORDER, b as STREAM_PROFILE_META, f as DeviceStatusSchema, ft as normalizeUnit, mt as parseStreamParamsFormPatch, o as CAP_NAMES_WITH_STATUS, on as sleep, q as enumerateItemArrayFields, sn as EventCategory, t as ALL_CAPABILITY_DEFINITIONS, xt as runtimeStatePolicyFor, yt as resolveContainerPrimaryChild, zt as DeviceFeature } from "../../dist-
|
|
2
|
-
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-
|
|
1
|
+
import { $t as isDeviceConfigCap, Bt as DeviceRole, Ft as BaseAddon, H as deviceManagerCapability, J as enumerateSchemaFields, P as buildStreamParamsConfigSchema, Pt as errMsg, U as deviceStateCapability, Vt as DeviceType, W as deviceStatusCapability, Wt as WELL_KNOWN_TAB_MAP, a as CAMERA_SWITCH_ORDER, b as STREAM_PROFILE_META, f as DeviceStatusSchema, ft as normalizeUnit, mt as parseStreamParamsFormPatch, o as CAP_NAMES_WITH_STATUS, on as sleep, q as enumerateItemArrayFields, sn as EventCategory, t as ALL_CAPABILITY_DEFINITIONS, xt as runtimeStatePolicyFor, yt as resolveContainerPrimaryChild, zt as DeviceFeature } from "../../dist-CVPtxkvV.mjs";
|
|
2
|
+
import { n as purgeRetiredSettingsRows } from "../../retired-settings-keys-qZHMIuI5.mjs";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
4
|
import { canonicalDeviceFingerprint } from "@camstack/types/node";
|
|
5
5
|
//#region src/builtins/device-manager/adoption-job-engine.ts
|
|
@@ -1891,7 +1891,10 @@ async function discoverDevices(pctx, input) {
|
|
|
1891
1891
|
stableId: d.stableId,
|
|
1892
1892
|
type: d.type,
|
|
1893
1893
|
suggestedName: d.suggestedName,
|
|
1894
|
-
prefilledConfig: d.prefilledConfig
|
|
1894
|
+
prefilledConfig: d.prefilledConfig,
|
|
1895
|
+
...d.alreadyOnboarded === true ? { alreadyOnboarded: true } : {},
|
|
1896
|
+
...d.onboardedDeviceId !== void 0 ? { onboardedDeviceId: d.onboardedDeviceId } : {},
|
|
1897
|
+
...d.onboardedName !== void 0 ? { onboardedName: d.onboardedName } : {}
|
|
1895
1898
|
}));
|
|
1896
1899
|
}
|
|
1897
1900
|
async function adoptDevice(pctx, input) {
|
|
@@ -3275,8 +3278,6 @@ var DeviceEventPropagator = class {
|
|
|
3275
3278
|
return chain;
|
|
3276
3279
|
}
|
|
3277
3280
|
};
|
|
3278
|
-
//#endregion
|
|
3279
|
-
//#region src/builtins/device-manager/migrate-device.ts
|
|
3280
3281
|
/** A refusal that names a switch the camera does not offer, rather than one it
|
|
3281
3282
|
* could not be asked about. The cap documents rejecting the former; anything
|
|
3282
3283
|
* else is treated as the camera being out of reach, which is the safe reading:
|
|
@@ -3288,10 +3289,31 @@ function classify(err) {
|
|
|
3288
3289
|
detail
|
|
3289
3290
|
};
|
|
3290
3291
|
}
|
|
3292
|
+
/**
|
|
3293
|
+
* One switch write under the bound. The race, not the write, is what fails on
|
|
3294
|
+
* timeout — the underlying promise is marked handled so a late rejection from
|
|
3295
|
+
* a camera that eventually answers "no" cannot surface as an unhandled
|
|
3296
|
+
* rejection after the migration already reported `unreachable`.
|
|
3297
|
+
*/
|
|
3298
|
+
async function setSwitchBounded(deps, deviceId, switchId, enabled) {
|
|
3299
|
+
const budget = deps.switchTimeoutMs ?? 15e3;
|
|
3300
|
+
const write = deps.setSwitch(deviceId, switchId, enabled);
|
|
3301
|
+
write.catch(() => {});
|
|
3302
|
+
let timer;
|
|
3303
|
+
try {
|
|
3304
|
+
await Promise.race([write, new Promise((_resolve, reject) => {
|
|
3305
|
+
timer = setTimeout(() => {
|
|
3306
|
+
reject(/* @__PURE__ */ new Error(`switch write did not answer within ${budget}ms — reported unreachable; if it lands late, a duplicate write of the same value is a no-op`));
|
|
3307
|
+
}, budget);
|
|
3308
|
+
})]);
|
|
3309
|
+
} finally {
|
|
3310
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3291
3313
|
async function applyAll(deps, deviceId, enabled) {
|
|
3292
3314
|
const out = [];
|
|
3293
3315
|
for (const switchId of CAMERA_SWITCH_ORDER) try {
|
|
3294
|
-
await deps
|
|
3316
|
+
await setSwitchBounded(deps, deviceId, switchId, enabled);
|
|
3295
3317
|
out.push({
|
|
3296
3318
|
deviceId,
|
|
3297
3319
|
switchId,
|
|
@@ -3339,7 +3361,6 @@ async function migrateDevice$1(deps, input) {
|
|
|
3339
3361
|
});
|
|
3340
3362
|
}
|
|
3341
3363
|
const up = await applyAll(deps, sourceId, true);
|
|
3342
|
-
await deps.respawnRunners([sourceId, targetId]);
|
|
3343
3364
|
deps.log("camera migrated", {
|
|
3344
3365
|
sourceId,
|
|
3345
3366
|
targetId,
|
|
@@ -3355,6 +3376,52 @@ async function migrateDevice$1(deps, input) {
|
|
|
3355
3376
|
};
|
|
3356
3377
|
}
|
|
3357
3378
|
//#endregion
|
|
3379
|
+
//#region src/builtins/device-manager/migrate-reload.ts
|
|
3380
|
+
async function reloadMigratedDevices(pctx, targets) {
|
|
3381
|
+
const ctx = pctx.host.ctx;
|
|
3382
|
+
for (const target of targets) {
|
|
3383
|
+
pctx.metaStore.idToAddonId.set(target.deviceId, target.addonId);
|
|
3384
|
+
pctx.host.remoteNativeCaps.delete(target.deviceId);
|
|
3385
|
+
pctx.host.capabilityRegistry?.unregisterAllNativeForDevice(target.deviceId);
|
|
3386
|
+
}
|
|
3387
|
+
const fallbackAddons = /* @__PURE__ */ new Map();
|
|
3388
|
+
await Promise.all(targets.map(async (target) => {
|
|
3389
|
+
try {
|
|
3390
|
+
const reloaded = await (await pctx.host.requireDeviceProvider(target.addonId)).reloadDevice({ stableId: target.stableId });
|
|
3391
|
+
ctx.logger.info("migration: device reloaded in place — no other device disturbed", {
|
|
3392
|
+
tags: { deviceId: target.deviceId },
|
|
3393
|
+
meta: {
|
|
3394
|
+
addonId: target.addonId,
|
|
3395
|
+
stableId: target.stableId,
|
|
3396
|
+
reloadedAs: reloaded.deviceId
|
|
3397
|
+
}
|
|
3398
|
+
});
|
|
3399
|
+
} catch (err) {
|
|
3400
|
+
ctx.logger.error("migration: in-place reload FAILED — falling back to a provider restart", {
|
|
3401
|
+
tags: { deviceId: target.deviceId },
|
|
3402
|
+
meta: {
|
|
3403
|
+
addonId: target.addonId,
|
|
3404
|
+
stableId: target.stableId,
|
|
3405
|
+
error: err instanceof Error ? err.message : String(err)
|
|
3406
|
+
}
|
|
3407
|
+
});
|
|
3408
|
+
fallbackAddons.set(target.addonId, target.deviceId);
|
|
3409
|
+
}
|
|
3410
|
+
}));
|
|
3411
|
+
if (fallbackAddons.size === 0) return;
|
|
3412
|
+
await Promise.all([...fallbackAddons.entries()].map(async ([addonId, migratedDeviceId]) => {
|
|
3413
|
+
const owned = [...pctx.metaStore.idToAddonId.entries()].filter(([, a]) => a === addonId).length;
|
|
3414
|
+
ctx.logger.info("migration: restarting a whole provider to flush the id maps", {
|
|
3415
|
+
tags: { deviceId: migratedDeviceId },
|
|
3416
|
+
meta: {
|
|
3417
|
+
addonId,
|
|
3418
|
+
devicesTakenDown: owned
|
|
3419
|
+
}
|
|
3420
|
+
});
|
|
3421
|
+
await ctx.api.addons.restartAddon.mutate({ addonId });
|
|
3422
|
+
}));
|
|
3423
|
+
}
|
|
3424
|
+
//#endregion
|
|
3358
3425
|
//#region src/builtins/device-manager/migrate-hardware-state.ts
|
|
3359
3426
|
/**
|
|
3360
3427
|
* The per-device state half of a migration (`deviceManager.migrateDevice`).
|
|
@@ -3535,72 +3602,121 @@ async function allocateDeviceId(pctx, input) {
|
|
|
3535
3602
|
* The temp id comes from `allocateNextDeviceId`, the monotonic counter, so the
|
|
3536
3603
|
* value a crash could park a row on was never used and will never be reused.
|
|
3537
3604
|
* `swapIds` therefore runs INSIDE the same lock the id was allocated under.
|
|
3605
|
+
*
|
|
3606
|
+
* Retry-safe since 2026-09-04 (`migrate-guard.ts`): a concurrent call touching
|
|
3607
|
+
* either device is REFUSED before it can queue on the lock, and a repeat of a
|
|
3608
|
+
* completed swap — matched against the `addonId`/`stableId` fingerprint the
|
|
3609
|
+
* swap left on the rows — is a no-op returning the original report. A client
|
|
3610
|
+
* retry ran a second full cycle on 2026-09-01 and swapped two cameras back;
|
|
3611
|
+
* neither path can re-run a swap any more.
|
|
3538
3612
|
*/
|
|
3539
3613
|
async function migrateDevice(pctx, input) {
|
|
3540
3614
|
const { sourceId, targetId } = input;
|
|
3541
3615
|
const ctx = pctx.host.ctx;
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
},
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
}
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
pctx.host.seedMirror(b, pctx.host.withResetSessionProbe(swapped.runtimeStateNowAtTarget));
|
|
3560
|
-
ctx.logger.info("migration: hardware-scoped device state swapped", {
|
|
3561
|
-
tags: { deviceId: a },
|
|
3616
|
+
pctx.migrationGuard.begin(sourceId, targetId);
|
|
3617
|
+
try {
|
|
3618
|
+
const outcome = await pctx.metaStore.withMetaWriteLock(async () => {
|
|
3619
|
+
const sourceRow = await pctx.metaStore.rows.get(sourceId);
|
|
3620
|
+
if (sourceRow === null) throw new Error(`[device-manager] migrateDevice: device ${sourceId} does not exist`);
|
|
3621
|
+
const targetRow = await pctx.metaStore.rows.get(targetId);
|
|
3622
|
+
if (targetRow === null) throw new Error(`[device-manager] migrateDevice: device ${targetId} does not exist`);
|
|
3623
|
+
const replay = pctx.migrationGuard.matchReplay(sourceId, targetId, {
|
|
3624
|
+
addonId: sourceRow.meta.addonId,
|
|
3625
|
+
stableId: sourceRow.meta.stableId
|
|
3626
|
+
}, {
|
|
3627
|
+
addonId: targetRow.meta.addonId,
|
|
3628
|
+
stableId: targetRow.meta.stableId
|
|
3629
|
+
});
|
|
3630
|
+
if (replay !== null) {
|
|
3631
|
+
ctx.logger.info("migrateDevice: this swap already completed — replaying the original report, NOTHING re-run", {
|
|
3632
|
+
tags: { deviceId: sourceId },
|
|
3562
3633
|
meta: {
|
|
3563
|
-
sourceId
|
|
3564
|
-
targetId
|
|
3565
|
-
hardwareKeysToSource: swapped.hardwareKeysToSource,
|
|
3566
|
-
hardwareKeysToTarget: swapped.hardwareKeysToTarget,
|
|
3567
|
-
roleKeysKeptAtSource: swapped.roleKeysKeptAtSource,
|
|
3568
|
-
roleKeysKeptAtTarget: swapped.roleKeysKeptAtTarget
|
|
3634
|
+
sourceId,
|
|
3635
|
+
targetId
|
|
3569
3636
|
}
|
|
3570
3637
|
});
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
if (
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3638
|
+
return {
|
|
3639
|
+
result: replay,
|
|
3640
|
+
reloadTargets: null
|
|
3641
|
+
};
|
|
3642
|
+
}
|
|
3643
|
+
const tempId = await pctx.metaStore.allocateNextDeviceId();
|
|
3644
|
+
const result = await migrateDevice$1({
|
|
3645
|
+
setSwitch: async (deviceId, switchId, enabled) => {
|
|
3646
|
+
if (switchId === "stream-broker") {
|
|
3647
|
+
const moved = await writeDisabledFlagUnderLock(pctx, deviceId, !enabled);
|
|
3648
|
+
emitDisabledEvents(pctx, deviceId, !enabled, moved);
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
await ctx.api.pipelineOrchestrator.setCameraSwitch.mutate({
|
|
3652
|
+
deviceId,
|
|
3653
|
+
switchId,
|
|
3654
|
+
enabled
|
|
3655
|
+
});
|
|
3656
|
+
},
|
|
3657
|
+
swapIds: async (a, b) => {
|
|
3658
|
+
await pctx.metaStore.rows.swapIds(a, b, tempId);
|
|
3659
|
+
},
|
|
3660
|
+
swapHardwareState: async (a, b) => {
|
|
3661
|
+
const swapped = await swapHardwareState(pctx.settings, a, b);
|
|
3662
|
+
pctx.host.seedMirror(a, pctx.host.withResetSessionProbe(swapped.runtimeStateNowAtSource));
|
|
3663
|
+
pctx.host.seedMirror(b, pctx.host.withResetSessionProbe(swapped.runtimeStateNowAtTarget));
|
|
3664
|
+
ctx.logger.info("migration: hardware-scoped device state swapped", {
|
|
3665
|
+
tags: { deviceId: a },
|
|
3585
3666
|
meta: {
|
|
3586
|
-
|
|
3587
|
-
|
|
3667
|
+
sourceId: a,
|
|
3668
|
+
targetId: b,
|
|
3669
|
+
hardwareKeysToSource: swapped.hardwareKeysToSource,
|
|
3670
|
+
hardwareKeysToTarget: swapped.hardwareKeysToTarget,
|
|
3671
|
+
roleKeysKeptAtSource: swapped.roleKeysKeptAtSource,
|
|
3672
|
+
roleKeysKeptAtTarget: swapped.roleKeysKeptAtTarget
|
|
3588
3673
|
}
|
|
3589
3674
|
});
|
|
3590
|
-
|
|
3675
|
+
},
|
|
3676
|
+
forgetStreamState: async (deviceId) => {
|
|
3677
|
+
await ctx.api.streamBroker.forgetDeviceHardware.mutate({ deviceId });
|
|
3678
|
+
},
|
|
3679
|
+
log: (message, meta) => {
|
|
3680
|
+
ctx.logger.info(message, {
|
|
3681
|
+
tags: { deviceId: sourceId },
|
|
3682
|
+
meta
|
|
3683
|
+
});
|
|
3591
3684
|
}
|
|
3592
|
-
},
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3685
|
+
}, {
|
|
3686
|
+
sourceId,
|
|
3687
|
+
targetId
|
|
3688
|
+
});
|
|
3689
|
+
pctx.migrationGuard.recordCompleted({
|
|
3690
|
+
sourceId,
|
|
3691
|
+
targetId,
|
|
3692
|
+
identityAtSource: {
|
|
3693
|
+
addonId: targetRow.meta.addonId,
|
|
3694
|
+
stableId: targetRow.meta.stableId
|
|
3695
|
+
},
|
|
3696
|
+
identityAtTarget: {
|
|
3697
|
+
addonId: sourceRow.meta.addonId,
|
|
3698
|
+
stableId: sourceRow.meta.stableId
|
|
3699
|
+
},
|
|
3700
|
+
result
|
|
3701
|
+
});
|
|
3702
|
+
return {
|
|
3703
|
+
result,
|
|
3704
|
+
reloadTargets: [{
|
|
3705
|
+
deviceId: sourceId,
|
|
3706
|
+
addonId: targetRow.meta.addonId,
|
|
3707
|
+
stableId: targetRow.meta.stableId
|
|
3708
|
+
}, {
|
|
3709
|
+
deviceId: targetId,
|
|
3710
|
+
addonId: sourceRow.meta.addonId,
|
|
3711
|
+
stableId: sourceRow.meta.stableId
|
|
3712
|
+
}]
|
|
3713
|
+
};
|
|
3602
3714
|
});
|
|
3603
|
-
|
|
3715
|
+
if (outcome.reloadTargets !== null) await reloadMigratedDevices(pctx, outcome.reloadTargets);
|
|
3716
|
+
return outcome.result;
|
|
3717
|
+
} finally {
|
|
3718
|
+
pctx.migrationGuard.end(sourceId, targetId);
|
|
3719
|
+
}
|
|
3604
3720
|
}
|
|
3605
3721
|
async function registerDevice(pctx, input) {
|
|
3606
3722
|
const { addonId, stableId, id, type, name, parentDeviceId, features, config } = input;
|
|
@@ -4287,35 +4403,23 @@ async function setMetadata(pctx, input) {
|
|
|
4287
4403
|
});
|
|
4288
4404
|
}
|
|
4289
4405
|
/**
|
|
4290
|
-
*
|
|
4291
|
-
*
|
|
4292
|
-
*
|
|
4293
|
-
*
|
|
4294
|
-
*
|
|
4295
|
-
* TWO events leave here, and they are not the same message:
|
|
4296
|
-
*
|
|
4297
|
-
* - `device.meta-changed` fires on EVERY call. It is the meta-surface echo
|
|
4298
|
-
* every UI redraws on, and idempotence is not interesting to it.
|
|
4299
|
-
* - `device.disabled` / `device.enabled` fire ONLY when the flag actually
|
|
4300
|
-
* MOVES. They are the lifecycle announcement — the operator asked to be
|
|
4301
|
-
* told when a camera is switched off, and a write that re-states a flag the
|
|
4302
|
-
* device already had is not that. Telemetry semantics (D8) are fine here: a
|
|
4303
|
-
* dropped announcement costs a notification, never durable state, and the
|
|
4304
|
-
* meta row is the authority either way (D62 — this switch stores nothing of
|
|
4305
|
-
* its own).
|
|
4406
|
+
* Read + patch the `disabled` flag. The caller HOLDS the meta write lock —
|
|
4407
|
+
* this is split out of {@link setDisabled} so `migrateDevice`, which holds the
|
|
4408
|
+
* lock for its whole run, can write the same authority without re-acquiring
|
|
4409
|
+
* it (the self-deadlock documented at its `setSwitch`).
|
|
4306
4410
|
*/
|
|
4307
|
-
async function
|
|
4308
|
-
const
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4411
|
+
async function writeDisabledFlagUnderLock(pctx, deviceId, disabled) {
|
|
4412
|
+
const persisted = await pctx.metaStore.resolvePersistedById(deviceId);
|
|
4413
|
+
if (!persisted) throw new Error(`[device-manager] setDisabled: unknown device id=${deviceId}`);
|
|
4414
|
+
const { meta: m } = persisted;
|
|
4415
|
+
await pctx.metaStore.rows.patch(deviceId, { disabled });
|
|
4416
|
+
return {
|
|
4417
|
+
changed: (m.disabled ?? false) !== disabled,
|
|
4418
|
+
integrationId: m.integrationId ?? ""
|
|
4419
|
+
};
|
|
4420
|
+
}
|
|
4421
|
+
/** The two announcements — meta echo always, lifecycle only on a transition. */
|
|
4422
|
+
function emitDisabledEvents(pctx, deviceId, disabled, moved) {
|
|
4319
4423
|
pctx.host.ctx.eventBus.emit({
|
|
4320
4424
|
id: randomUUID(),
|
|
4321
4425
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -4345,6 +4449,10 @@ async function setDisabled(pctx, input) {
|
|
|
4345
4449
|
}
|
|
4346
4450
|
});
|
|
4347
4451
|
}
|
|
4452
|
+
async function setDisabled(pctx, input) {
|
|
4453
|
+
const { deviceId, disabled } = input;
|
|
4454
|
+
emitDisabledEvents(pctx, deviceId, disabled, await pctx.metaStore.withMetaWriteLock(() => writeDisabledFlagUnderLock(pctx, deviceId, disabled)));
|
|
4455
|
+
}
|
|
4348
4456
|
async function loadRuntimeState(pctx, input) {
|
|
4349
4457
|
const { deviceId } = input;
|
|
4350
4458
|
if (!await pctx.metaStore.resolvePersistedById(deviceId)) return {};
|
|
@@ -5959,6 +6067,43 @@ function resolveNativeCapOwnerSync(pctx, capName, deviceId) {
|
|
|
5959
6067
|
};
|
|
5960
6068
|
return resolveRemoteNativeCapFromRegistry(pctx.bindingsDeps, capName, deviceId);
|
|
5961
6069
|
}
|
|
6070
|
+
function sameIdentity(a, b) {
|
|
6071
|
+
return a.addonId === b.addonId && a.stableId === b.stableId;
|
|
6072
|
+
}
|
|
6073
|
+
/** One guard per device-manager instance. `now` is injectable for the specs. */
|
|
6074
|
+
function createMigrationGuard(now = Date.now) {
|
|
6075
|
+
const inFlight = /* @__PURE__ */ new Set();
|
|
6076
|
+
const completed = /* @__PURE__ */ new Map();
|
|
6077
|
+
const pairKey = (sourceId, targetId) => `${sourceId}->${targetId}`;
|
|
6078
|
+
return {
|
|
6079
|
+
begin(sourceId, targetId) {
|
|
6080
|
+
for (const id of [sourceId, targetId]) if (inFlight.has(id)) throw new Error(`[device-manager] migrateDevice: a migration involving device ${id} is already in flight — this call was refused, not queued. The running migration's report stands; re-read the device rows before retrying.`);
|
|
6081
|
+
inFlight.add(sourceId);
|
|
6082
|
+
inFlight.add(targetId);
|
|
6083
|
+
},
|
|
6084
|
+
end(sourceId, targetId) {
|
|
6085
|
+
inFlight.delete(sourceId);
|
|
6086
|
+
inFlight.delete(targetId);
|
|
6087
|
+
},
|
|
6088
|
+
recordCompleted(record) {
|
|
6089
|
+
completed.set(pairKey(record.sourceId, record.targetId), {
|
|
6090
|
+
...record,
|
|
6091
|
+
completedAt: now()
|
|
6092
|
+
});
|
|
6093
|
+
},
|
|
6094
|
+
matchReplay(sourceId, targetId, atSource, atTarget) {
|
|
6095
|
+
const key = pairKey(sourceId, targetId);
|
|
6096
|
+
const record = completed.get(key);
|
|
6097
|
+
if (record === void 0) return null;
|
|
6098
|
+
if (now() - record.completedAt > 9e5) {
|
|
6099
|
+
completed.delete(key);
|
|
6100
|
+
return null;
|
|
6101
|
+
}
|
|
6102
|
+
if (!sameIdentity(record.identityAtSource, atSource) || !sameIdentity(record.identityAtTarget, atTarget)) return null;
|
|
6103
|
+
return record.result;
|
|
6104
|
+
}
|
|
6105
|
+
};
|
|
6106
|
+
}
|
|
5962
6107
|
//#endregion
|
|
5963
6108
|
//#region src/builtins/device-manager/device-manager.addon.ts
|
|
5964
6109
|
var DeviceManagerAddon = class extends BaseAddon {
|
|
@@ -6199,6 +6344,7 @@ var DeviceManagerAddon = class extends BaseAddon {
|
|
|
6199
6344
|
settings,
|
|
6200
6345
|
registry,
|
|
6201
6346
|
bindingsDeps: this.bindingsDeps,
|
|
6347
|
+
migrationGuard: createMigrationGuard(),
|
|
6202
6348
|
requireDeviceOps,
|
|
6203
6349
|
stampIntegrationId: stampIntegrationId$1,
|
|
6204
6350
|
get provider() {
|
|
@@ -24,6 +24,13 @@ export declare function allocateDeviceId(pctx: ProviderContext, input: Parameter
|
|
|
24
24
|
* The temp id comes from `allocateNextDeviceId`, the monotonic counter, so the
|
|
25
25
|
* value a crash could park a row on was never used and will never be reused.
|
|
26
26
|
* `swapIds` therefore runs INSIDE the same lock the id was allocated under.
|
|
27
|
+
*
|
|
28
|
+
* Retry-safe since 2026-09-04 (`migrate-guard.ts`): a concurrent call touching
|
|
29
|
+
* either device is REFUSED before it can queue on the lock, and a repeat of a
|
|
30
|
+
* completed swap — matched against the `addonId`/`stableId` fingerprint the
|
|
31
|
+
* swap left on the rows — is a no-op returning the original report. A client
|
|
32
|
+
* retry ran a second full cycle on 2026-09-01 and swapped two cameras back;
|
|
33
|
+
* neither path can re-run a swap any more.
|
|
27
34
|
*/
|
|
28
35
|
export declare function migrateDevice(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['migrateDevice']>[0]): ReturnType<IDeviceManagerProvider['migrateDevice']>;
|
|
29
36
|
export declare function registerDevice(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['registerDevice']>[0]): ReturnType<IDeviceManagerProvider['registerDevice']>;
|
|
@@ -188,24 +195,6 @@ export declare function applyInitialMeta(pctx: ProviderContext, input: Parameter
|
|
|
188
195
|
* the meta-changed event.
|
|
189
196
|
*/
|
|
190
197
|
export declare function setMetadata(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['setMetadata']>[0]): ReturnType<IDeviceManagerProvider['setMetadata']>;
|
|
191
|
-
/**
|
|
192
|
-
* Soft-disable the device. Persisted on the meta row;
|
|
193
|
-
* lifecycle gating is the driver's responsibility (BaseDevice
|
|
194
|
-
* exposes `this.disabled` for the driver to consult at the top
|
|
195
|
-
* of its lifecycle methods).
|
|
196
|
-
*
|
|
197
|
-
* TWO events leave here, and they are not the same message:
|
|
198
|
-
*
|
|
199
|
-
* - `device.meta-changed` fires on EVERY call. It is the meta-surface echo
|
|
200
|
-
* every UI redraws on, and idempotence is not interesting to it.
|
|
201
|
-
* - `device.disabled` / `device.enabled` fire ONLY when the flag actually
|
|
202
|
-
* MOVES. They are the lifecycle announcement — the operator asked to be
|
|
203
|
-
* told when a camera is switched off, and a write that re-states a flag the
|
|
204
|
-
* device already had is not that. Telemetry semantics (D8) are fine here: a
|
|
205
|
-
* dropped announcement costs a notification, never durable state, and the
|
|
206
|
-
* meta row is the authority either way (D62 — this switch stores nothing of
|
|
207
|
-
* its own).
|
|
208
|
-
*/
|
|
209
198
|
export declare function setDisabled(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['setDisabled']>[0]): ReturnType<IDeviceManagerProvider['setDisabled']>;
|
|
210
199
|
export declare function loadRuntimeState(pctx: ProviderContext, input: Parameters<IDeviceManagerProvider['loadRuntimeState']>[0]): ReturnType<IDeviceManagerProvider['loadRuntimeState']>;
|
|
211
200
|
/**
|
|
@@ -2,6 +2,7 @@ import { AddonContext, ICapabilityRegistry, IDeviceAdoptionProvider, IDeviceMana
|
|
|
2
2
|
import { AdoptionJobEngine } from './adoption-job-engine.js';
|
|
3
3
|
import { BindingsDeps } from './device-bindings-store.js';
|
|
4
4
|
import { DeviceManagerSettings, DeviceMetaStore } from './device-meta-store.js';
|
|
5
|
+
import { MigrationGuard } from './migrate-guard.js';
|
|
5
6
|
type IDeviceProviderCap = InferProvider<typeof deviceProviderCapability>;
|
|
6
7
|
/**
|
|
7
8
|
* The addon-instance surface the extracted provider functions need. Exposed by
|
|
@@ -47,6 +48,9 @@ export interface ProviderContext {
|
|
|
47
48
|
/** Hub-process device registry (null when this node owns no registry). */
|
|
48
49
|
readonly registry: IDeviceRegistry | null;
|
|
49
50
|
readonly bindingsDeps: BindingsDeps;
|
|
51
|
+
/** In-flight refusal + completed-swap replay for `migrateDevice` — the
|
|
52
|
+
* reason a retried migration can no longer undo the one that ran. */
|
|
53
|
+
readonly migrationGuard: MigrationGuard;
|
|
50
54
|
/** Resolve the per-device `device-ops` native provider (throws when absent). */
|
|
51
55
|
requireDeviceOps(deviceId: number): IDeviceOpsProvider;
|
|
52
56
|
/** Stamp an integration id onto a device's meta row + emit DeviceMetaChanged. */
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { CameraSwitchId } from '@camstack/types';
|
|
2
|
+
/**
|
|
3
|
+
* Upper bound for ONE switch write. Generous against a live camera (a real
|
|
4
|
+
* write is sub-second; the camera-plane pair is a few seconds of HTTP) and
|
|
5
|
+
* small against the alternative: the 60 s transport default that let three
|
|
6
|
+
* phases burn three minutes on 2026-09-01.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SWITCH_WRITE_TIMEOUT_MS = 15000;
|
|
2
9
|
/** What actually happened to one switch on one device. */
|
|
3
10
|
export type SwitchOutcome = 'off' | 'on' | 'not-offered' | 'unreachable';
|
|
4
11
|
export interface SwitchReport {
|
|
@@ -59,10 +66,14 @@ export interface MigrateDeviceDeps {
|
|
|
59
66
|
* dropped event (D8) would leave the feeder respawning forever.
|
|
60
67
|
*/
|
|
61
68
|
readonly forgetStreamState: (deviceId: number) => Promise<void>;
|
|
62
|
-
/** Respawn the runners that hold either number in memory. Disabling stops
|
|
63
|
-
* data PRODUCTION; it does not flush a cache that maps id → addon. */
|
|
64
|
-
readonly respawnRunners: (deviceIds: readonly number[]) => Promise<void>;
|
|
65
69
|
readonly log: (message: string, meta: Record<string, unknown>) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Override for {@link SWITCH_WRITE_TIMEOUT_MS}, for the specs. A write that
|
|
72
|
+
* outlives the bound is reported `unreachable` — never `off`/`on` — and may
|
|
73
|
+
* still land later, which every switch authority tolerates (a duplicate
|
|
74
|
+
* write of the same value is a no-op at all eight of them).
|
|
75
|
+
*/
|
|
76
|
+
readonly switchTimeoutMs?: number;
|
|
66
77
|
}
|
|
67
78
|
/**
|
|
68
79
|
* Put both cameras to sleep, exchange their identities, wake the target.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { MigrateDeviceResult } from './migrate-device.js';
|
|
2
|
+
/** The addon-facing identity a device row carries — what `swapIds` moves. */
|
|
3
|
+
export interface DeviceIdentity {
|
|
4
|
+
readonly addonId: string;
|
|
5
|
+
readonly stableId: string;
|
|
6
|
+
}
|
|
7
|
+
/** What a finished migration left behind, for replay matching. */
|
|
8
|
+
export interface CompletedMigration {
|
|
9
|
+
readonly sourceId: number;
|
|
10
|
+
readonly targetId: number;
|
|
11
|
+
/** Identity the completed swap left at `sourceId` (the pre-swap target's). */
|
|
12
|
+
readonly identityAtSource: DeviceIdentity;
|
|
13
|
+
/** Identity the completed swap left at `targetId` (the pre-swap source's). */
|
|
14
|
+
readonly identityAtTarget: DeviceIdentity;
|
|
15
|
+
readonly result: MigrateDeviceResult;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* How long a completed migration absorbs an identical repeat call. Sized to
|
|
19
|
+
* comfortably cover the cap's own `timeoutMs` (10 min): a retry fired by a
|
|
20
|
+
* client that gave up arrives inside that envelope; a call arriving later is
|
|
21
|
+
* an operator's deliberate new operation and runs.
|
|
22
|
+
*/
|
|
23
|
+
export declare const MIGRATION_REPLAY_WINDOW_MS: number;
|
|
24
|
+
export interface MigrationGuard {
|
|
25
|
+
/** Claim both ids for a run. Throws when either is already in flight. */
|
|
26
|
+
begin(sourceId: number, targetId: number): void;
|
|
27
|
+
/** Release both ids. Always paired with {@link begin} via try/finally. */
|
|
28
|
+
end(sourceId: number, targetId: number): void;
|
|
29
|
+
/** Record a completed swap's fingerprint for replay matching. */
|
|
30
|
+
recordCompleted(record: CompletedMigration): void;
|
|
31
|
+
/**
|
|
32
|
+
* The original report, when the call is a repeat of a completed swap: same
|
|
33
|
+
* ordered pair, current row identities equal to the recorded post-swap
|
|
34
|
+
* identities, within the window. `null` means "this is a new operation".
|
|
35
|
+
*/
|
|
36
|
+
matchReplay(sourceId: number, targetId: number, atSource: DeviceIdentity, atTarget: DeviceIdentity): MigrateDeviceResult | null;
|
|
37
|
+
}
|
|
38
|
+
/** One guard per device-manager instance. `now` is injectable for the specs. */
|
|
39
|
+
export declare function createMigrationGuard(now?: () => number): MigrationGuard;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ProviderContext } from './device-provider-context.js';
|
|
2
|
+
/** One migrated number and the identity that lives at it AFTER the swap. */
|
|
3
|
+
export interface MigratedDeviceTarget {
|
|
4
|
+
readonly deviceId: number;
|
|
5
|
+
readonly addonId: string;
|
|
6
|
+
readonly stableId: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function reloadMigratedDevices(pctx: ProviderContext, targets: readonly MigratedDeviceTarget[]): Promise<void>;
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
7
7
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
8
8
|
/**
|
|
9
9
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as BaseAddon, G as doorbellCapability, Jt as createEvent, M as bareAddonId, Pt as errMsg, Vt as DeviceType, Y as evaluateSensorEdge, _ as SOURCE_CAPS, nt as isSameAddonId, rt as isSourceCap, sn as EventCategory, v as SOURCE_DEVICE_TYPES } from "../../dist-
|
|
1
|
+
import { Ft as BaseAddon, G as doorbellCapability, Jt as createEvent, M as bareAddonId, Pt as errMsg, Vt as DeviceType, Y as evaluateSensorEdge, _ as SOURCE_CAPS, nt as isSameAddonId, rt as isSourceCap, sn as EventCategory, v as SOURCE_DEVICE_TYPES } from "../../dist-CVPtxkvV.mjs";
|
|
2
2
|
//#region src/builtins/doorbell/trigger-engine.ts
|
|
3
3
|
/**
|
|
4
4
|
* Pure trigger logic for the virtual-doorbell builtin — edge detection over
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
7
7
|
const require_formatter = require("../../formatter-DqAKDlvN.js");
|
|
8
8
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
9
9
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-
|
|
1
|
+
import { Ft as BaseAddon, ct as logDestinationCapability } from "../../dist-CVPtxkvV.mjs";
|
|
2
2
|
import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
|
|
3
3
|
//#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
|
|
4
4
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
4
4
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
5
5
|
var NO_DEVICES = "liveness:no-devices";
|
|
6
6
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as BaseAddon, Jt as createEvent, Pt as errMsg, sn as EventCategory } from "../../dist-
|
|
1
|
+
import { Ft as BaseAddon, Jt as createEvent, Pt as errMsg, sn as EventCategory } from "../../dist-CVPtxkvV.mjs";
|
|
2
2
|
//#region src/builtins/liveness-monitor/liveness-checks.ts
|
|
3
3
|
var NO_DEVICES = "liveness:no-devices";
|
|
4
4
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
7
7
|
let node_crypto = require("node:crypto");
|
|
8
8
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
9
9
|
let crypto$1 = require("crypto");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { A as authProviderCapability, Ft as BaseAddon, T as UserRecordSchema, jt as userManagementCapability, r as ApiKeyRecordSchema, x as ScopedTokenSchema } from "../../dist-
|
|
2
|
+
import { A as authProviderCapability, Ft as BaseAddon, T as UserRecordSchema, jt as userManagementCapability, r as ApiKeyRecordSchema, x as ScopedTokenSchema } from "../../dist-CVPtxkvV.mjs";
|
|
3
3
|
import * as crypto$2 from "node:crypto";
|
|
4
4
|
import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
|
|
5
5
|
import nodeCrypto from "crypto";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("../../chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("../../dist-
|
|
3
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
4
4
|
const require_tls = require("../../tls-BxQlomxd.js");
|
|
5
5
|
let node_fs_promises = require("node:fs/promises");
|
|
6
6
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ft as BaseAddon, sn as EventCategory, st as localNetworkCapability } from "../../dist-
|
|
1
|
+
import { Ft as BaseAddon, sn as EventCategory, st as localNetworkCapability } from "../../dist-CVPtxkvV.mjs";
|
|
2
2
|
import { S as readLanHttpState, _ as DEFAULT_LAN_HTTP_PORT, a as writeTlsMode, i as writeExtraSans, l as reissueTlsLeaf, n as readTlsAccessStatus, o as validateUploadedTls, r as readTlsMode, s as ensureTlsCert, t as readExtraSans, y as applyLanHttp } from "../../tls-DOTmtLCW.mjs";
|
|
3
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
6
|
+
const require_dist = require("../../dist-D8VIyu_0.js");
|
|
7
7
|
//#region src/builtins/loki-logging/loki-payload.ts
|
|
8
8
|
/**
|
|
9
9
|
* Loki rejects a label name that is not a valid Prometheus label
|