@camstack/system 1.2.475 → 1.2.476
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/{agent-https-BsqT0qni.js → agent-https-DkXBXEvz.js} +1 -1
- package/dist/{agent-https-wA8gGLc1.mjs → agent-https-vpf_D97z.mjs} +1 -1
- 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/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer-live-set.d.ts +9 -1
- package/dist/builtins/composer/composer.addon.js +130 -11
- package/dist/builtins/composer/composer.addon.mjs +130 -11
- package/dist/builtins/composer/composer.d.ts +8 -1
- package/dist/builtins/composer/composition-runtime.d.ts +2 -0
- package/dist/builtins/composer/composition-target.d.ts +6 -0
- package/dist/builtins/composer/owned-fields-target.d.ts +9 -0
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/block-supervisor.d.ts +19 -1
- package/dist/builtins/core-blocks/composition-api.d.ts +7 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +108 -10
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +108 -10
- package/dist/builtins/device-history/device-history.addon.js +1 -1
- package/dist/builtins/device-history/device-history.addon.mjs +1 -1
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.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/keychain/index.js +3 -3
- package/dist/builtins/keychain/index.mjs +3 -3
- 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 +2 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +2 -2
- package/dist/builtins/local-network/local-network.addon.js +2 -2
- package/dist/builtins/local-network/local-network.addon.mjs +2 -2
- 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/record-entries/index.js +1 -1
- package/dist/builtins/record-entries/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/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
- 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 +3 -3
- package/dist/builtins/system-config/system-config.addon.mjs +3 -3
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-CiFkyAcf.mjs → composition-sources-B5nK7pHt.mjs} +1 -1
- package/dist/{composition-sources-DeUSUid6.js → composition-sources-BNOP9mFp.js} +1 -1
- package/dist/{constants-3Wj5OyEk.js → constants-D4VigrMM.js} +1 -1
- package/dist/{constants-DZJAkne8.mjs → constants-jbhoFV7w.mjs} +1 -1
- package/dist/{device-ca-DiV5xcMz.mjs → device-ca-CvBZeyVX.mjs} +1 -1
- package/dist/{device-ca-ftrfVdc0.js → device-ca-DhyQeXsa.js} +1 -1
- package/dist/{dist-DygMs3Qc.mjs → dist-B_V9r61Z.mjs} +21 -2
- package/dist/{dist-BtDdPdZ7.js → dist-CNU7cdFf.js} +21 -2
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-Bc9PnWu3.mjs → hub-mdns-ciao-BuUg0gpI.mjs} +2 -2
- package/dist/{hub-mdns-ciao-B1VcdfT1.js → hub-mdns-ciao-DFidf52M.js} +2 -2
- package/dist/index.js +7 -7
- package/dist/index.mjs +7 -7
- package/dist/{restore-archive-TDkQfmLO.js → restore-archive-BtCheeWu.js} +1 -1
- package/dist/{restore-archive-D_Pwryre.mjs → restore-archive-CDo4Zlmx.mjs} +1 -1
- package/dist/{wal-maintenance-D3UwIKX5.js → wal-maintenance-B7xBeIFi.js} +0 -0
- package/dist/{wal-maintenance-rLv4uOmp.mjs → wal-maintenance-DItlr0Yu.mjs} +0 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
2
|
-
const require_dist = require("./dist-
|
|
2
|
+
const require_dist = require("./dist-CNU7cdFf.js");
|
|
3
3
|
const require_x509_es = require("./x509.es-WtnRNyYS.js");
|
|
4
4
|
let zod = require("zod");
|
|
5
5
|
let node_crypto = require("node:crypto");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { qi as defineRecordKinds } from "./dist-
|
|
1
|
+
import { qi as defineRecordKinds } from "./dist-B_V9r61Z.mjs";
|
|
2
2
|
import { C as backdatedNotBefore, S as withUtcTimeEncoding, _ as NameConstraints, a as KeyUsageFlags, c as Pkcs10CertificateRequest, d as SubjectKeyIdentifierExtension, f as X509Certificate$1, g as GeneralSubtrees, h as GeneralSubtree, i as Extension, l as Pkcs10CertificateRequestGenerator, m as cryptoProvider, n as BasicConstraintsExtension, o as KeyUsagesExtension, p as X509CertificateGenerator, r as ExtendedKeyUsageExtension, s as PemConverter, t as AuthorityKeyIdentifierExtension, u as SubjectAlternativeNameExtension, v as GeneralName, x as AsnConvert } from "./x509.es-BRiJgOvu.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { X509Certificate, createHash, createPrivateKey, randomBytes, webcrypto } from "node:crypto";
|
|
@@ -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-CNU7cdFf.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Oa as EventCategory, _t as addonPagesCapability, ei as errMsg, ti as BaseAddon } from "../../dist-
|
|
1
|
+
import { Oa as EventCategory, _t as addonPagesCapability, ei as errMsg, ti as BaseAddon } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
@@ -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-CNU7cdFf.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let node_crypto = require("node:crypto");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Oa as EventCategory, ei as errMsg, ti as BaseAddon, yt as addonWidgetsCapability } from "../../dist-
|
|
1
|
+
import { Oa as EventCategory, ei as errMsg, ti as BaseAddon, yt as addonWidgetsCapability } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import * as path$1 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-CNU7cdFf.js");
|
|
7
7
|
const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
|
|
8
8
|
//#region src/builtins/alerts/alert-episode-policy.ts
|
|
9
9
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Oa as EventCategory, St as alertsCapability, Wi as createEvent, bn as isAlertEpisodeSeverity, bt as alertEpisodeId, ei as errMsg, i as AlertSchema, qi as defineRecordKinds, ti as BaseAddon, xt as alertEpisodePayload, yn as isAlertEpisodeOpen } from "../../dist-
|
|
1
|
+
import { Oa as EventCategory, St as alertsCapability, Wi as createEvent, bn as isAlertEpisodeSeverity, bt as alertEpisodeId, ei as errMsg, i as AlertSchema, qi as defineRecordKinds, ti as BaseAddon, xt as alertEpisodePayload, yn as isAlertEpisodeOpen } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
|
|
3
3
|
//#region src/builtins/alerts/alert-episode-policy.ts
|
|
4
4
|
/**
|
|
@@ -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-CNU7cdFf.js");
|
|
7
7
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
8
8
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
9
9
|
deadZoneFraction: .5,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Et as bareAddonId, I as FIRST_LEVEL_MACRO_CLASSES, Oa as EventCategory, ei as errMsg, nr as ptzAutotrackCapability, ta as isEvent, ti as BaseAddon } from "../../dist-
|
|
1
|
+
import { Et as bareAddonId, I as FIRST_LEVEL_MACRO_CLASSES, Oa as EventCategory, ei as errMsg, nr as ptzAutotrackCapability, ta as isEvent, ti as BaseAddon } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
//#region src/builtins/autotrack/autotrack-config.ts
|
|
3
3
|
var DEFAULT_AUTOTRACK_LOOP_CONFIG = {
|
|
4
4
|
deadZoneFraction: .5,
|
|
@@ -3,9 +3,9 @@ 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-CNU7cdFf.js");
|
|
7
7
|
const require_read_all_rows$1 = require("../../read-all-rows-CVoO1ONM.js");
|
|
8
|
-
const require_restore_archive = require("../../restore-archive-
|
|
8
|
+
const require_restore_archive = require("../../restore-archive-BtCheeWu.js");
|
|
9
9
|
let node_crypto = require("node:crypto");
|
|
10
10
|
let node_fs_promises = require("node:fs/promises");
|
|
11
11
|
node_fs_promises = require_chunk.__toESM(node_fs_promises);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Ca as toNodeId, Dr as storageOccupancyCapability, Oa as EventCategory, Tt as backupCapability, Vn as mayWriteToLocation, la as nodePin, ti as BaseAddon } from "../../dist-
|
|
1
|
+
import { Ca as toNodeId, Dr as storageOccupancyCapability, Oa as EventCategory, Tt as backupCapability, Vn as mayWriteToLocation, la as nodePin, ti as BaseAddon } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { t as require_read_all_rows } from "../../read-all-rows-TaPqdWNF.mjs";
|
|
3
|
-
import { _ as backupRecordStoresOf, a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, g as backupOrchestratorRecordKinds, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-
|
|
3
|
+
import { _ as backupRecordStoresOf, a as BackupSnapshotRefusedError, d as ENCRYPTED_BACKUP_SUFFIX, f as generateBackupKeyPair, g as backupOrchestratorRecordKinds, i as BackupCancelledError, l as BackupKeyFormatError, m as parseBackupSecretKey, n as precheckRestoreKey, o as DEFAULT_BACKUP_DATABASES, p as parseBackupPublicKey, r as prepareRestoreArchive, s as SystemBackupService } from "../../restore-archive-CDo4Zlmx.mjs";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import * as fsp from "node:fs/promises";
|
|
6
6
|
import * as path$1 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-CNU7cdFf.js");
|
|
7
7
|
const require_settle_sources = require("../../settle-sources-Bhsy57y-.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/builtins/calendars/calendar-color.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mt as calendarsCapability, g as CalendarPreferencesSchema, qi as defineRecordKinds, ti as BaseAddon } from "../../dist-
|
|
1
|
+
import { Mt as calendarsCapability, g as CalendarPreferencesSchema, qi as defineRecordKinds, ti as BaseAddon } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { t as settleSourcesWithTimeout } from "../../settle-sources-CDtNC8ub.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/builtins/calendars/calendar-color.ts
|
|
@@ -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-CNU7cdFf.js");
|
|
7
7
|
let zod = require("zod");
|
|
8
8
|
let _camstack_types_node = require("@camstack/types/node");
|
|
9
9
|
let node_path = require("node:path");
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $i as hydrateSchema, $r as DeviceType, Br as buildFfmpegArgs, Gn as motionCapability, Hn as memoizePinnedFfmpeg, N as DeclaredDevices, Nt as cameraGridLayoutCapability, Oa as EventCategory, Sr as snapshotCapability, T as DERIVED_CAMERA_SILENCED_CAP_NAMES, Wi as createEvent, X as MOTION_CLOSE_AFTER_MS, Zr as DeviceFeature, a as BaseDevice, ei as errMsg, kr as streamCatalogCapability, qt as declarationOwnerNodeId, ti as BaseAddon } from "../../dist-
|
|
1
|
+
import { $i as hydrateSchema, $r as DeviceType, Br as buildFfmpegArgs, Gn as motionCapability, Hn as memoizePinnedFfmpeg, N as DeclaredDevices, Nt as cameraGridLayoutCapability, Oa as EventCategory, Sr as snapshotCapability, T as DERIVED_CAMERA_SILENCED_CAP_NAMES, Wi as createEvent, X as MOTION_CLOSE_AFTER_MS, Zr as DeviceFeature, a as BaseDevice, ei as errMsg, kr as streamCatalogCapability, qt as declarationOwnerNodeId, ti as BaseAddon } from "../../dist-B_V9r61Z.mjs";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { FfmpegProcess } from "@camstack/types/node";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ClaimGate, type ClaimKey } from "./claim-gate.js";
|
|
2
2
|
import type { PlannedBlock } from "./composer-plan.js";
|
|
3
3
|
import type { LiveComposition } from "./composer-verdict.js";
|
|
4
4
|
import type { TrackedSourceRequest } from "./source-tracker.js";
|
|
@@ -20,3 +20,11 @@ export declare function trackedSourceRequests(live: Iterable<LiveComposition>):
|
|
|
20
20
|
* are. A disabled block wants none (rule 7).
|
|
21
21
|
*/
|
|
22
22
|
export declare function wantedClaims(live: ReadonlyMap<string, LiveComposition>, claimGate: Pick<ClaimGate, "claimsOf">): readonly ClaimKey[];
|
|
23
|
+
/**
|
|
24
|
+
* Claims an operator has already confirmed are no longer wanted: a deleted
|
|
25
|
+
* block (`retiredBlockIds`), or a cap an edit dropped. Released on this apply,
|
|
26
|
+
* not after a second one — a missing block in a single snapshot is still the
|
|
27
|
+
* two-apply gate (`wantedClaims`). A disabled block is not here: its runtime
|
|
28
|
+
* hands the fields back itself.
|
|
29
|
+
*/
|
|
30
|
+
export declare function confirmedReleaseKeys(retiredBlockIds: readonly string[], planned: readonly PlannedBlock[], previous: ReadonlyMap<string, LiveComposition>, claimGate: Pick<ClaimGate, "claimsOf">): readonly ClaimKey[];
|
|
@@ -3,8 +3,8 @@ Object.defineProperties(exports, {
|
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
5
|
require("../../chunk-Cek0wNdY.js");
|
|
6
|
-
const require_dist = require("../../dist-
|
|
7
|
-
const require_composition_sources = require("../../composition-sources-
|
|
6
|
+
const require_dist = require("../../dist-CNU7cdFf.js");
|
|
7
|
+
const require_composition_sources = require("../../composition-sources-BNOP9mFp.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/builtins/shared/device-state-changed.ts
|
|
10
10
|
/** Structural narrowing helper for untrusted bus payloads. */
|
|
@@ -793,6 +793,41 @@ function wantedClaims(live, claimGate) {
|
|
|
793
793
|
for (const owner of held) wanted.push(...claimGate.claimsOf(owner));
|
|
794
794
|
return wanted;
|
|
795
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* Claims an operator has already confirmed are no longer wanted: a deleted
|
|
798
|
+
* block (`retiredBlockIds`), or a cap an edit dropped. Released on this apply,
|
|
799
|
+
* not after a second one — a missing block in a single snapshot is still the
|
|
800
|
+
* two-apply gate (`wantedClaims`). A disabled block is not here: its runtime
|
|
801
|
+
* hands the fields back itself.
|
|
802
|
+
*/
|
|
803
|
+
function confirmedReleaseKeys(retiredBlockIds, planned, previous, claimGate) {
|
|
804
|
+
const retired = new Set(retiredBlockIds);
|
|
805
|
+
const seen = /* @__PURE__ */ new Set();
|
|
806
|
+
const keys = [];
|
|
807
|
+
const push = (key) => {
|
|
808
|
+
const id = claimKey(key);
|
|
809
|
+
if (seen.has(id)) return;
|
|
810
|
+
seen.add(id);
|
|
811
|
+
keys.push(key);
|
|
812
|
+
};
|
|
813
|
+
for (const owner of retired) for (const key of claimGate.claimsOf(owner)) push(key);
|
|
814
|
+
const plannedById = new Map(planned.map((block) => [block.block.id, block]));
|
|
815
|
+
for (const [blockId, entry] of previous) {
|
|
816
|
+
if (retired.has(blockId)) continue;
|
|
817
|
+
const next = plannedById.get(blockId);
|
|
818
|
+
if (next === void 0 || !next.block.enabled) continue;
|
|
819
|
+
if (entry.planned.block.updatedAt === next.block.updatedAt) continue;
|
|
820
|
+
for (const key of claimGate.claimsOf(blockId)) if (!planStillWantsClaim(next, key)) push(key);
|
|
821
|
+
}
|
|
822
|
+
return keys;
|
|
823
|
+
}
|
|
824
|
+
/** True when this plan still holds `key` — including while the plan cannot say, so a bad read releases nothing. */
|
|
825
|
+
function planStillWantsClaim(planned, key) {
|
|
826
|
+
const target = planned.target;
|
|
827
|
+
if (target.kind !== "existing") return false;
|
|
828
|
+
if (target.waiting !== null || target.gone !== null || target.deviceId === null || planned.problems.length > 0) return true;
|
|
829
|
+
return target.deviceId === key.deviceId && target.features.some((feature) => feature.cap === key.capName);
|
|
830
|
+
}
|
|
796
831
|
//#endregion
|
|
797
832
|
//#region src/builtins/composer/composition-declarations.ts
|
|
798
833
|
/**
|
|
@@ -1718,6 +1753,13 @@ var CompositionRuntime = class {
|
|
|
1718
1753
|
this.stopped = true;
|
|
1719
1754
|
this.deps.timer.disarm();
|
|
1720
1755
|
}
|
|
1756
|
+
/** `stop`, then wait until the target has sent nothing further. */
|
|
1757
|
+
quiesce() {
|
|
1758
|
+
this.stop();
|
|
1759
|
+
const quiesce = this.deps.target.quiesce;
|
|
1760
|
+
if (quiesce === void 0) return Promise.resolve();
|
|
1761
|
+
return quiesce.call(this.deps.target);
|
|
1762
|
+
}
|
|
1721
1763
|
state() {
|
|
1722
1764
|
return {
|
|
1723
1765
|
failure: this.failure,
|
|
@@ -2221,6 +2263,10 @@ var OwnedFieldsTarget = class {
|
|
|
2221
2263
|
listeners = [];
|
|
2222
2264
|
/** Per cap, bumped by every `withhold`: a claim that settles under another epoch claimed a stale field set and does not land (I-2). */
|
|
2223
2265
|
epoch = /* @__PURE__ */ new Map();
|
|
2266
|
+
/** Set by `quiesce`: nothing further is sent. */
|
|
2267
|
+
closed = false;
|
|
2268
|
+
idle = Promise.resolve();
|
|
2269
|
+
markIdle = null;
|
|
2224
2270
|
constructor(deps) {
|
|
2225
2271
|
this.deps = deps;
|
|
2226
2272
|
this.id = deps.deviceId;
|
|
@@ -2245,6 +2291,27 @@ var OwnedFieldsTarget = class {
|
|
|
2245
2291
|
}
|
|
2246
2292
|
/** `device-status` belongs to the native device; availability lives in the block report only. */
|
|
2247
2293
|
setAvailable(_available) {}
|
|
2294
|
+
/**
|
|
2295
|
+
* The block has stopped. Writes still queued are dropped; the call in flight
|
|
2296
|
+
* is allowed to finish, and then nothing else is sent.
|
|
2297
|
+
*/
|
|
2298
|
+
quiesce() {
|
|
2299
|
+
this.closed = true;
|
|
2300
|
+
const dropped = [...this.pending.keys()];
|
|
2301
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
2302
|
+
for (const cap of dropped) this.deps.logger.info("composed write dropped — the block stopped before it was sent", {
|
|
2303
|
+
tags: { deviceId: this.deps.deviceId },
|
|
2304
|
+
meta: {
|
|
2305
|
+
cap,
|
|
2306
|
+
owner: this.deps.owner
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
if (this.inFlight.size === 0) return Promise.resolve();
|
|
2310
|
+
if (this.markIdle === null) this.idle = new Promise((resolve) => {
|
|
2311
|
+
this.markIdle = resolve;
|
|
2312
|
+
});
|
|
2313
|
+
return this.idle;
|
|
2314
|
+
}
|
|
2248
2315
|
onAsyncFailure(listener) {
|
|
2249
2316
|
this.listeners = [...this.listeners, listener];
|
|
2250
2317
|
}
|
|
@@ -2260,6 +2327,17 @@ var OwnedFieldsTarget = class {
|
|
|
2260
2327
|
return this.deps.fieldsOf(cap).filter((f) => held === void 0 || !held.has(f));
|
|
2261
2328
|
}
|
|
2262
2329
|
enqueue(cap, op) {
|
|
2330
|
+
if (this.closed) {
|
|
2331
|
+
this.deps.logger.info("composed write dropped — the block stopped before it was sent", {
|
|
2332
|
+
tags: { deviceId: this.deps.deviceId },
|
|
2333
|
+
meta: {
|
|
2334
|
+
cap,
|
|
2335
|
+
owner: this.deps.owner,
|
|
2336
|
+
op: op.kind
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2339
|
+
return;
|
|
2340
|
+
}
|
|
2263
2341
|
if (!this.inFlight.has(cap)) {
|
|
2264
2342
|
this.send(cap, op);
|
|
2265
2343
|
return;
|
|
@@ -2282,6 +2360,11 @@ var OwnedFieldsTarget = class {
|
|
|
2282
2360
|
}
|
|
2283
2361
|
settled(cap) {
|
|
2284
2362
|
this.inFlight = new Set([...this.inFlight].filter((c) => c !== cap));
|
|
2363
|
+
if (this.closed) {
|
|
2364
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
2365
|
+
if (this.inFlight.size === 0) this.markIdle?.();
|
|
2366
|
+
return;
|
|
2367
|
+
}
|
|
2285
2368
|
const next = this.pending.get(cap);
|
|
2286
2369
|
if (next === void 0) return;
|
|
2287
2370
|
this.pending = new Map([...this.pending].filter(([c]) => c !== cap));
|
|
@@ -2698,7 +2781,11 @@ function verdictOf(blockId, entry, unsynced, grafts = null) {
|
|
|
2698
2781
|
* filter in `composer.addon.ts` stays load-bearing. Its fields are CLAIMED on
|
|
2699
2782
|
* the hub under the block id (`OwnedFieldsTarget`), and released through the
|
|
2700
2783
|
* `ClaimGate` — two applies must agree, seeded at boot from the claims index —
|
|
2701
|
-
* when the block
|
|
2784
|
+
* when the block merely vanished from one snapshot. An operator delete
|
|
2785
|
+
* (`retiredBlockIds`) or an edit that drops a cap releases those claims on
|
|
2786
|
+
* THIS apply, after the old runtime has quiesced and before any replacement
|
|
2787
|
+
* claims; a release that does not land is logged with `tags: { deviceId }` and
|
|
2788
|
+
* returned on the apply. Its own replaced
|
|
2702
2789
|
* fields are read in the NATIVE view (rule 6). Its target row gone on two
|
|
2703
2790
|
* agreeing index reads fails the block by name and ungrafts what it added —
|
|
2704
2791
|
* whether the loss was seen on `device.unregistered` or on a later plan; its
|
|
@@ -2846,12 +2933,16 @@ var Composer = class {
|
|
|
2846
2933
|
};
|
|
2847
2934
|
});
|
|
2848
2935
|
await this.composed.reconcile(gate.integrationId, declarations, planned);
|
|
2936
|
+
const releasing = confirmedReleaseKeys(input.retiredBlockIds ?? [], planned, this.live, this.claimGate);
|
|
2849
2937
|
const rebuilt = await this.rebuildRuntimes(planned, declarations, restart, rebuildErrors);
|
|
2938
|
+
await Promise.all(rebuilt.stopped.map((runtime) => runtime.quiesce()));
|
|
2939
|
+
const unreleasedClaims = await this.releaseConfirmed(releasing);
|
|
2850
2940
|
await this.syncSources(rebuilt);
|
|
2851
2941
|
await this.reconcileClaims();
|
|
2852
2942
|
return {
|
|
2853
2943
|
blocks: planned.map((p) => this.verdict(p.block.id)),
|
|
2854
|
-
acted: true
|
|
2944
|
+
acted: true,
|
|
2945
|
+
unreleasedClaims
|
|
2855
2946
|
};
|
|
2856
2947
|
}
|
|
2857
2948
|
plan(block, restart, claimsWait) {
|
|
@@ -2872,7 +2963,13 @@ var Composer = class {
|
|
|
2872
2963
|
async rebuildRuntimes(planned, declarations, restart, rebuildErrors) {
|
|
2873
2964
|
const reset = /* @__PURE__ */ new Set();
|
|
2874
2965
|
const fresh = /* @__PURE__ */ new Set();
|
|
2966
|
+
const stopped = [];
|
|
2875
2967
|
const next = /* @__PURE__ */ new Map();
|
|
2968
|
+
const halt = (runtime) => {
|
|
2969
|
+
if (runtime === null) return;
|
|
2970
|
+
runtime.stop();
|
|
2971
|
+
stopped.push(runtime);
|
|
2972
|
+
};
|
|
2876
2973
|
for (const p of planned) {
|
|
2877
2974
|
const previous = this.live.get(p.block.id);
|
|
2878
2975
|
const lost = lostTarget(p, previous?.planned);
|
|
@@ -2943,7 +3040,7 @@ var Composer = class {
|
|
|
2943
3040
|
enabled: p.block.enabled,
|
|
2944
3041
|
settled: p.problems.length === 0
|
|
2945
3042
|
});
|
|
2946
|
-
previous?.runtime
|
|
3043
|
+
halt(previous?.runtime ?? null);
|
|
2947
3044
|
if (runtime !== null) fresh.add(runtime);
|
|
2948
3045
|
next.set(p.block.id, {
|
|
2949
3046
|
planned: p,
|
|
@@ -2958,12 +3055,15 @@ var Composer = class {
|
|
|
2958
3055
|
for (const [blockId, entry] of this.live) {
|
|
2959
3056
|
if (next.has(blockId)) continue;
|
|
2960
3057
|
if (held.has(require_dist.composedDeviceStableId(blockId))) next.set(blockId, entry);
|
|
2961
|
-
else entry.runtime
|
|
3058
|
+
else halt(entry.runtime);
|
|
2962
3059
|
}
|
|
2963
3060
|
this.live = next;
|
|
2964
3061
|
const liveRuntimes = new Set([...next.values()].map((e) => e.runtime));
|
|
2965
3062
|
this.unsynced = new Set([...[...this.unsynced].filter((r) => liveRuntimes.has(r)), ...fresh]);
|
|
2966
|
-
return {
|
|
3063
|
+
return {
|
|
3064
|
+
reset,
|
|
3065
|
+
stopped
|
|
3066
|
+
};
|
|
2967
3067
|
}
|
|
2968
3068
|
ungraftGone(blockId, target, deviceId) {
|
|
2969
3069
|
this.grafts.gone(deviceId);
|
|
@@ -3047,21 +3147,40 @@ var Composer = class {
|
|
|
3047
3147
|
if (!this.claimSeed.done) return;
|
|
3048
3148
|
for (const key of this.claimGate.filter(wantedClaims(this.live, this.claimGate))) await this.release(key);
|
|
3049
3149
|
}
|
|
3150
|
+
/** Confirmed releases, awaited. A failure is the string the hub gave; the gate retries it later. */
|
|
3151
|
+
async releaseConfirmed(keys) {
|
|
3152
|
+
const unreleased = [];
|
|
3153
|
+
for (const key of keys) {
|
|
3154
|
+
const error = await this.release(key);
|
|
3155
|
+
if (error === null) continue;
|
|
3156
|
+
unreleased.push({
|
|
3157
|
+
deviceId: key.deviceId,
|
|
3158
|
+
capName: key.capName,
|
|
3159
|
+
owner: key.owner,
|
|
3160
|
+
error
|
|
3161
|
+
});
|
|
3162
|
+
}
|
|
3163
|
+
return unreleased;
|
|
3164
|
+
}
|
|
3165
|
+
/** Null when the hub confirmed the release (or held nothing of ours). */
|
|
3050
3166
|
async release(key) {
|
|
3051
3167
|
let outcome;
|
|
3052
3168
|
try {
|
|
3053
3169
|
outcome = await this.deps.claims.releaseClaim(key);
|
|
3054
3170
|
} catch (err) {
|
|
3055
|
-
|
|
3056
|
-
|
|
3171
|
+
const error = require_dist.errMsg(err);
|
|
3172
|
+
this.claimGate.releaseFailed(key, error);
|
|
3173
|
+
return error;
|
|
3057
3174
|
}
|
|
3058
3175
|
if (!outcome.ok && !RELEASE_SETTLED_CODES.has(outcome.code)) {
|
|
3059
|
-
|
|
3060
|
-
|
|
3176
|
+
const error = `${outcome.code}: ${outcome.message}`;
|
|
3177
|
+
this.claimGate.releaseFailed(key, error);
|
|
3178
|
+
return error;
|
|
3061
3179
|
}
|
|
3062
3180
|
this.claimGate.released(key, outcome.ok ? "released" : outcome.code);
|
|
3063
3181
|
await this.grafts.released(key.deviceId, key.capName);
|
|
3064
3182
|
await this.onClaimEvent(key.deviceId, key.capName, key.owner, "free");
|
|
3183
|
+
return null;
|
|
3065
3184
|
}
|
|
3066
3185
|
/**
|
|
3067
3186
|
* Rule 5: a customization whose target row is gone — the tracker's two
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $n as planComposition, $r as DeviceType, Gr as compositionItemFieldPath, Hr as composedDeviceRef, It as composerCapability, Jr as createStatefulExpressionMemory, Kr as compositionSliceKey, Lt as compositionFieldKey, N as DeclaredDevices, Oa as EventCategory, Ot as buildCapabilityLookup, Ur as composedDeviceStableId, Vr as cloneStatefulExpressionMemory, Wi as createEvent, Wr as compositionFeatureEnabled, Xr as toExpressionValue, Yr as disarmRoseMemory, a as BaseDevice, cn as evaluateCompositionField, d as COMPOSED_ITEM_FIXED_FIELDS, dn as expressionContainsBuiltinCall, ei as errMsg, qr as compositionSourceKey, r as ALL_CAPABILITY_DEFINITIONS, ti as BaseAddon, zr as COMPOSER_ADDON_ID } from "../../dist-
|
|
2
|
-
import { n as normalizedNativeOwner } from "../../composition-sources-
|
|
1
|
+
import { $n as planComposition, $r as DeviceType, Gr as compositionItemFieldPath, Hr as composedDeviceRef, It as composerCapability, Jr as createStatefulExpressionMemory, Kr as compositionSliceKey, Lt as compositionFieldKey, N as DeclaredDevices, Oa as EventCategory, Ot as buildCapabilityLookup, Ur as composedDeviceStableId, Vr as cloneStatefulExpressionMemory, Wi as createEvent, Wr as compositionFeatureEnabled, Xr as toExpressionValue, Yr as disarmRoseMemory, a as BaseDevice, cn as evaluateCompositionField, d as COMPOSED_ITEM_FIXED_FIELDS, dn as expressionContainsBuiltinCall, ei as errMsg, qr as compositionSourceKey, r as ALL_CAPABILITY_DEFINITIONS, ti as BaseAddon, zr as COMPOSER_ADDON_ID } from "../../dist-B_V9r61Z.mjs";
|
|
2
|
+
import { n as normalizedNativeOwner } from "../../composition-sources-B5nK7pHt.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/builtins/shared/device-state-changed.ts
|
|
5
5
|
/** Structural narrowing helper for untrusted bus payloads. */
|
|
@@ -788,6 +788,41 @@ function wantedClaims(live, claimGate) {
|
|
|
788
788
|
for (const owner of held) wanted.push(...claimGate.claimsOf(owner));
|
|
789
789
|
return wanted;
|
|
790
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Claims an operator has already confirmed are no longer wanted: a deleted
|
|
793
|
+
* block (`retiredBlockIds`), or a cap an edit dropped. Released on this apply,
|
|
794
|
+
* not after a second one — a missing block in a single snapshot is still the
|
|
795
|
+
* two-apply gate (`wantedClaims`). A disabled block is not here: its runtime
|
|
796
|
+
* hands the fields back itself.
|
|
797
|
+
*/
|
|
798
|
+
function confirmedReleaseKeys(retiredBlockIds, planned, previous, claimGate) {
|
|
799
|
+
const retired = new Set(retiredBlockIds);
|
|
800
|
+
const seen = /* @__PURE__ */ new Set();
|
|
801
|
+
const keys = [];
|
|
802
|
+
const push = (key) => {
|
|
803
|
+
const id = claimKey(key);
|
|
804
|
+
if (seen.has(id)) return;
|
|
805
|
+
seen.add(id);
|
|
806
|
+
keys.push(key);
|
|
807
|
+
};
|
|
808
|
+
for (const owner of retired) for (const key of claimGate.claimsOf(owner)) push(key);
|
|
809
|
+
const plannedById = new Map(planned.map((block) => [block.block.id, block]));
|
|
810
|
+
for (const [blockId, entry] of previous) {
|
|
811
|
+
if (retired.has(blockId)) continue;
|
|
812
|
+
const next = plannedById.get(blockId);
|
|
813
|
+
if (next === void 0 || !next.block.enabled) continue;
|
|
814
|
+
if (entry.planned.block.updatedAt === next.block.updatedAt) continue;
|
|
815
|
+
for (const key of claimGate.claimsOf(blockId)) if (!planStillWantsClaim(next, key)) push(key);
|
|
816
|
+
}
|
|
817
|
+
return keys;
|
|
818
|
+
}
|
|
819
|
+
/** True when this plan still holds `key` — including while the plan cannot say, so a bad read releases nothing. */
|
|
820
|
+
function planStillWantsClaim(planned, key) {
|
|
821
|
+
const target = planned.target;
|
|
822
|
+
if (target.kind !== "existing") return false;
|
|
823
|
+
if (target.waiting !== null || target.gone !== null || target.deviceId === null || planned.problems.length > 0) return true;
|
|
824
|
+
return target.deviceId === key.deviceId && target.features.some((feature) => feature.cap === key.capName);
|
|
825
|
+
}
|
|
791
826
|
//#endregion
|
|
792
827
|
//#region src/builtins/composer/composition-declarations.ts
|
|
793
828
|
/**
|
|
@@ -1713,6 +1748,13 @@ var CompositionRuntime = class {
|
|
|
1713
1748
|
this.stopped = true;
|
|
1714
1749
|
this.deps.timer.disarm();
|
|
1715
1750
|
}
|
|
1751
|
+
/** `stop`, then wait until the target has sent nothing further. */
|
|
1752
|
+
quiesce() {
|
|
1753
|
+
this.stop();
|
|
1754
|
+
const quiesce = this.deps.target.quiesce;
|
|
1755
|
+
if (quiesce === void 0) return Promise.resolve();
|
|
1756
|
+
return quiesce.call(this.deps.target);
|
|
1757
|
+
}
|
|
1716
1758
|
state() {
|
|
1717
1759
|
return {
|
|
1718
1760
|
failure: this.failure,
|
|
@@ -2216,6 +2258,10 @@ var OwnedFieldsTarget = class {
|
|
|
2216
2258
|
listeners = [];
|
|
2217
2259
|
/** Per cap, bumped by every `withhold`: a claim that settles under another epoch claimed a stale field set and does not land (I-2). */
|
|
2218
2260
|
epoch = /* @__PURE__ */ new Map();
|
|
2261
|
+
/** Set by `quiesce`: nothing further is sent. */
|
|
2262
|
+
closed = false;
|
|
2263
|
+
idle = Promise.resolve();
|
|
2264
|
+
markIdle = null;
|
|
2219
2265
|
constructor(deps) {
|
|
2220
2266
|
this.deps = deps;
|
|
2221
2267
|
this.id = deps.deviceId;
|
|
@@ -2240,6 +2286,27 @@ var OwnedFieldsTarget = class {
|
|
|
2240
2286
|
}
|
|
2241
2287
|
/** `device-status` belongs to the native device; availability lives in the block report only. */
|
|
2242
2288
|
setAvailable(_available) {}
|
|
2289
|
+
/**
|
|
2290
|
+
* The block has stopped. Writes still queued are dropped; the call in flight
|
|
2291
|
+
* is allowed to finish, and then nothing else is sent.
|
|
2292
|
+
*/
|
|
2293
|
+
quiesce() {
|
|
2294
|
+
this.closed = true;
|
|
2295
|
+
const dropped = [...this.pending.keys()];
|
|
2296
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
2297
|
+
for (const cap of dropped) this.deps.logger.info("composed write dropped — the block stopped before it was sent", {
|
|
2298
|
+
tags: { deviceId: this.deps.deviceId },
|
|
2299
|
+
meta: {
|
|
2300
|
+
cap,
|
|
2301
|
+
owner: this.deps.owner
|
|
2302
|
+
}
|
|
2303
|
+
});
|
|
2304
|
+
if (this.inFlight.size === 0) return Promise.resolve();
|
|
2305
|
+
if (this.markIdle === null) this.idle = new Promise((resolve) => {
|
|
2306
|
+
this.markIdle = resolve;
|
|
2307
|
+
});
|
|
2308
|
+
return this.idle;
|
|
2309
|
+
}
|
|
2243
2310
|
onAsyncFailure(listener) {
|
|
2244
2311
|
this.listeners = [...this.listeners, listener];
|
|
2245
2312
|
}
|
|
@@ -2255,6 +2322,17 @@ var OwnedFieldsTarget = class {
|
|
|
2255
2322
|
return this.deps.fieldsOf(cap).filter((f) => held === void 0 || !held.has(f));
|
|
2256
2323
|
}
|
|
2257
2324
|
enqueue(cap, op) {
|
|
2325
|
+
if (this.closed) {
|
|
2326
|
+
this.deps.logger.info("composed write dropped — the block stopped before it was sent", {
|
|
2327
|
+
tags: { deviceId: this.deps.deviceId },
|
|
2328
|
+
meta: {
|
|
2329
|
+
cap,
|
|
2330
|
+
owner: this.deps.owner,
|
|
2331
|
+
op: op.kind
|
|
2332
|
+
}
|
|
2333
|
+
});
|
|
2334
|
+
return;
|
|
2335
|
+
}
|
|
2258
2336
|
if (!this.inFlight.has(cap)) {
|
|
2259
2337
|
this.send(cap, op);
|
|
2260
2338
|
return;
|
|
@@ -2277,6 +2355,11 @@ var OwnedFieldsTarget = class {
|
|
|
2277
2355
|
}
|
|
2278
2356
|
settled(cap) {
|
|
2279
2357
|
this.inFlight = new Set([...this.inFlight].filter((c) => c !== cap));
|
|
2358
|
+
if (this.closed) {
|
|
2359
|
+
this.pending = /* @__PURE__ */ new Map();
|
|
2360
|
+
if (this.inFlight.size === 0) this.markIdle?.();
|
|
2361
|
+
return;
|
|
2362
|
+
}
|
|
2280
2363
|
const next = this.pending.get(cap);
|
|
2281
2364
|
if (next === void 0) return;
|
|
2282
2365
|
this.pending = new Map([...this.pending].filter(([c]) => c !== cap));
|
|
@@ -2693,7 +2776,11 @@ function verdictOf(blockId, entry, unsynced, grafts = null) {
|
|
|
2693
2776
|
* filter in `composer.addon.ts` stays load-bearing. Its fields are CLAIMED on
|
|
2694
2777
|
* the hub under the block id (`OwnedFieldsTarget`), and released through the
|
|
2695
2778
|
* `ClaimGate` — two applies must agree, seeded at boot from the claims index —
|
|
2696
|
-
* when the block
|
|
2779
|
+
* when the block merely vanished from one snapshot. An operator delete
|
|
2780
|
+
* (`retiredBlockIds`) or an edit that drops a cap releases those claims on
|
|
2781
|
+
* THIS apply, after the old runtime has quiesced and before any replacement
|
|
2782
|
+
* claims; a release that does not land is logged with `tags: { deviceId }` and
|
|
2783
|
+
* returned on the apply. Its own replaced
|
|
2697
2784
|
* fields are read in the NATIVE view (rule 6). Its target row gone on two
|
|
2698
2785
|
* agreeing index reads fails the block by name and ungrafts what it added —
|
|
2699
2786
|
* whether the loss was seen on `device.unregistered` or on a later plan; its
|
|
@@ -2841,12 +2928,16 @@ var Composer = class {
|
|
|
2841
2928
|
};
|
|
2842
2929
|
});
|
|
2843
2930
|
await this.composed.reconcile(gate.integrationId, declarations, planned);
|
|
2931
|
+
const releasing = confirmedReleaseKeys(input.retiredBlockIds ?? [], planned, this.live, this.claimGate);
|
|
2844
2932
|
const rebuilt = await this.rebuildRuntimes(planned, declarations, restart, rebuildErrors);
|
|
2933
|
+
await Promise.all(rebuilt.stopped.map((runtime) => runtime.quiesce()));
|
|
2934
|
+
const unreleasedClaims = await this.releaseConfirmed(releasing);
|
|
2845
2935
|
await this.syncSources(rebuilt);
|
|
2846
2936
|
await this.reconcileClaims();
|
|
2847
2937
|
return {
|
|
2848
2938
|
blocks: planned.map((p) => this.verdict(p.block.id)),
|
|
2849
|
-
acted: true
|
|
2939
|
+
acted: true,
|
|
2940
|
+
unreleasedClaims
|
|
2850
2941
|
};
|
|
2851
2942
|
}
|
|
2852
2943
|
plan(block, restart, claimsWait) {
|
|
@@ -2867,7 +2958,13 @@ var Composer = class {
|
|
|
2867
2958
|
async rebuildRuntimes(planned, declarations, restart, rebuildErrors) {
|
|
2868
2959
|
const reset = /* @__PURE__ */ new Set();
|
|
2869
2960
|
const fresh = /* @__PURE__ */ new Set();
|
|
2961
|
+
const stopped = [];
|
|
2870
2962
|
const next = /* @__PURE__ */ new Map();
|
|
2963
|
+
const halt = (runtime) => {
|
|
2964
|
+
if (runtime === null) return;
|
|
2965
|
+
runtime.stop();
|
|
2966
|
+
stopped.push(runtime);
|
|
2967
|
+
};
|
|
2871
2968
|
for (const p of planned) {
|
|
2872
2969
|
const previous = this.live.get(p.block.id);
|
|
2873
2970
|
const lost = lostTarget(p, previous?.planned);
|
|
@@ -2938,7 +3035,7 @@ var Composer = class {
|
|
|
2938
3035
|
enabled: p.block.enabled,
|
|
2939
3036
|
settled: p.problems.length === 0
|
|
2940
3037
|
});
|
|
2941
|
-
previous?.runtime
|
|
3038
|
+
halt(previous?.runtime ?? null);
|
|
2942
3039
|
if (runtime !== null) fresh.add(runtime);
|
|
2943
3040
|
next.set(p.block.id, {
|
|
2944
3041
|
planned: p,
|
|
@@ -2953,12 +3050,15 @@ var Composer = class {
|
|
|
2953
3050
|
for (const [blockId, entry] of this.live) {
|
|
2954
3051
|
if (next.has(blockId)) continue;
|
|
2955
3052
|
if (held.has(composedDeviceStableId(blockId))) next.set(blockId, entry);
|
|
2956
|
-
else entry.runtime
|
|
3053
|
+
else halt(entry.runtime);
|
|
2957
3054
|
}
|
|
2958
3055
|
this.live = next;
|
|
2959
3056
|
const liveRuntimes = new Set([...next.values()].map((e) => e.runtime));
|
|
2960
3057
|
this.unsynced = new Set([...[...this.unsynced].filter((r) => liveRuntimes.has(r)), ...fresh]);
|
|
2961
|
-
return {
|
|
3058
|
+
return {
|
|
3059
|
+
reset,
|
|
3060
|
+
stopped
|
|
3061
|
+
};
|
|
2962
3062
|
}
|
|
2963
3063
|
ungraftGone(blockId, target, deviceId) {
|
|
2964
3064
|
this.grafts.gone(deviceId);
|
|
@@ -3042,21 +3142,40 @@ var Composer = class {
|
|
|
3042
3142
|
if (!this.claimSeed.done) return;
|
|
3043
3143
|
for (const key of this.claimGate.filter(wantedClaims(this.live, this.claimGate))) await this.release(key);
|
|
3044
3144
|
}
|
|
3145
|
+
/** Confirmed releases, awaited. A failure is the string the hub gave; the gate retries it later. */
|
|
3146
|
+
async releaseConfirmed(keys) {
|
|
3147
|
+
const unreleased = [];
|
|
3148
|
+
for (const key of keys) {
|
|
3149
|
+
const error = await this.release(key);
|
|
3150
|
+
if (error === null) continue;
|
|
3151
|
+
unreleased.push({
|
|
3152
|
+
deviceId: key.deviceId,
|
|
3153
|
+
capName: key.capName,
|
|
3154
|
+
owner: key.owner,
|
|
3155
|
+
error
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
return unreleased;
|
|
3159
|
+
}
|
|
3160
|
+
/** Null when the hub confirmed the release (or held nothing of ours). */
|
|
3045
3161
|
async release(key) {
|
|
3046
3162
|
let outcome;
|
|
3047
3163
|
try {
|
|
3048
3164
|
outcome = await this.deps.claims.releaseClaim(key);
|
|
3049
3165
|
} catch (err) {
|
|
3050
|
-
|
|
3051
|
-
|
|
3166
|
+
const error = errMsg(err);
|
|
3167
|
+
this.claimGate.releaseFailed(key, error);
|
|
3168
|
+
return error;
|
|
3052
3169
|
}
|
|
3053
3170
|
if (!outcome.ok && !RELEASE_SETTLED_CODES.has(outcome.code)) {
|
|
3054
|
-
|
|
3055
|
-
|
|
3171
|
+
const error = `${outcome.code}: ${outcome.message}`;
|
|
3172
|
+
this.claimGate.releaseFailed(key, error);
|
|
3173
|
+
return error;
|
|
3056
3174
|
}
|
|
3057
3175
|
this.claimGate.released(key, outcome.ok ? "released" : outcome.code);
|
|
3058
3176
|
await this.grafts.released(key.deviceId, key.capName);
|
|
3059
3177
|
await this.onClaimEvent(key.deviceId, key.capName, key.owner, "free");
|
|
3178
|
+
return null;
|
|
3060
3179
|
}
|
|
3061
3180
|
/**
|
|
3062
3181
|
* Rule 5: a customization whose target row is gone — the tracker's two
|